[Wincairo] Add support for context menus to non-legacy minibrowser
[WebKit-https.git] / Source / WebKit / UIProcess / win / WebView.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebView.h"
29
30 #include "APIPageConfiguration.h"
31 #include "DrawingAreaProxyImpl.h"
32 #include "Logging.h"
33 #include "NativeWebKeyboardEvent.h"
34 #include "NativeWebMouseEvent.h"
35 #include "NativeWebWheelEvent.h"
36 #include "WKAPICast.h"
37 #include "WebContextMenuProxyWin.h"
38 #include "WebEditCommandProxy.h"
39 #include "WebEventFactory.h"
40 #include "WebPageProxy.h"
41 #include "WebProcessPool.h"
42 #include <Commctrl.h>
43 #include <WebCore/BitmapInfo.h>
44 #include <WebCore/Cursor.h>
45 #include <WebCore/Editor.h>
46 #include <WebCore/FileSystem.h>
47 #include <WebCore/FloatRect.h>
48 #include <WebCore/HWndDC.h>
49 #include <WebCore/IntRect.h>
50 #include <WebCore/NotImplemented.h>
51 #include <WebCore/Region.h>
52 #include <WebCore/WebCoreInstanceHandle.h>
53 #include <WebCore/WindowMessageBroadcaster.h>
54 #include <WebCore/WindowsTouch.h>
55 #include <cairo-win32.h>
56 #include <cairo.h>
57 #include <wtf/SoftLinking.h>
58 #include <wtf/text/StringBuffer.h>
59 #include <wtf/text/StringBuilder.h>
60 #include <wtf/text/WTFString.h>
61
62 using namespace WebCore;
63
64 namespace WebKit {
65
66 static const LPCWSTR kWebKit2WebViewWindowClassName = L"WebKit2WebViewWindowClass";
67
68 static const int kMaxToolTipWidth = 250;
69
70 enum {
71     UpdateActiveStateTimer = 1,
72 };
73
74 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
75 {
76     LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
77
78     if (WebView* webView = reinterpret_cast<WebView*>(longPtr))
79         return webView->wndProc(hWnd, message, wParam, lParam);
80
81     if (message == WM_CREATE) {
82         LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
83
84         // Associate the WebView with the window.
85         ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
86         return 0;
87     }
88
89     return ::DefWindowProc(hWnd, message, wParam, lParam);
90 }
91
92 LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
93 {
94     LRESULT lResult = 0;
95     bool handled = true;
96
97     switch (message) {
98     case WM_CLOSE:
99         m_page->tryClose();
100         break;
101     case WM_DESTROY:
102         m_isBeingDestroyed = true;
103         close();
104         break;
105     case WM_ERASEBKGND:
106         lResult = 1;
107         break;
108     case WM_PAINT:
109         lResult = onPaintEvent(hWnd, message, wParam, lParam, handled);
110         break;
111     case WM_PRINTCLIENT:
112         lResult = onPrintClientEvent(hWnd, message, wParam, lParam, handled);
113         break;
114     case WM_MOUSEACTIVATE:
115         setWasActivatedByMouseEvent(true);
116         handled = false;
117         break;
118     case WM_MOUSEMOVE:
119     case WM_LBUTTONDOWN:
120     case WM_MBUTTONDOWN:
121     case WM_RBUTTONDOWN:
122     case WM_LBUTTONDBLCLK:
123     case WM_MBUTTONDBLCLK:
124     case WM_RBUTTONDBLCLK:
125     case WM_LBUTTONUP:
126     case WM_MBUTTONUP:
127     case WM_RBUTTONUP:
128     case WM_MOUSELEAVE:
129         lResult = onMouseEvent(hWnd, message, wParam, lParam, handled);
130         break;
131     case WM_MOUSEWHEEL:
132         lResult = onWheelEvent(hWnd, message, wParam, lParam, handled);
133         break;
134     case WM_HSCROLL:
135         lResult = onHorizontalScroll(hWnd, message, wParam, lParam, handled);
136         break;
137     case WM_VSCROLL:
138         lResult = onVerticalScroll(hWnd, message, wParam, lParam, handled);
139         break;
140     case WM_SYSKEYDOWN:
141     case WM_KEYDOWN:
142     case WM_SYSCHAR:
143     case WM_CHAR:
144     case WM_SYSKEYUP:
145     case WM_KEYUP:
146         lResult = onKeyEvent(hWnd, message, wParam, lParam, handled);
147         break;
148     case WM_SIZE:
149         lResult = onSizeEvent(hWnd, message, wParam, lParam, handled);
150         break;
151     case WM_WINDOWPOSCHANGED:
152         lResult = onWindowPositionChangedEvent(hWnd, message, wParam, lParam, handled);
153         break;
154     case WM_SETFOCUS:
155         lResult = onSetFocusEvent(hWnd, message, wParam, lParam, handled);
156         break;
157     case WM_KILLFOCUS:
158         lResult = onKillFocusEvent(hWnd, message, wParam, lParam, handled);
159         break;
160     case WM_TIMER:
161         lResult = onTimerEvent(hWnd, message, wParam, lParam, handled);
162         break;
163     case WM_SHOWWINDOW:
164         lResult = onShowWindowEvent(hWnd, message, wParam, lParam, handled);
165         break;
166     case WM_SETCURSOR:
167         lResult = onSetCursor(hWnd, message, wParam, lParam, handled);
168         break;
169     case WM_MENUCOMMAND:
170         lResult = onMenuCommand(hWnd, message, wParam, lParam, handled);
171         break;
172     default:
173         handled = false;
174         break;
175     }
176
177     if (!handled)
178         lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
179
180     return lResult;
181 }
182
183 bool WebView::registerWebViewWindowClass()
184 {
185     static bool haveRegisteredWindowClass = false;
186     if (haveRegisteredWindowClass)
187         return true;
188     haveRegisteredWindowClass = true;
189
190     WNDCLASSEX wcex;
191
192     wcex.cbSize = sizeof(WNDCLASSEX);
193     wcex.style = CS_DBLCLKS;
194     wcex.lpfnWndProc = WebView::WebViewWndProc;
195     wcex.cbClsExtra = 0;
196     wcex.cbWndExtra = sizeof(WebView*);
197     wcex.hInstance = instanceHandle();
198     wcex.hIcon = 0;
199     wcex.hCursor = ::LoadCursor(0, IDC_ARROW);
200     wcex.hbrBackground = 0;
201     wcex.lpszMenuName = 0;
202     wcex.lpszClassName = kWebKit2WebViewWindowClassName;
203     wcex.hIconSm = 0;
204
205     return !!::RegisterClassEx(&wcex);
206 }
207
208 WebView::WebView(RECT rect, const API::PageConfiguration& configuration, HWND parentWindow)
209     : m_pageClient(std::make_unique<PageClientImpl>(*this))
210 {
211     registerWebViewWindowClass();
212
213     m_window = ::CreateWindowExW(0, kWebKit2WebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE,
214         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, parentWindow ? parentWindow : HWND_MESSAGE, 0, instanceHandle(), this);
215     ASSERT(::IsWindow(m_window));
216     // We only check our window style, and not ::IsWindowVisible, because m_isVisible only tracks
217     // this window's visibility status, while ::IsWindowVisible takes our ancestors' visibility
218     // status into account. <http://webkit.org/b/54104>
219     ASSERT(m_isVisible == static_cast<bool>(::GetWindowLong(m_window, GWL_STYLE) & WS_VISIBLE));
220
221     auto pageConfiguration = configuration.copy();
222     WebProcessPool* processPool = pageConfiguration->processPool();
223     m_page = processPool->createWebPage(*m_pageClient, WTFMove(pageConfiguration));
224     m_page->initializeWebPage();
225
226     if (m_page->drawingArea())
227         m_page->drawingArea()->setSize(IntSize(rect.right - rect.left, rect.bottom - rect.top));
228
229     // FIXME: Initializing the tooltip window here matches WebKit win, but seems like something
230     // we could do on demand to save resources.
231     initializeToolTipWindow();
232
233     // Initialize the top level parent window and register it with the WindowMessageBroadcaster.
234     windowAncestryDidChange();
235 }
236
237 WebView::~WebView()
238 {
239     // Tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD.
240     if (::IsWindow(m_toolTipWindow))
241         ::DestroyWindow(m_toolTipWindow);
242 }
243
244 void WebView::initialize()
245 {
246     if (shouldInitializeTrackPointHack()) {
247         // If we detected a registry key belonging to a TrackPoint driver, then create fake
248         // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages.
249         // We create an invisible vertical scrollbar and an invisible horizontal scrollbar to allow
250         // for receiving both types of messages.
251         ::CreateWindow(TEXT("SCROLLBAR"), TEXT("FAKETRACKPOINTHSCROLLBAR"), WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_window, 0, instanceHandle(), 0);
252         ::CreateWindow(TEXT("SCROLLBAR"), TEXT("FAKETRACKPOINTVSCROLLBAR"), WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_window, 0, instanceHandle(), 0);
253     }
254 }
255
256 void WebView::setParentWindow(HWND parentWindow)
257 {
258     if (m_window) {
259         // If the host window hasn't changed, bail.
260         if (::GetParent(m_window) == parentWindow)
261             return;
262         if (parentWindow)
263             ::SetParent(m_window, parentWindow);
264         else if (!m_isBeingDestroyed) {
265             // Turn the WebView into a message-only window so it will no longer be a child of the
266             // old parent window and will be hidden from screen. We only do this when
267             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
268             // m_window in a weird state (see <http://webkit.org/b/29337>).
269             ::SetParent(m_window, HWND_MESSAGE);
270         }
271     }
272
273     windowAncestryDidChange();
274 }
275
276 static HWND findTopLevelParentWindow(HWND window)
277 {
278     if (!window)
279         return 0;
280
281     HWND current = window;
282     for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent)) {
283         if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
284             return current;
285     }
286     ASSERT_NOT_REACHED();
287     return 0;
288 }
289
290 void WebView::windowAncestryDidChange()
291 {
292     HWND newTopLevelParentWindow;
293     if (m_window)
294         newTopLevelParentWindow = findTopLevelParentWindow(m_window);
295     else {
296         // There's no point in tracking active state changes of our parent window if we don't have
297         // a window ourselves.
298         newTopLevelParentWindow = 0;
299     }
300
301     if (newTopLevelParentWindow == m_topLevelParentWindow)
302         return;
303
304     if (m_topLevelParentWindow)
305         WindowMessageBroadcaster::removeListener(m_topLevelParentWindow, this);
306
307     m_topLevelParentWindow = newTopLevelParentWindow;
308
309     if (m_topLevelParentWindow)
310         WindowMessageBroadcaster::addListener(m_topLevelParentWindow, this);
311
312     updateActiveState();
313 }
314
315 LRESULT WebView::onMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
316 {
317     NativeWebMouseEvent mouseEvent = NativeWebMouseEvent(hWnd, message, wParam, lParam, m_wasActivatedByMouseEvent);
318     setWasActivatedByMouseEvent(false);
319
320     switch (message) {
321     case WM_LBUTTONDOWN:
322     case WM_MBUTTONDOWN:
323     case WM_RBUTTONDOWN:
324         ::SetFocus(m_window);
325         ::SetCapture(m_window);
326         break;
327     case WM_LBUTTONUP:
328     case WM_MBUTTONUP:
329     case WM_RBUTTONUP:
330         ::ReleaseCapture();
331         break;
332     case WM_MOUSEMOVE:
333         startTrackingMouseLeave();
334         break;
335     case WM_MOUSELEAVE:
336         stopTrackingMouseLeave();
337         break;
338     case WM_LBUTTONDBLCLK:
339     case WM_MBUTTONDBLCLK:
340     case WM_RBUTTONDBLCLK:
341         break;
342     default:
343         ASSERT_NOT_REACHED();
344     }
345
346     m_page->handleMouseEvent(mouseEvent);
347
348     handled = true;
349     return 0;
350 }
351
352 LRESULT WebView::onWheelEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
353 {
354     NativeWebWheelEvent wheelEvent(hWnd, message, wParam, lParam);
355     if (wheelEvent.controlKey()) {
356         // We do not want WebKit to handle Control + Wheel, this should be handled by the client application
357         // to zoom the page.
358         handled = false;
359         return 0;
360     }
361
362     m_page->handleWheelEvent(wheelEvent);
363
364     handled = true;
365     return 0;
366 }
367
368 LRESULT WebView::onHorizontalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
369 {
370     ScrollDirection direction;
371     ScrollGranularity granularity;
372     switch (LOWORD(wParam)) {
373     case SB_LINELEFT:
374         granularity = ScrollByLine;
375         direction = ScrollLeft;
376         break;
377     case SB_LINERIGHT:
378         granularity = ScrollByLine;
379         direction = ScrollRight;
380         break;
381     case SB_PAGELEFT:
382         granularity = ScrollByDocument;
383         direction = ScrollLeft;
384         break;
385     case SB_PAGERIGHT:
386         granularity = ScrollByDocument;
387         direction = ScrollRight;
388         break;
389     default:
390         handled = false;
391         return 0;
392     }
393
394     m_page->scrollBy(direction, granularity);
395
396     handled = true;
397     return 0;
398 }
399
400 LRESULT WebView::onVerticalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
401 {
402     ScrollDirection direction;
403     ScrollGranularity granularity;
404     switch (LOWORD(wParam)) {
405     case SB_LINEDOWN:
406         granularity = ScrollByLine;
407         direction = ScrollDown;
408         break;
409     case SB_LINEUP:
410         granularity = ScrollByLine;
411         direction = ScrollUp;
412         break;
413     case SB_PAGEDOWN:
414         granularity = ScrollByDocument;
415         direction = ScrollDown;
416         break;
417     case SB_PAGEUP:
418         granularity = ScrollByDocument;
419         direction = ScrollUp;
420         break;
421     default:
422         handled = false;
423         return 0;
424     }
425
426     m_page->scrollBy(direction, granularity);
427
428     handled = true;
429     return 0;
430 }
431
432 LRESULT WebView::onKeyEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
433 {
434     m_page->handleKeyboardEvent(NativeWebKeyboardEvent(hWnd, message, wParam, lParam));
435
436     // We claim here to always have handled the event. If the event is not in fact handled, we will
437     // find out later in didNotHandleKeyEvent.
438     handled = true;
439     return 0;
440 }
441
442 static void drawPageBackground(HDC dc, const WebPageProxy* page, const RECT& rect)
443 {
444     if (!page->drawsBackground())
445         return;
446
447     ::FillRect(dc, &rect, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
448 }
449
450 void WebView::paint(HDC hdc, const IntRect& dirtyRect)
451 {
452     if (dirtyRect.isEmpty())
453         return;
454     m_page->endPrinting();
455     if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(m_page->drawingArea())) {
456         // FIXME: We should port WebKit1's rect coalescing logic here.
457         Region unpaintedRegion;
458         cairo_surface_t* surface = cairo_win32_surface_create(hdc);
459         cairo_t* context = cairo_create(surface);
460
461         drawingArea->paint(context, dirtyRect, unpaintedRegion);
462
463         cairo_destroy(context);
464         cairo_surface_destroy(surface);
465
466         Vector<IntRect> unpaintedRects = unpaintedRegion.rects();
467         for (size_t i = 0; i < unpaintedRects.size(); ++i) {
468             RECT winRect = unpaintedRects[i];
469             drawPageBackground(hdc, m_page.get(), unpaintedRects[i]);
470         }
471     } else
472         drawPageBackground(hdc, m_page.get(), dirtyRect);
473 }
474
475 LRESULT WebView::onPaintEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled)
476 {
477     // Update child windows now so that any areas of our window they reveal will be included in the
478     // invalid region that ::BeginPaint sees.
479
480     PAINTSTRUCT paintStruct;
481     HDC hdc = ::BeginPaint(m_window, &paintStruct);
482     paint(hdc, paintStruct.rcPaint);
483
484     ::EndPaint(m_window, &paintStruct);
485
486     handled = true;
487     return 0;
488 }
489
490 LRESULT WebView::onPrintClientEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
491 {
492     HDC hdc = reinterpret_cast<HDC>(wParam);
493     RECT winRect;
494     ::GetClientRect(hWnd, &winRect);
495
496     paint(hdc, winRect);
497
498     handled = true;
499     return 0;
500 }
501
502 LRESULT WebView::onSizeEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
503 {
504     int width = LOWORD(lParam);
505     int height = HIWORD(lParam);
506
507     if (m_page && m_page->drawingArea()) {
508         // FIXME specify correctly layerPosition.
509         m_page->drawingArea()->setSize(IntSize(width, height), m_nextResizeScrollOffset);
510         m_nextResizeScrollOffset = IntSize();
511     }
512
513     handled = true;
514     return 0;
515 }
516
517 LRESULT WebView::onWindowPositionChangedEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
518 {
519     if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
520         updateActiveStateSoon();
521
522     handled = false;
523     return 0;
524 }
525
526 LRESULT WebView::onSetFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
527 {
528     m_page->activityStateDidChange(ActivityState::IsFocused);
529     handled = true;
530     return 0;
531 }
532
533 LRESULT WebView::onKillFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
534 {
535     m_page->activityStateDidChange(ActivityState::IsFocused);
536     handled = true;
537     return 0;
538 }
539
540 LRESULT WebView::onTimerEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
541 {
542     switch (wParam) {
543     case UpdateActiveStateTimer:
544         ::KillTimer(hWnd, UpdateActiveStateTimer);
545         updateActiveState();
546         break;
547     }
548
549     handled = true;
550     return 0;
551 }
552
553 LRESULT WebView::onShowWindowEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
554 {
555     // lParam is 0 when the message is sent because of a ShowWindow call.
556     // FIXME: Since we don't get notified when an ancestor window is hidden or shown, we will keep
557     // painting even when we have a hidden ancestor. <http://webkit.org/b/54104>
558     if (!lParam)
559         setIsVisible(wParam);
560
561     handled = false;
562     return 0;
563 }
564
565 LRESULT WebView::onSetCursor(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
566 {
567     if (!m_lastCursorSet) {
568         handled = false;
569         return 0;
570     }
571
572     ::SetCursor(m_lastCursorSet);
573     return 0;
574 }
575
576 LRESULT WebView::onMenuCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
577 {
578     auto hMenu = reinterpret_cast<HMENU>(lParam);
579     auto index = static_cast<unsigned>(wParam);
580
581     MENUITEMINFO menuItemInfo;
582     menuItemInfo.cbSize = sizeof(menuItemInfo);
583     menuItemInfo.cch = 0;
584     menuItemInfo.fMask = MIIM_STRING;
585     ::GetMenuItemInfo(hMenu, index, TRUE, &menuItemInfo);
586
587     menuItemInfo.cch++;
588     Vector<WCHAR> buffer(menuItemInfo.cch);
589     menuItemInfo.dwTypeData = buffer.data();
590     menuItemInfo.fMask |= MIIM_ID;
591
592     ::GetMenuItemInfo(hMenu, index, TRUE, &menuItemInfo);
593
594     String title(buffer.data(), menuItemInfo.cch);
595     ContextMenuAction action = static_cast<ContextMenuAction>(menuItemInfo.wID);
596     bool enabled = !(menuItemInfo.fState & MFS_DISABLED);
597     bool checked = menuItemInfo.fState & MFS_CHECKED;
598     WebContextMenuItemData item(ContextMenuItemType::ActionType, action, title, enabled, checked);
599     m_page->contextMenuItemSelected(item);
600
601     handled = true;
602     return 0;
603 }
604
605 void WebView::updateActiveState()
606 {
607     m_page->activityStateDidChange(ActivityState::WindowIsActive);
608 }
609
610 void WebView::updateActiveStateSoon()
611 {
612     // This function is called while processing the WM_NCACTIVATE message.
613     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
614     // still return our window. If we were to call updateActiveState() in that case, we would
615     // wrongly think that we are still the active window. To work around this, we update our
616     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
617     // the newly-activated window.
618
619     ::SetTimer(m_window, UpdateActiveStateTimer, 0, 0);
620 }
621
622 static bool initCommonControls()
623 {
624     static bool haveInitialized = false;
625     if (haveInitialized)
626         return true;
627
628     INITCOMMONCONTROLSEX init;
629     init.dwSize = sizeof(init);
630     init.dwICC = ICC_TREEVIEW_CLASSES;
631     haveInitialized = !!::InitCommonControlsEx(&init);
632     return haveInitialized;
633 }
634
635 void WebView::initializeToolTipWindow()
636 {
637     if (!initCommonControls())
638         return;
639
640     m_toolTipWindow = ::CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
641         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
642         m_window, 0, 0, 0);
643     if (!m_toolTipWindow)
644         return;
645
646     TOOLINFO info = { 0 };
647     info.cbSize = sizeof(info);
648     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
649     info.uId = reinterpret_cast<UINT_PTR>(m_window);
650
651     ::SendMessage(m_toolTipWindow, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
652     ::SendMessage(m_toolTipWindow, TTM_SETMAXTIPWIDTH, 0, kMaxToolTipWidth);
653     ::SetWindowPos(m_toolTipWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
654 }
655
656 void WebView::startTrackingMouseLeave()
657 {
658     if (m_trackingMouseLeave)
659         return;
660     m_trackingMouseLeave = true;
661
662     TRACKMOUSEEVENT trackMouseEvent;
663     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
664     trackMouseEvent.dwFlags = TME_LEAVE;
665     trackMouseEvent.hwndTrack = m_window;
666
667     ::TrackMouseEvent(&trackMouseEvent);
668 }
669
670 void WebView::stopTrackingMouseLeave()
671 {
672     if (!m_trackingMouseLeave)
673         return;
674     m_trackingMouseLeave = false;
675
676     TRACKMOUSEEVENT trackMouseEvent;
677     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
678     trackMouseEvent.dwFlags = TME_LEAVE | TME_CANCEL;
679     trackMouseEvent.hwndTrack = m_window;
680
681     ::TrackMouseEvent(&trackMouseEvent);
682 }
683
684 bool WebView::shouldInitializeTrackPointHack()
685 {
686     static bool shouldCreateScrollbars;
687     static bool hasRunTrackPointCheck;
688
689     if (hasRunTrackPointCheck)
690         return shouldCreateScrollbars;
691
692     hasRunTrackPointCheck = true;
693     const wchar_t* trackPointKeys[] = {
694         L"Software\\Lenovo\\TrackPoint",
695         L"Software\\Lenovo\\UltraNav",
696         L"Software\\Alps\\Apoint\\TrackPoint",
697         L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
698         L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2"
699     };
700
701     for (size_t i = 0; i < WTF_ARRAY_LENGTH(trackPointKeys); ++i) {
702         HKEY trackPointKey;
703         int readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey);
704         ::RegCloseKey(trackPointKey);
705         if (readKeyResult == ERROR_SUCCESS) {
706             shouldCreateScrollbars = true;
707             return shouldCreateScrollbars;
708         }
709     }
710
711     return shouldCreateScrollbars;
712 }
713
714 void WebView::close()
715 {
716     if (m_window) {
717         // We can't check IsWindow(m_window) here, because that will return true even while
718         // we're already handling WM_DESTROY. So we check !m_isBeingDestroyed instead.
719         if (!m_isBeingDestroyed)
720             DestroyWindow(m_window);
721         // Either we just destroyed m_window, or it's in the process of being destroyed. Either
722         // way, we clear it out to make sure we don't try to use it later.
723         m_window = 0;
724     }
725     setParentWindow(0);
726     m_page->close();
727 }
728
729 HCURSOR WebView::cursorToShow() const
730 {
731     if (!m_page->isValid())
732         return 0;
733
734     // We only show the override cursor if the default (arrow) cursor is showing.
735     static HCURSOR arrowCursor = ::LoadCursor(0, IDC_ARROW);
736     if (m_overrideCursor && m_webCoreCursor == arrowCursor)
737         return m_overrideCursor;
738
739     return m_webCoreCursor;
740 }
741
742 void WebView::updateNativeCursor()
743 {
744     m_lastCursorSet = cursorToShow();
745     if (!m_lastCursorSet)
746         return;
747     ::SetCursor(m_lastCursorSet);
748 }
749
750 void WebView::setOverrideCursor(HCURSOR overrideCursor)
751 {
752     m_overrideCursor = overrideCursor;
753     updateNativeCursor();
754 }
755
756 void WebView::setIsInWindow(bool isInWindow)
757 {
758     m_isInWindow = isInWindow;
759     if (m_page)
760         m_page->activityStateDidChange(ActivityState::IsInWindow);
761 }
762
763 void WebView::setIsVisible(bool isVisible)
764 {
765     m_isVisible = isVisible;
766     if (m_page)
767         m_page->activityStateDidChange(ActivityState::IsVisible);
768 }
769
770 bool WebView::isWindowActive()
771 {
772     HWND activeWindow = ::GetActiveWindow();
773     return (activeWindow && m_topLevelParentWindow == findTopLevelParentWindow(activeWindow));
774 }
775
776 bool WebView::isFocused()
777 {
778     return ::GetFocus() == m_window;
779 }
780
781 bool WebView::isVisible()
782 {
783     return m_isVisible;
784 }
785
786 bool WebView::isInWindow()
787 {
788     return m_isInWindow;
789 }
790
791 void WebView::setScrollOffsetOnNextResize(const IntSize& scrollOffset)
792 {
793     // The next time we get a WM_SIZE message, scroll by the specified amount in onSizeEvent().
794     m_nextResizeScrollOffset = scrollOffset;
795 }
796
797 void WebView::setViewNeedsDisplay(const WebCore::Region& region)
798 {
799     const RECT r = region.bounds();
800     ::InvalidateRect(m_window, &r, true);
801 }
802
803 #if ENABLE(INPUT_TYPE_COLOR)
804 PassRefPtr<WebColorChooserProxy> WebView::createColorChooserProxy(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&)
805 {
806     notImplemented();
807     return 0;
808 }
809 #endif
810
811 void WebView::didCommitLoadForMainFrame(bool useCustomRepresentation)
812 {
813 }
814
815 double WebView::customRepresentationZoomFactor()
816 {
817     return 1;
818 }
819
820 void WebView::setCustomRepresentationZoomFactor(double)
821 {
822 }
823
824 void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned)
825 {
826 }
827
828 void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned)
829 {
830 }
831
832 HWND WebView::nativeWindow()
833 {
834     return m_window;
835 }
836
837 // WebCore::WindowMessageListener
838
839 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
840 {
841     switch (message) {
842     case WM_NCACTIVATE:
843         updateActiveStateSoon();
844         break;
845     case WM_SETTINGCHANGE:
846         break;
847     }
848 }
849
850 } // namespace WebKit