1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "WebView.h"
28 
29 #include "ChunkedUpdateDrawingAreaProxy.h"
30 #include "DrawingAreaProxyImpl.h"
31 #include "FindIndicator.h"
32 #include "Logging.h"
33 #include "NativeWebKeyboardEvent.h"
34 #include "NativeWebMouseEvent.h"
35 #include "NativeWebWheelEvent.h"
36 #include "Region.h"
37 #include "RunLoop.h"
38 #include "WKAPICast.h"
39 #include "WebContext.h"
40 #include "WebContextMenuProxyWin.h"
41 #include "WebEditCommandProxy.h"
42 #include "WebEventFactory.h"
43 #include "WebPageProxy.h"
44 #include "WebPopupMenuProxyWin.h"
45 #include <Commctrl.h>
46 #include <WebCore/BitmapInfo.h>
47 #include <WebCore/Cursor.h>
48 #include <WebCore/FloatRect.h>
49 #if USE(CG)
50 #include <WebCore/GraphicsContextCG.h>
51 #endif
52 #include <WebCore/IntRect.h>
53 #include <WebCore/SoftLinking.h>
54 #include <WebCore/WebCoreInstanceHandle.h>
55 #include <WebCore/WindowMessageBroadcaster.h>
56 #include <WebCore/WindowsTouch.h>
57 #include <wtf/text/WTFString.h>
58 
59 #if ENABLE(FULLSCREEN_API)
60 #include "WebFullScreenManagerProxy.h"
61 #include <WebCore/FullScreenController.h>
62 #endif
63 
64 namespace Ime {
65 // We need these functions in a separate namespace, because in the global namespace they conflict
66 // with the definitions in imm.h only by the type modifier (the macro defines them as static) and
67 // imm.h is included by windows.h
68 SOFT_LINK_LIBRARY(IMM32)
69 SOFT_LINK(IMM32, ImmGetContext, HIMC, WINAPI, (HWND hwnd), (hwnd))
70 SOFT_LINK(IMM32, ImmReleaseContext, BOOL, WINAPI, (HWND hWnd, HIMC hIMC), (hWnd, hIMC))
71 SOFT_LINK(IMM32, ImmGetCompositionStringW, LONG, WINAPI, (HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen), (hIMC, dwIndex, lpBuf, dwBufLen))
72 SOFT_LINK(IMM32, ImmSetCandidateWindow, BOOL, WINAPI, (HIMC hIMC, LPCANDIDATEFORM lpCandidate), (hIMC, lpCandidate))
73 SOFT_LINK(IMM32, ImmSetOpenStatus, BOOL, WINAPI, (HIMC hIMC, BOOL fOpen), (hIMC, fOpen))
74 SOFT_LINK(IMM32, ImmNotifyIME, BOOL, WINAPI, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue), (hIMC, dwAction, dwIndex, dwValue))
75 SOFT_LINK(IMM32, ImmAssociateContextEx, BOOL, WINAPI, (HWND hWnd, HIMC hIMC, DWORD dwFlags), (hWnd, hIMC, dwFlags))
76 };
77 
78 // Soft link functions for gestures and panning.
79 SOFT_LINK_LIBRARY(USER32);
80 SOFT_LINK_OPTIONAL(USER32, GetGestureInfo, BOOL, WINAPI, (HGESTUREINFO, PGESTUREINFO));
81 SOFT_LINK_OPTIONAL(USER32, SetGestureConfig, BOOL, WINAPI, (HWND, DWORD, UINT, PGESTURECONFIG, UINT));
82 SOFT_LINK_OPTIONAL(USER32, CloseGestureInfoHandle, BOOL, WINAPI, (HGESTUREINFO));
83 
84 SOFT_LINK_LIBRARY(Uxtheme);
85 SOFT_LINK_OPTIONAL(Uxtheme, BeginPanningFeedback, BOOL, WINAPI, (HWND));
86 SOFT_LINK_OPTIONAL(Uxtheme, EndPanningFeedback, BOOL, WINAPI, (HWND, BOOL));
87 SOFT_LINK_OPTIONAL(Uxtheme, UpdatePanningFeedback, BOOL, WINAPI, (HWND, LONG, LONG, BOOL));
88 
89 using namespace WebCore;
90 
91 namespace WebKit {
92 
93 static const LPCWSTR kWebKit2WebViewWindowClassName = L"WebKit2WebViewWindowClass";
94 
95 // Constants not available on all platforms.
96 const int WM_XP_THEMECHANGED = 0x031A;
97 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
98 
99 static const int kMaxToolTipWidth = 250;
100 
101 enum {
102     UpdateActiveStateTimer = 1,
103 };
104 
useNewDrawingArea()105 static bool useNewDrawingArea()
106 {
107     // FIXME: Remove this function and the old drawing area code once we aren't interested in
108     // testing the old drawing area anymore.
109     return true;
110 }
111 
WebViewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)112 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
113 {
114     LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
115 
116     if (WebView* webView = reinterpret_cast<WebView*>(longPtr))
117         return webView->wndProc(hWnd, message, wParam, lParam);
118 
119     if (message == WM_CREATE) {
120         LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
121 
122         // Associate the WebView with the window.
123         ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
124         return 0;
125     }
126 
127     return ::DefWindowProc(hWnd, message, wParam, lParam);
128 }
129 
wndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)130 LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
131 {
132     LRESULT lResult = 0;
133     bool handled = true;
134 
135     switch (message) {
136     case WM_CLOSE:
137         m_page->tryClose();
138         break;
139     case WM_DESTROY:
140         m_isBeingDestroyed = true;
141         close();
142         break;
143     case WM_ERASEBKGND:
144         lResult = 1;
145         break;
146     case WM_PAINT:
147         lResult = onPaintEvent(hWnd, message, wParam, lParam, handled);
148         break;
149     case WM_PRINTCLIENT:
150         lResult = onPrintClientEvent(hWnd, message, wParam, lParam, handled);
151         break;
152     case WM_MOUSEACTIVATE:
153         setWasActivatedByMouseEvent(true);
154         handled = false;
155         break;
156     case WM_MOUSEMOVE:
157     case WM_LBUTTONDOWN:
158     case WM_MBUTTONDOWN:
159     case WM_RBUTTONDOWN:
160     case WM_LBUTTONDBLCLK:
161     case WM_MBUTTONDBLCLK:
162     case WM_RBUTTONDBLCLK:
163     case WM_LBUTTONUP:
164     case WM_MBUTTONUP:
165     case WM_RBUTTONUP:
166     case WM_MOUSELEAVE:
167         lResult = onMouseEvent(hWnd, message, wParam, lParam, handled);
168         break;
169     case WM_MOUSEWHEEL:
170     case WM_VISTA_MOUSEHWHEEL:
171         lResult = onWheelEvent(hWnd, message, wParam, lParam, handled);
172         break;
173     case WM_HSCROLL:
174         lResult = onHorizontalScroll(hWnd, message, wParam, lParam, handled);
175         break;
176     case WM_VSCROLL:
177         lResult = onVerticalScroll(hWnd, message, wParam, lParam, handled);
178         break;
179     case WM_GESTURENOTIFY:
180         lResult = onGestureNotify(hWnd, message, wParam, lParam, handled);
181         break;
182     case WM_GESTURE:
183         lResult = onGesture(hWnd, message, wParam, lParam, handled);
184         break;
185     case WM_SYSKEYDOWN:
186     case WM_KEYDOWN:
187     case WM_SYSCHAR:
188     case WM_CHAR:
189     case WM_SYSKEYUP:
190     case WM_KEYUP:
191         lResult = onKeyEvent(hWnd, message, wParam, lParam, handled);
192         break;
193     case WM_SIZE:
194         lResult = onSizeEvent(hWnd, message, wParam, lParam, handled);
195         break;
196     case WM_WINDOWPOSCHANGED:
197         lResult = onWindowPositionChangedEvent(hWnd, message, wParam, lParam, handled);
198         break;
199     case WM_SETFOCUS:
200         lResult = onSetFocusEvent(hWnd, message, wParam, lParam, handled);
201         break;
202     case WM_KILLFOCUS:
203         lResult = onKillFocusEvent(hWnd, message, wParam, lParam, handled);
204         break;
205     case WM_TIMER:
206         lResult = onTimerEvent(hWnd, message, wParam, lParam, handled);
207         break;
208     case WM_SHOWWINDOW:
209         lResult = onShowWindowEvent(hWnd, message, wParam, lParam, handled);
210         break;
211     case WM_SETCURSOR:
212         lResult = onSetCursor(hWnd, message, wParam, lParam, handled);
213         break;
214     case WM_IME_STARTCOMPOSITION:
215         handled = onIMEStartComposition();
216         break;
217     case WM_IME_REQUEST:
218         lResult = onIMERequest(wParam, lParam);
219         break;
220     case WM_IME_COMPOSITION:
221         handled = onIMEComposition(lParam);
222         break;
223     case WM_IME_ENDCOMPOSITION:
224         handled = onIMEEndComposition();
225         break;
226     case WM_IME_SELECT:
227         handled = onIMESelect(wParam, lParam);
228         break;
229     case WM_IME_SETCONTEXT:
230         handled = onIMESetContext(wParam, lParam);
231         break;
232     default:
233         handled = false;
234         break;
235     }
236 
237     if (!handled)
238         lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
239 
240     return lResult;
241 }
242 
registerWebViewWindowClass()243 bool WebView::registerWebViewWindowClass()
244 {
245     static bool haveRegisteredWindowClass = false;
246     if (haveRegisteredWindowClass)
247         return true;
248     haveRegisteredWindowClass = true;
249 
250     WNDCLASSEX wcex;
251 
252     wcex.cbSize = sizeof(WNDCLASSEX);
253     wcex.style          = CS_DBLCLKS;
254     wcex.lpfnWndProc    = WebView::WebViewWndProc;
255     wcex.cbClsExtra     = 0;
256     wcex.cbWndExtra     = sizeof(WebView*);
257     wcex.hInstance      = instanceHandle();
258     wcex.hIcon          = 0;
259     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
260     wcex.hbrBackground  = 0;
261     wcex.lpszMenuName   = 0;
262     wcex.lpszClassName  = kWebKit2WebViewWindowClassName;
263     wcex.hIconSm        = 0;
264 
265     return !!::RegisterClassEx(&wcex);
266 }
267 
WebView(RECT rect,WebContext * context,WebPageGroup * pageGroup,HWND parentWindow)268 WebView::WebView(RECT rect, WebContext* context, WebPageGroup* pageGroup, HWND parentWindow)
269     : m_topLevelParentWindow(0)
270     , m_toolTipWindow(0)
271     , m_lastCursorSet(0)
272     , m_webCoreCursor(0)
273     , m_overrideCursor(0)
274     , m_trackingMouseLeave(false)
275     , m_isInWindow(false)
276     , m_isVisible(false)
277     , m_wasActivatedByMouseEvent(false)
278     , m_isBeingDestroyed(false)
279     , m_inIMEComposition(0)
280     , m_findIndicatorCallback(0)
281     , m_findIndicatorCallbackContext(0)
282     , m_lastPanX(0)
283     , m_lastPanY(0)
284     , m_overPanY(0)
285     , m_gestureReachedScrollingLimit(false)
286 {
287     registerWebViewWindowClass();
288 
289     m_window = ::CreateWindowExW(0, kWebKit2WebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE,
290         rect.top, rect.left, rect.right - rect.left, rect.bottom - rect.top, parentWindow ? parentWindow : HWND_MESSAGE, 0, instanceHandle(), this);
291     ASSERT(::IsWindow(m_window));
292     // We only check our window style, and not ::IsWindowVisible, because m_isVisible only tracks
293     // this window's visibility status, while ::IsWindowVisible takes our ancestors' visibility
294     // status into account. <http://webkit.org/b/54104>
295     ASSERT(m_isVisible == static_cast<bool>(::GetWindowLong(m_window, GWL_STYLE) & WS_VISIBLE));
296 
297     m_page = context->createWebPage(this, pageGroup);
298     m_page->initializeWebPage();
299 
300     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper, (void**)&m_dropTargetHelper);
301 
302     // FIXME: Initializing the tooltip window here matches WebKit win, but seems like something
303     // we could do on demand to save resources.
304     initializeToolTipWindow();
305 
306     // Initialize the top level parent window and register it with the WindowMessageBroadcaster.
307     windowAncestryDidChange();
308 
309 #if ENABLE(FULLSCREEN_API)
310     m_page->fullScreenManager()->setWebView(this);
311 #endif
312 }
313 
~WebView()314 WebView::~WebView()
315 {
316     // Tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD.
317     if (::IsWindow(m_toolTipWindow))
318         ::DestroyWindow(m_toolTipWindow);
319 }
320 
initialize()321 void WebView::initialize()
322 {
323     ::RegisterDragDrop(m_window, this);
324 
325     if (shouldInitializeTrackPointHack()) {
326         // If we detected a registry key belonging to a TrackPoint driver, then create fake
327         // scrollbars, so the WebView will receive WM_VSCROLL and WM_HSCROLL messages.
328         // We create an invisible vertical scrollbar and an invisible horizontal scrollbar to allow
329         // for receiving both types of messages.
330         ::CreateWindow(TEXT("SCROLLBAR"), TEXT("FAKETRACKPOINTHSCROLLBAR"), WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, 0, 0, 0, m_window, 0, instanceHandle(), 0);
331         ::CreateWindow(TEXT("SCROLLBAR"), TEXT("FAKETRACKPOINTVSCROLLBAR"), WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, m_window, 0, instanceHandle(), 0);
332     }
333 }
334 
initializeUndoClient(const WKViewUndoClient * client)335 void WebView::initializeUndoClient(const WKViewUndoClient* client)
336 {
337     m_undoClient.initialize(client);
338 }
339 
setParentWindow(HWND parentWindow)340 void WebView::setParentWindow(HWND parentWindow)
341 {
342     if (m_window) {
343         // If the host window hasn't changed, bail.
344         if (::GetParent(m_window) == parentWindow)
345             return;
346         if (parentWindow)
347             ::SetParent(m_window, parentWindow);
348         else if (!m_isBeingDestroyed) {
349             // Turn the WebView into a message-only window so it will no longer be a child of the
350             // old parent window and will be hidden from screen. We only do this when
351             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
352             // m_window in a weird state (see <http://webkit.org/b/29337>).
353             ::SetParent(m_window, HWND_MESSAGE);
354         }
355     }
356 
357     windowAncestryDidChange();
358 }
359 
findTopLevelParentWindow(HWND window)360 static HWND findTopLevelParentWindow(HWND window)
361 {
362     if (!window)
363         return 0;
364 
365     HWND current = window;
366     for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent)) {
367         if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
368             return current;
369     }
370     ASSERT_NOT_REACHED();
371     return 0;
372 }
373 
windowAncestryDidChange()374 void WebView::windowAncestryDidChange()
375 {
376     HWND newTopLevelParentWindow;
377     if (m_window)
378         newTopLevelParentWindow = findTopLevelParentWindow(m_window);
379     else {
380         // There's no point in tracking active state changes of our parent window if we don't have
381         // a window ourselves.
382         newTopLevelParentWindow = 0;
383     }
384 
385     if (newTopLevelParentWindow == m_topLevelParentWindow)
386         return;
387 
388     if (m_topLevelParentWindow)
389         WindowMessageBroadcaster::removeListener(m_topLevelParentWindow, this);
390 
391     m_topLevelParentWindow = newTopLevelParentWindow;
392 
393     if (m_topLevelParentWindow)
394         WindowMessageBroadcaster::addListener(m_topLevelParentWindow, this);
395 
396     updateActiveState();
397 }
398 
onMouseEvent(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)399 LRESULT WebView::onMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
400 {
401     NativeWebMouseEvent mouseEvent = NativeWebMouseEvent(hWnd, message, wParam, lParam, m_wasActivatedByMouseEvent);
402     setWasActivatedByMouseEvent(false);
403 
404     switch (message) {
405     case WM_LBUTTONDOWN:
406     case WM_MBUTTONDOWN:
407     case WM_RBUTTONDOWN:
408         ::SetFocus(m_window);
409         ::SetCapture(m_window);
410         break;
411     case WM_LBUTTONUP:
412     case WM_MBUTTONUP:
413     case WM_RBUTTONUP:
414         ::ReleaseCapture();
415         break;
416     case WM_MOUSEMOVE:
417         startTrackingMouseLeave();
418         break;
419     case WM_MOUSELEAVE:
420         stopTrackingMouseLeave();
421         break;
422     case WM_LBUTTONDBLCLK:
423     case WM_MBUTTONDBLCLK:
424     case WM_RBUTTONDBLCLK:
425         break;
426     default:
427         ASSERT_NOT_REACHED();
428     }
429 
430     m_page->handleMouseEvent(mouseEvent);
431 
432     handled = true;
433     return 0;
434 }
435 
onWheelEvent(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)436 LRESULT WebView::onWheelEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
437 {
438     NativeWebWheelEvent wheelEvent(hWnd, message, wParam, lParam);
439     if (wheelEvent.controlKey()) {
440         // We do not want WebKit to handle Control + Wheel, this should be handled by the client application
441         // to zoom the page.
442         handled = false;
443         return 0;
444     }
445 
446     m_page->handleWheelEvent(wheelEvent);
447 
448     handled = true;
449     return 0;
450 }
451 
onHorizontalScroll(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)452 LRESULT WebView::onHorizontalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
453 {
454     ScrollDirection direction;
455     ScrollGranularity granularity;
456     switch (LOWORD(wParam)) {
457     case SB_LINELEFT:
458         granularity = ScrollByLine;
459         direction = ScrollLeft;
460         break;
461     case SB_LINERIGHT:
462         granularity = ScrollByLine;
463         direction = ScrollRight;
464         break;
465     case SB_PAGELEFT:
466         granularity = ScrollByDocument;
467         direction = ScrollLeft;
468         break;
469     case SB_PAGERIGHT:
470         granularity = ScrollByDocument;
471         direction = ScrollRight;
472         break;
473     default:
474         handled = false;
475         return 0;
476     }
477 
478     m_page->scrollBy(direction, granularity);
479 
480     handled = true;
481     return 0;
482 }
483 
onVerticalScroll(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)484 LRESULT WebView::onVerticalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
485 {
486     ScrollDirection direction;
487     ScrollGranularity granularity;
488     switch (LOWORD(wParam)) {
489     case SB_LINEDOWN:
490         granularity = ScrollByLine;
491         direction = ScrollDown;
492         break;
493     case SB_LINEUP:
494         granularity = ScrollByLine;
495         direction = ScrollUp;
496         break;
497     case SB_PAGEDOWN:
498         granularity = ScrollByDocument;
499         direction = ScrollDown;
500         break;
501     case SB_PAGEUP:
502         granularity = ScrollByDocument;
503         direction = ScrollUp;
504         break;
505     default:
506         handled = false;
507         return 0;
508     }
509 
510     m_page->scrollBy(direction, granularity);
511 
512     handled = true;
513     return 0;
514 }
515 
onGestureNotify(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)516 LRESULT WebView::onGestureNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
517 {
518     // We shouldn't be getting any gesture messages without SetGestureConfig soft-linking correctly.
519     ASSERT(SetGestureConfigPtr());
520 
521     GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
522 
523     POINT localPoint = { gn->ptsLocation.x, gn->ptsLocation.y };
524     ::ScreenToClient(m_window, &localPoint);
525 
526     bool canPan = m_page->gestureWillBegin(localPoint);
527 
528     DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
529     DWORD dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
530     if (canPan)
531         dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
532     else
533         dwPanBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
534 
535     GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock };
536     return SetGestureConfigPtr()(m_window, 0, 1, &gc, sizeof(gc));
537 }
538 
onGesture(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)539 LRESULT WebView::onGesture(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
540 {
541     ASSERT(GetGestureInfoPtr());
542     ASSERT(CloseGestureInfoHandlePtr());
543     ASSERT(UpdatePanningFeedbackPtr());
544     ASSERT(BeginPanningFeedbackPtr());
545     ASSERT(EndPanningFeedbackPtr());
546 
547     if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr() || !UpdatePanningFeedbackPtr() || !BeginPanningFeedbackPtr() || !EndPanningFeedbackPtr()) {
548         handled = false;
549         return 0;
550     }
551 
552     HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
553     GESTUREINFO gi = {0};
554     gi.cbSize = sizeof(GESTUREINFO);
555 
556     if (!GetGestureInfoPtr()(gestureHandle, &gi)) {
557         handled = false;
558         return 0;
559     }
560 
561     switch (gi.dwID) {
562     case GID_BEGIN:
563         m_lastPanX = gi.ptsLocation.x;
564         m_lastPanY = gi.ptsLocation.y;
565         break;
566     case GID_END:
567         m_page->gestureDidEnd();
568         break;
569     case GID_PAN: {
570         int currentX = gi.ptsLocation.x;
571         int currentY = gi.ptsLocation.y;
572 
573         // Reverse the calculations because moving your fingers up should move the screen down, and
574         // vice-versa.
575         int deltaX = m_lastPanX - currentX;
576         int deltaY = m_lastPanY - currentY;
577 
578         m_lastPanX = currentX;
579         m_lastPanY = currentY;
580 
581         // Calculate the overpan for window bounce.
582         m_overPanY -= deltaY;
583 
584         if (deltaX || deltaY)
585             m_page->gestureDidScroll(IntSize(deltaX, deltaY));
586 
587         if (gi.dwFlags & GF_BEGIN) {
588             BeginPanningFeedbackPtr()(m_window);
589             m_gestureReachedScrollingLimit = false;
590             m_overPanY = 0;
591         } else if (gi.dwFlags & GF_END) {
592             EndPanningFeedbackPtr()(m_window, true);
593             m_overPanY = 0;
594         }
595 
596         // FIXME: Support horizontal window bounce - <http://webkit.org/b/58068>.
597         // FIXME: Window Bounce doesn't undo until user releases their finger - <http://webkit.org/b/58069>.
598 
599         if (m_gestureReachedScrollingLimit)
600             UpdatePanningFeedbackPtr()(m_window, 0, m_overPanY, gi.dwFlags & GF_INERTIA);
601 
602         CloseGestureInfoHandlePtr()(gestureHandle);
603 
604         handled = true;
605         return 0;
606     }
607     default:
608         break;
609     }
610 
611     // If we get to this point, the gesture has not been handled. We forward
612     // the call to DefWindowProc by returning false, and we don't need to
613     // to call CloseGestureInfoHandle.
614     // http://msdn.microsoft.com/en-us/library/dd353228(VS.85).aspx
615     handled = false;
616     return 0;
617 }
618 
onKeyEvent(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)619 LRESULT WebView::onKeyEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
620 {
621 #if ENABLE(FULLSCREEN_API)
622     // Trap the ESC key when in full screen mode.
623     if (message == WM_KEYDOWN && wParam == VK_ESCAPE && m_fullScreenController && m_fullScreenController->isFullScreen()) {
624         m_fullScreenController->exitFullScreen();
625         return false;
626     }
627 #endif
628 
629     m_page->handleKeyboardEvent(NativeWebKeyboardEvent(hWnd, message, wParam, lParam));
630 
631     // We claim here to always have handled the event. If the event is not in fact handled, we will
632     // find out later in didNotHandleKeyEvent.
633     handled = true;
634     return 0;
635 }
636 
drawPageBackground(HDC dc,const WebPageProxy * page,const RECT & rect)637 static void drawPageBackground(HDC dc, const WebPageProxy* page, const RECT& rect)
638 {
639     if (!page->drawsBackground() || page->drawsTransparentBackground())
640         return;
641 
642     ::FillRect(dc, &rect, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
643 }
644 
paint(HDC hdc,const IntRect & dirtyRect)645 void WebView::paint(HDC hdc, const IntRect& dirtyRect)
646 {
647     m_page->endPrinting();
648     if (useNewDrawingArea()) {
649         if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(m_page->drawingArea())) {
650             // FIXME: We should port WebKit1's rect coalescing logic here.
651             Region unpaintedRegion;
652             drawingArea->paint(hdc, dirtyRect, unpaintedRegion);
653 
654             Vector<IntRect> unpaintedRects = unpaintedRegion.rects();
655             for (size_t i = 0; i < unpaintedRects.size(); ++i) {
656                 RECT winRect = unpaintedRects[i];
657                 drawPageBackground(hdc, m_page.get(), unpaintedRects[i]);
658             }
659         } else
660             drawPageBackground(hdc, m_page.get(), dirtyRect);
661 
662         m_page->didDraw();
663     } else {
664         if (m_page->isValid() && m_page->drawingArea() && m_page->drawingArea()->paint(dirtyRect, hdc))
665             m_page->didDraw();
666         else
667             drawPageBackground(hdc, m_page.get(), dirtyRect);
668     }
669 }
670 
flashRects(HDC dc,const IntRect rects[],size_t rectCount,HBRUSH brush)671 static void flashRects(HDC dc, const IntRect rects[], size_t rectCount, HBRUSH brush)
672 {
673     for (size_t i = 0; i < rectCount; ++i) {
674         RECT winRect = rects[i];
675         ::FillRect(dc, &winRect, brush);
676     }
677 
678     ::GdiFlush();
679     ::Sleep(50);
680 }
681 
createBrush(const Color & color)682 static OwnPtr<HBRUSH> createBrush(const Color& color)
683 {
684     return adoptPtr(::CreateSolidBrush(RGB(color.red(), color.green(), color.blue())));
685 }
686 
onPaintEvent(HWND hWnd,UINT message,WPARAM,LPARAM,bool & handled)687 LRESULT WebView::onPaintEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled)
688 {
689     // Update child windows now so that any areas of our window they reveal will be included in the
690     // invalid region that ::BeginPaint sees.
691     updateChildWindowGeometries();
692 
693     PAINTSTRUCT paintStruct;
694     HDC hdc = ::BeginPaint(m_window, &paintStruct);
695 
696     if (WebPageProxy::debugPaintFlags() & kWKDebugFlashViewUpdates) {
697         static HBRUSH brush = createBrush(WebPageProxy::viewUpdatesFlashColor().rgb()).leakPtr();
698         IntRect rect = paintStruct.rcPaint;
699         flashRects(hdc, &rect, 1, brush);
700     }
701 
702     paint(hdc, paintStruct.rcPaint);
703 
704     ::EndPaint(m_window, &paintStruct);
705 
706     handled = true;
707     return 0;
708 }
709 
onPrintClientEvent(HWND hWnd,UINT,WPARAM wParam,LPARAM,bool & handled)710 LRESULT WebView::onPrintClientEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
711 {
712     HDC hdc = reinterpret_cast<HDC>(wParam);
713     RECT winRect;
714     ::GetClientRect(hWnd, &winRect);
715 
716     // Twidding the visibility flags tells the DrawingArea to resume painting. Right now, the
717     // the visible state of the view only affects whether or not painting happens, but in the
718     // future it could affect more, which we wouldn't want to touch here.
719 
720     // FIXME: We should have a better way of telling the WebProcess to draw even if we're
721     // invisible than twiddling the visibility flag.
722 
723     bool wasVisible = isViewVisible();
724     if (!wasVisible)
725         setIsVisible(true);
726 
727     paint(hdc, winRect);
728 
729     if (!wasVisible)
730         setIsVisible(false);
731 
732     handled = true;
733     return 0;
734 }
735 
onSizeEvent(HWND,UINT,WPARAM,LPARAM lParam,bool & handled)736 LRESULT WebView::onSizeEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
737 {
738     int width = LOWORD(lParam);
739     int height = HIWORD(lParam);
740 
741     if (m_page && m_page->drawingArea()) {
742         m_page->drawingArea()->setSize(IntSize(width, height), m_nextResizeScrollOffset);
743         m_nextResizeScrollOffset = IntSize();
744     }
745 
746     handled = true;
747     return 0;
748 }
749 
onWindowPositionChangedEvent(HWND,UINT,WPARAM,LPARAM lParam,bool & handled)750 LRESULT WebView::onWindowPositionChangedEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
751 {
752     if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
753         updateActiveStateSoon();
754 
755     handled = false;
756     return 0;
757 }
758 
onSetFocusEvent(HWND,UINT,WPARAM,LPARAM lParam,bool & handled)759 LRESULT WebView::onSetFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
760 {
761     m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
762     handled = true;
763     return 0;
764 }
765 
onKillFocusEvent(HWND,UINT,WPARAM,LPARAM lParam,bool & handled)766 LRESULT WebView::onKillFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
767 {
768     m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
769     handled = true;
770     return 0;
771 }
772 
onTimerEvent(HWND hWnd,UINT,WPARAM wParam,LPARAM,bool & handled)773 LRESULT WebView::onTimerEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
774 {
775     switch (wParam) {
776     case UpdateActiveStateTimer:
777         ::KillTimer(hWnd, UpdateActiveStateTimer);
778         updateActiveState();
779         break;
780     }
781 
782     handled = true;
783     return 0;
784 }
785 
onShowWindowEvent(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)786 LRESULT WebView::onShowWindowEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
787 {
788     // lParam is 0 when the message is sent because of a ShowWindow call.
789     // FIXME: Since we don't get notified when an ancestor window is hidden or shown, we will keep
790     // painting even when we have a hidden ancestor. <http://webkit.org/b/54104>
791     if (!lParam)
792         setIsVisible(wParam);
793 
794     handled = false;
795     return 0;
796 }
797 
onSetCursor(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,bool & handled)798 LRESULT WebView::onSetCursor(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
799 {
800     if (!m_lastCursorSet) {
801         handled = false;
802         return 0;
803     }
804 
805     ::SetCursor(m_lastCursorSet);
806     return 0;
807 }
808 
updateActiveState()809 void WebView::updateActiveState()
810 {
811     m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
812 }
813 
updateActiveStateSoon()814 void WebView::updateActiveStateSoon()
815 {
816     // This function is called while processing the WM_NCACTIVATE message.
817     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
818     // still return our window. If we were to call updateActiveState() in that case, we would
819     // wrongly think that we are still the active window. To work around this, we update our
820     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
821     // the newly-activated window.
822 
823     ::SetTimer(m_window, UpdateActiveStateTimer, 0, 0);
824 }
825 
initCommonControls()826 static bool initCommonControls()
827 {
828     static bool haveInitialized = false;
829     if (haveInitialized)
830         return true;
831 
832     INITCOMMONCONTROLSEX init;
833     init.dwSize = sizeof(init);
834     init.dwICC = ICC_TREEVIEW_CLASSES;
835     haveInitialized = !!::InitCommonControlsEx(&init);
836     return haveInitialized;
837 }
838 
initializeToolTipWindow()839 void WebView::initializeToolTipWindow()
840 {
841     if (!initCommonControls())
842         return;
843 
844     m_toolTipWindow = ::CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
845                                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
846                                        m_window, 0, 0, 0);
847     if (!m_toolTipWindow)
848         return;
849 
850     TOOLINFO info = {0};
851     info.cbSize = sizeof(info);
852     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
853     info.uId = reinterpret_cast<UINT_PTR>(m_window);
854 
855     ::SendMessage(m_toolTipWindow, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
856     ::SendMessage(m_toolTipWindow, TTM_SETMAXTIPWIDTH, 0, kMaxToolTipWidth);
857     ::SetWindowPos(m_toolTipWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
858 }
859 
startTrackingMouseLeave()860 void WebView::startTrackingMouseLeave()
861 {
862     if (m_trackingMouseLeave)
863         return;
864     m_trackingMouseLeave = true;
865 
866     TRACKMOUSEEVENT trackMouseEvent;
867     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
868     trackMouseEvent.dwFlags = TME_LEAVE;
869     trackMouseEvent.hwndTrack = m_window;
870 
871     ::TrackMouseEvent(&trackMouseEvent);
872 }
873 
stopTrackingMouseLeave()874 void WebView::stopTrackingMouseLeave()
875 {
876     if (!m_trackingMouseLeave)
877         return;
878     m_trackingMouseLeave = false;
879 
880     TRACKMOUSEEVENT trackMouseEvent;
881     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
882     trackMouseEvent.dwFlags = TME_LEAVE | TME_CANCEL;
883     trackMouseEvent.hwndTrack = m_window;
884 
885     ::TrackMouseEvent(&trackMouseEvent);
886 }
887 
shouldInitializeTrackPointHack()888 bool WebView::shouldInitializeTrackPointHack()
889 {
890     static bool shouldCreateScrollbars;
891     static bool hasRunTrackPointCheck;
892 
893     if (hasRunTrackPointCheck)
894         return shouldCreateScrollbars;
895 
896     hasRunTrackPointCheck = true;
897     const wchar_t* trackPointKeys[] = {
898         L"Software\\Lenovo\\TrackPoint",
899         L"Software\\Lenovo\\UltraNav",
900         L"Software\\Alps\\Apoint\\TrackPoint",
901         L"Software\\Synaptics\\SynTPEnh\\UltraNavUSB",
902         L"Software\\Synaptics\\SynTPEnh\\UltraNavPS2"
903     };
904 
905     for (size_t i = 0; i < WTF_ARRAY_LENGTH(trackPointKeys); ++i) {
906         HKEY trackPointKey;
907         int readKeyResult = ::RegOpenKeyExW(HKEY_CURRENT_USER, trackPointKeys[i], 0, KEY_READ, &trackPointKey);
908         ::RegCloseKey(trackPointKey);
909         if (readKeyResult == ERROR_SUCCESS) {
910             shouldCreateScrollbars = true;
911             return shouldCreateScrollbars;
912         }
913     }
914 
915     return shouldCreateScrollbars;
916 }
917 
close()918 void WebView::close()
919 {
920     m_undoClient.initialize(0);
921     ::RevokeDragDrop(m_window);
922     if (m_window) {
923         // We can't check IsWindow(m_window) here, because that will return true even while
924         // we're already handling WM_DESTROY. So we check !m_isBeingDestroyed instead.
925         if (!m_isBeingDestroyed)
926             DestroyWindow(m_window);
927         // Either we just destroyed m_window, or it's in the process of being destroyed. Either
928         // way, we clear it out to make sure we don't try to use it later.
929         m_window = 0;
930     }
931     setParentWindow(0);
932     m_page->close();
933 }
934 
935 // PageClient
936 
createDrawingAreaProxy()937 PassOwnPtr<DrawingAreaProxy> WebView::createDrawingAreaProxy()
938 {
939     if (useNewDrawingArea())
940         return DrawingAreaProxyImpl::create(m_page.get());
941 
942     return ChunkedUpdateDrawingAreaProxy::create(this, m_page.get());
943 }
944 
setViewNeedsDisplay(const WebCore::IntRect & rect)945 void WebView::setViewNeedsDisplay(const WebCore::IntRect& rect)
946 {
947     RECT r = rect;
948     ::InvalidateRect(m_window, &r, false);
949 }
950 
displayView()951 void WebView::displayView()
952 {
953     ::UpdateWindow(m_window);
954 }
955 
scrollView(const IntRect & scrollRect,const IntSize & scrollOffset)956 void WebView::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
957 {
958     // FIXME: Actually scroll the view contents.
959     setViewNeedsDisplay(scrollRect);
960 }
961 
flashBackingStoreUpdates(const Vector<IntRect> & updateRects)962 void WebView::flashBackingStoreUpdates(const Vector<IntRect>& updateRects)
963 {
964     static HBRUSH brush = createBrush(WebPageProxy::backingStoreUpdatesFlashColor().rgb()).leakPtr();
965     HDC dc = ::GetDC(m_window);
966     flashRects(dc, updateRects.data(), updateRects.size(), brush);
967     ::ReleaseDC(m_window, dc);
968 }
969 
viewSize()970 WebCore::IntSize WebView::viewSize()
971 {
972     RECT clientRect;
973     GetClientRect(m_window, &clientRect);
974 
975     return IntRect(clientRect).size();
976 }
977 
isViewWindowActive()978 bool WebView::isViewWindowActive()
979 {
980     HWND activeWindow = ::GetActiveWindow();
981     return (activeWindow && m_topLevelParentWindow == findTopLevelParentWindow(activeWindow));
982 }
983 
isViewFocused()984 bool WebView::isViewFocused()
985 {
986     return ::GetFocus() == m_window;
987 }
988 
isViewVisible()989 bool WebView::isViewVisible()
990 {
991     return m_isVisible;
992 }
993 
isViewInWindow()994 bool WebView::isViewInWindow()
995 {
996     return m_isInWindow;
997 }
998 
pageClosed()999 void WebView::pageClosed()
1000 {
1001 }
1002 
processDidCrash()1003 void WebView::processDidCrash()
1004 {
1005     updateNativeCursor();
1006     ::InvalidateRect(m_window, 0, TRUE);
1007 }
1008 
didRelaunchProcess()1009 void WebView::didRelaunchProcess()
1010 {
1011     updateNativeCursor();
1012     ::InvalidateRect(m_window, 0, TRUE);
1013 }
1014 
toolTipChanged(const String &,const String & newToolTip)1015 void WebView::toolTipChanged(const String&, const String& newToolTip)
1016 {
1017     if (!m_toolTipWindow)
1018         return;
1019 
1020     if (!newToolTip.isEmpty()) {
1021         // This is necessary because String::charactersWithNullTermination() is not const.
1022         String toolTip = newToolTip;
1023 
1024         TOOLINFO info = {0};
1025         info.cbSize = sizeof(info);
1026         info.uFlags = TTF_IDISHWND;
1027         info.uId = reinterpret_cast<UINT_PTR>(m_window);
1028         info.lpszText = const_cast<UChar*>(toolTip.charactersWithNullTermination());
1029         ::SendMessage(m_toolTipWindow, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
1030     }
1031 
1032     ::SendMessage(m_toolTipWindow, TTM_ACTIVATE, !newToolTip.isEmpty(), 0);
1033 }
1034 
cursorToShow() const1035 HCURSOR WebView::cursorToShow() const
1036 {
1037     if (!m_page->isValid())
1038         return 0;
1039 
1040     // We only show the override cursor if the default (arrow) cursor is showing.
1041     static HCURSOR arrowCursor = ::LoadCursor(0, IDC_ARROW);
1042     if (m_overrideCursor && m_webCoreCursor == arrowCursor)
1043         return m_overrideCursor;
1044 
1045     return m_webCoreCursor;
1046 }
1047 
updateNativeCursor()1048 void WebView::updateNativeCursor()
1049 {
1050     m_lastCursorSet = cursorToShow();
1051     if (!m_lastCursorSet)
1052         return;
1053     ::SetCursor(m_lastCursorSet);
1054 }
1055 
setCursor(const WebCore::Cursor & cursor)1056 void WebView::setCursor(const WebCore::Cursor& cursor)
1057 {
1058     if (!cursor.platformCursor()->nativeCursor())
1059         return;
1060     m_webCoreCursor = cursor.platformCursor()->nativeCursor();
1061     updateNativeCursor();
1062 }
1063 
setOverrideCursor(HCURSOR overrideCursor)1064 void WebView::setOverrideCursor(HCURSOR overrideCursor)
1065 {
1066     m_overrideCursor = overrideCursor;
1067     updateNativeCursor();
1068 }
1069 
setInitialFocus(bool forward)1070 void WebView::setInitialFocus(bool forward)
1071 {
1072     m_page->setInitialFocus(forward);
1073 }
1074 
setScrollOffsetOnNextResize(const IntSize & scrollOffset)1075 void WebView::setScrollOffsetOnNextResize(const IntSize& scrollOffset)
1076 {
1077     // The next time we get a WM_SIZE message, scroll by the specified amount in onSizeEvent().
1078     m_nextResizeScrollOffset = scrollOffset;
1079 }
1080 
setViewportArguments(const WebCore::ViewportArguments &)1081 void WebView::setViewportArguments(const WebCore::ViewportArguments&)
1082 {
1083 }
1084 
registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand,WebPageProxy::UndoOrRedo undoOrRedo)1085 void WebView::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo)
1086 {
1087     RefPtr<WebEditCommandProxy> command = prpCommand;
1088     m_undoClient.registerEditCommand(this, command, undoOrRedo);
1089 }
1090 
clearAllEditCommands()1091 void WebView::clearAllEditCommands()
1092 {
1093     m_undoClient.clearAllEditCommands(this);
1094 }
1095 
canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)1096 bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
1097 {
1098     return m_undoClient.canUndoRedo(this, undoOrRedo);
1099 }
1100 
executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)1101 void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
1102 {
1103     m_undoClient.executeUndoRedo(this, undoOrRedo);
1104 }
1105 
reapplyEditCommand(WebEditCommandProxy * command)1106 void WebView::reapplyEditCommand(WebEditCommandProxy* command)
1107 {
1108     if (!m_page->isValid() || !m_page->isValidEditCommand(command))
1109         return;
1110 
1111     command->reapply();
1112 }
1113 
unapplyEditCommand(WebEditCommandProxy * command)1114 void WebView::unapplyEditCommand(WebEditCommandProxy* command)
1115 {
1116     if (!m_page->isValid() || !m_page->isValidEditCommand(command))
1117         return;
1118 
1119     command->unapply();
1120 }
1121 
convertToDeviceSpace(const FloatRect & rect)1122 FloatRect WebView::convertToDeviceSpace(const FloatRect& rect)
1123 {
1124     return rect;
1125 }
1126 
windowToScreen(const IntRect & rect)1127 IntRect WebView::windowToScreen(const IntRect& rect)
1128 {
1129     return rect;
1130 }
1131 
convertToUserSpace(const FloatRect & rect)1132 FloatRect WebView::convertToUserSpace(const FloatRect& rect)
1133 {
1134     return rect;
1135 }
1136 
getIMMContext()1137 HIMC WebView::getIMMContext()
1138 {
1139     return Ime::ImmGetContext(m_window);
1140 }
1141 
prepareCandidateWindow(HIMC hInputContext)1142 void WebView::prepareCandidateWindow(HIMC hInputContext)
1143 {
1144     IntRect caret = m_page->firstRectForCharacterInSelectedRange(0);
1145     CANDIDATEFORM form;
1146     form.dwIndex = 0;
1147     form.dwStyle = CFS_EXCLUDE;
1148     form.ptCurrentPos.x = caret.x();
1149     form.ptCurrentPos.y = caret.maxY();
1150     form.rcArea.top = caret.y();
1151     form.rcArea.bottom = caret.maxY();
1152     form.rcArea.left = caret.x();
1153     form.rcArea.right = caret.maxX();
1154     Ime::ImmSetCandidateWindow(hInputContext, &form);
1155 }
1156 
resetIME()1157 void WebView::resetIME()
1158 {
1159     HIMC hInputContext = getIMMContext();
1160     if (!hInputContext)
1161         return;
1162     Ime::ImmNotifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
1163     Ime::ImmReleaseContext(m_window, hInputContext);
1164 }
1165 
setInputMethodState(bool enabled)1166 void WebView::setInputMethodState(bool enabled)
1167 {
1168     Ime::ImmAssociateContextEx(m_window, 0, enabled ? IACE_DEFAULT : 0);
1169 }
1170 
compositionSelectionChanged(bool hasChanged)1171 void WebView::compositionSelectionChanged(bool hasChanged)
1172 {
1173     if (m_page->editorState().hasComposition && !hasChanged)
1174         resetIME();
1175 }
1176 
onIMEStartComposition()1177 bool WebView::onIMEStartComposition()
1178 {
1179     LOG(TextInput, "onIMEStartComposition");
1180     m_inIMEComposition++;
1181 
1182     HIMC hInputContext = getIMMContext();
1183     if (!hInputContext)
1184         return false;
1185     prepareCandidateWindow(hInputContext);
1186     Ime::ImmReleaseContext(m_window, hInputContext);
1187     return true;
1188 }
1189 
getCompositionString(HIMC hInputContext,DWORD type,String & result)1190 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
1191 {
1192     LONG compositionLength = Ime::ImmGetCompositionStringW(hInputContext, type, 0, 0);
1193     if (compositionLength <= 0)
1194         return false;
1195     Vector<UChar> compositionBuffer(compositionLength / 2);
1196     compositionLength = Ime::ImmGetCompositionStringW(hInputContext, type, compositionBuffer.data(), compositionLength);
1197     result = String::adopt(compositionBuffer);
1198     return true;
1199 }
1200 
compositionToUnderlines(const Vector<DWORD> & clauses,const Vector<BYTE> & attributes,Vector<CompositionUnderline> & underlines)1201 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
1202 {
1203     if (clauses.isEmpty()) {
1204         underlines.clear();
1205         return;
1206     }
1207 
1208     size_t numBoundaries = clauses.size() - 1;
1209     underlines.resize(numBoundaries);
1210     for (unsigned i = 0; i < numBoundaries; ++i) {
1211         underlines[i].startOffset = clauses[i];
1212         underlines[i].endOffset = clauses[i + 1];
1213         BYTE attribute = attributes[clauses[i]];
1214         underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
1215         underlines[i].color = Color::black;
1216     }
1217 }
1218 
1219 #if !LOG_DISABLED
1220 #define APPEND_ARGUMENT_NAME(name) \
1221     if (lparam & name) { \
1222         if (needsComma) \
1223             result += ", "; \
1224             result += #name; \
1225         needsComma = true; \
1226     }
1227 
imeCompositionArgumentNames(LPARAM lparam)1228 static String imeCompositionArgumentNames(LPARAM lparam)
1229 {
1230     String result;
1231     bool needsComma = false;
1232 
1233     APPEND_ARGUMENT_NAME(GCS_COMPATTR);
1234     APPEND_ARGUMENT_NAME(GCS_COMPCLAUSE);
1235     APPEND_ARGUMENT_NAME(GCS_COMPREADSTR);
1236     APPEND_ARGUMENT_NAME(GCS_COMPREADATTR);
1237     APPEND_ARGUMENT_NAME(GCS_COMPREADCLAUSE);
1238     APPEND_ARGUMENT_NAME(GCS_COMPSTR);
1239     APPEND_ARGUMENT_NAME(GCS_CURSORPOS);
1240     APPEND_ARGUMENT_NAME(GCS_DELTASTART);
1241     APPEND_ARGUMENT_NAME(GCS_RESULTCLAUSE);
1242     APPEND_ARGUMENT_NAME(GCS_RESULTREADCLAUSE);
1243     APPEND_ARGUMENT_NAME(GCS_RESULTREADSTR);
1244     APPEND_ARGUMENT_NAME(GCS_RESULTSTR);
1245     APPEND_ARGUMENT_NAME(CS_INSERTCHAR);
1246     APPEND_ARGUMENT_NAME(CS_NOMOVECARET);
1247 
1248     return result;
1249 }
1250 
imeRequestName(WPARAM wparam)1251 static String imeRequestName(WPARAM wparam)
1252 {
1253     switch (wparam) {
1254     case IMR_CANDIDATEWINDOW:
1255         return "IMR_CANDIDATEWINDOW";
1256     case IMR_COMPOSITIONFONT:
1257         return "IMR_COMPOSITIONFONT";
1258     case IMR_COMPOSITIONWINDOW:
1259         return "IMR_COMPOSITIONWINDOW";
1260     case IMR_CONFIRMRECONVERTSTRING:
1261         return "IMR_CONFIRMRECONVERTSTRING";
1262     case IMR_DOCUMENTFEED:
1263         return "IMR_DOCUMENTFEED";
1264     case IMR_QUERYCHARPOSITION:
1265         return "IMR_QUERYCHARPOSITION";
1266     case IMR_RECONVERTSTRING:
1267         return "IMR_RECONVERTSTRING";
1268     default:
1269         return "Unknown (" + String::number(wparam) + ")";
1270     }
1271 }
1272 #endif
1273 
onIMEComposition(LPARAM lparam)1274 bool WebView::onIMEComposition(LPARAM lparam)
1275 {
1276     LOG(TextInput, "onIMEComposition %s", imeCompositionArgumentNames(lparam).latin1().data());
1277     HIMC hInputContext = getIMMContext();
1278     if (!hInputContext)
1279         return true;
1280 
1281     if (!m_page->editorState().isContentEditable)
1282         return true;
1283 
1284     prepareCandidateWindow(hInputContext);
1285 
1286     if (lparam & GCS_RESULTSTR || !lparam) {
1287         String compositionString;
1288         if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
1289             return true;
1290 
1291         m_page->confirmComposition(compositionString);
1292         return true;
1293     }
1294 
1295     String compositionString;
1296     if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
1297         return true;
1298 
1299     // Composition string attributes
1300     int numAttributes = Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPATTR, 0, 0);
1301     Vector<BYTE> attributes(numAttributes);
1302     Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes);
1303 
1304     // Get clauses
1305     int numBytes = Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPCLAUSE, 0, 0);
1306     Vector<DWORD> clauses(numBytes / sizeof(DWORD));
1307     Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPCLAUSE, clauses.data(), numBytes);
1308 
1309     Vector<CompositionUnderline> underlines;
1310     compositionToUnderlines(clauses, attributes, underlines);
1311 
1312     int cursorPosition = LOWORD(Ime::ImmGetCompositionStringW(hInputContext, GCS_CURSORPOS, 0, 0));
1313 
1314     m_page->setComposition(compositionString, underlines, cursorPosition);
1315 
1316     return true;
1317 }
1318 
onIMEEndComposition()1319 bool WebView::onIMEEndComposition()
1320 {
1321     LOG(TextInput, "onIMEEndComposition");
1322     // If the composition hasn't been confirmed yet, it needs to be cancelled.
1323     // This happens after deleting the last character from inline input hole.
1324     if (m_page->editorState().hasComposition)
1325         m_page->confirmComposition(String());
1326 
1327     if (m_inIMEComposition)
1328         m_inIMEComposition--;
1329 
1330     return true;
1331 }
1332 
onIMERequestCharPosition(IMECHARPOSITION * charPos)1333 LRESULT WebView::onIMERequestCharPosition(IMECHARPOSITION* charPos)
1334 {
1335     if (charPos->dwCharPos && !m_page->editorState().hasComposition)
1336         return 0;
1337     IntRect caret = m_page->firstRectForCharacterInSelectedRange(charPos->dwCharPos);
1338     charPos->pt.x = caret.x();
1339     charPos->pt.y = caret.y();
1340     ::ClientToScreen(m_window, &charPos->pt);
1341     charPos->cLineHeight = caret.height();
1342     ::GetWindowRect(m_window, &charPos->rcDocument);
1343     return true;
1344 }
1345 
onIMERequestReconvertString(RECONVERTSTRING * reconvertString)1346 LRESULT WebView::onIMERequestReconvertString(RECONVERTSTRING* reconvertString)
1347 {
1348     String text = m_page->getSelectedText();
1349     unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
1350 
1351     if (!reconvertString)
1352         return totalSize;
1353 
1354     if (totalSize > reconvertString->dwSize)
1355         return 0;
1356     reconvertString->dwCompStrLen = text.length();
1357     reconvertString->dwStrLen = text.length();
1358     reconvertString->dwTargetStrLen = text.length();
1359     reconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
1360     memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar));
1361     return totalSize;
1362 }
1363 
onIMERequest(WPARAM request,LPARAM data)1364 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data)
1365 {
1366     LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data());
1367     if (!m_page->editorState().isContentEditable)
1368         return 0;
1369 
1370     switch (request) {
1371     case IMR_RECONVERTSTRING:
1372         return onIMERequestReconvertString(reinterpret_cast<RECONVERTSTRING*>(data));
1373 
1374     case IMR_QUERYCHARPOSITION:
1375         return onIMERequestCharPosition(reinterpret_cast<IMECHARPOSITION*>(data));
1376     }
1377     return 0;
1378 }
1379 
onIMESelect(WPARAM wparam,LPARAM lparam)1380 bool WebView::onIMESelect(WPARAM wparam, LPARAM lparam)
1381 {
1382     UNUSED_PARAM(wparam);
1383     UNUSED_PARAM(lparam);
1384     LOG(TextInput, "onIMESelect locale %ld %s", lparam, wparam ? "select" : "deselect");
1385     return false;
1386 }
1387 
onIMESetContext(WPARAM wparam,LPARAM)1388 bool WebView::onIMESetContext(WPARAM wparam, LPARAM)
1389 {
1390     LOG(TextInput, "onIMESetContext %s", wparam ? "active" : "inactive");
1391     return false;
1392 }
1393 
doneWithKeyEvent(const NativeWebKeyboardEvent & event,bool wasEventHandled)1394 void WebView::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled)
1395 {
1396     // Calling ::DefWindowProcW will ensure that pressing the Alt key will generate a WM_SYSCOMMAND
1397     // event, e.g. See <http://webkit.org/b/47671>.
1398     if (!wasEventHandled)
1399         ::DefWindowProcW(event.nativeEvent()->hwnd, event.nativeEvent()->message, event.nativeEvent()->wParam, event.nativeEvent()->lParam);
1400 }
1401 
createPopupMenuProxy(WebPageProxy * page)1402 PassRefPtr<WebPopupMenuProxy> WebView::createPopupMenuProxy(WebPageProxy* page)
1403 {
1404     return WebPopupMenuProxyWin::create(this, page);
1405 }
1406 
createContextMenuProxy(WebPageProxy * page)1407 PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy* page)
1408 {
1409     return WebContextMenuProxyWin::create(m_window, page);
1410 }
1411 
setFindIndicator(PassRefPtr<FindIndicator> prpFindIndicator,bool fadeOut)1412 void WebView::setFindIndicator(PassRefPtr<FindIndicator> prpFindIndicator, bool fadeOut)
1413 {
1414     if (!m_findIndicatorCallback)
1415         return;
1416 
1417     HBITMAP hbmp = 0;
1418     IntRect selectionRect;
1419 
1420     if (RefPtr<FindIndicator> findIndicator = prpFindIndicator) {
1421         if (ShareableBitmap* contentImage = findIndicator->contentImage()) {
1422             // Render the contentImage to an HBITMAP.
1423             void* bits;
1424             HDC hdc = ::CreateCompatibleDC(0);
1425             int width = contentImage->bounds().width();
1426             int height = contentImage->bounds().height();
1427             BitmapInfo bitmapInfo = BitmapInfo::create(contentImage->size());
1428 
1429             hbmp = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, static_cast<void**>(&bits), 0, 0);
1430             HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc, hbmp));
1431 #if USE(CG)
1432             RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(bits, width, height,
1433                 8, width * sizeof(RGBQUAD), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
1434 
1435             GraphicsContext graphicsContext(context.get());
1436             contentImage->paint(graphicsContext, IntPoint(), contentImage->bounds());
1437 #else
1438             // FIXME: Implement!
1439 #endif
1440 
1441             ::SelectObject(hdc, hbmpOld);
1442             ::DeleteDC(hdc);
1443         }
1444 
1445         selectionRect = IntRect(findIndicator->selectionRectInWindowCoordinates());
1446     }
1447 
1448     // The callback is responsible for calling ::DeleteObject(hbmp).
1449     (*m_findIndicatorCallback)(toAPI(this), hbmp, selectionRect, fadeOut, m_findIndicatorCallbackContext);
1450 }
1451 
setFindIndicatorCallback(WKViewFindIndicatorCallback callback,void * context)1452 void WebView::setFindIndicatorCallback(WKViewFindIndicatorCallback callback, void* context)
1453 {
1454     m_findIndicatorCallback = callback;
1455     m_findIndicatorCallbackContext = context;
1456 }
1457 
getFindIndicatorCallback(void ** context)1458 WKViewFindIndicatorCallback WebView::getFindIndicatorCallback(void** context)
1459 {
1460     if (context)
1461         *context = m_findIndicatorCallbackContext;
1462 
1463     return m_findIndicatorCallback;
1464 }
1465 
didCommitLoadForMainFrame(bool useCustomRepresentation)1466 void WebView::didCommitLoadForMainFrame(bool useCustomRepresentation)
1467 {
1468 }
1469 
didFinishLoadingDataForCustomRepresentation(const String & suggestedFilename,const CoreIPC::DataReference &)1470 void WebView::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
1471 {
1472 }
1473 
customRepresentationZoomFactor()1474 double WebView::customRepresentationZoomFactor()
1475 {
1476     return 1;
1477 }
1478 
setCustomRepresentationZoomFactor(double)1479 void WebView::setCustomRepresentationZoomFactor(double)
1480 {
1481 }
1482 
didChangeScrollbarsForMainFrame() const1483 void WebView::didChangeScrollbarsForMainFrame() const
1484 {
1485 }
1486 
findStringInCustomRepresentation(const String &,FindOptions,unsigned)1487 void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned)
1488 {
1489 }
1490 
countStringMatchesInCustomRepresentation(const String &,FindOptions,unsigned)1491 void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned)
1492 {
1493 }
1494 
setIsInWindow(bool isInWindow)1495 void WebView::setIsInWindow(bool isInWindow)
1496 {
1497     m_isInWindow = isInWindow;
1498     m_page->viewStateDidChange(WebPageProxy::ViewIsInWindow);
1499 }
1500 
setIsVisible(bool isVisible)1501 void WebView::setIsVisible(bool isVisible)
1502 {
1503     m_isVisible = isVisible;
1504 
1505     if (m_page)
1506         m_page->viewStateDidChange(WebPageProxy::ViewIsVisible);
1507 }
1508 
1509 #if USE(ACCELERATED_COMPOSITING)
1510 
enterAcceleratedCompositingMode(const LayerTreeContext &)1511 void WebView::enterAcceleratedCompositingMode(const LayerTreeContext&)
1512 {
1513     ASSERT(useNewDrawingArea());
1514     // FIXME: Implement.
1515     ASSERT_NOT_REACHED();
1516 }
1517 
exitAcceleratedCompositingMode()1518 void WebView::exitAcceleratedCompositingMode()
1519 {
1520     ASSERT(useNewDrawingArea());
1521     // FIXME: Implement.
1522     ASSERT_NOT_REACHED();
1523 }
1524 
1525 #endif // USE(ACCELERATED_COMPOSITING)
1526 
nativeWindow()1527 HWND WebView::nativeWindow()
1528 {
1529     return m_window;
1530 }
1531 
scheduleChildWindowGeometryUpdate(HWND window,const WebCore::IntRect & rectInParentClientCoordinates,const WebCore::IntRect & clipRectInChildClientCoordinates)1532 void WebView::scheduleChildWindowGeometryUpdate(HWND window, const WebCore::IntRect& rectInParentClientCoordinates, const WebCore::IntRect& clipRectInChildClientCoordinates)
1533 {
1534     ChildWindowGeometry geometry;
1535     geometry.rectInParentClientCoordinates = rectInParentClientCoordinates;
1536     geometry.clipRectInChildClientCoordinates = clipRectInChildClientCoordinates;
1537 
1538     m_childWindowGeometriesToUpdate.set(window, geometry);
1539 }
1540 
setWindowRegion(HWND window,PassOwnPtr<HRGN> popRegion)1541 static void setWindowRegion(HWND window, PassOwnPtr<HRGN> popRegion)
1542 {
1543     OwnPtr<HRGN> region = popRegion;
1544 
1545     if (!::SetWindowRgn(window, region.get(), TRUE))
1546         return;
1547 
1548     // Windows owns the region now.
1549     region.leakPtr();
1550 }
1551 
updateChildWindowGeometries()1552 void WebView::updateChildWindowGeometries()
1553 {
1554     HashMap<HWND, ChildWindowGeometry> geometriesToUpdate;
1555     geometriesToUpdate.swap(m_childWindowGeometriesToUpdate);
1556 
1557     HDWP deferWindowPos = ::BeginDeferWindowPos(geometriesToUpdate.size());
1558 
1559     HashMap<HWND, ChildWindowGeometry>::const_iterator end = geometriesToUpdate.end();
1560     for (HashMap<HWND, ChildWindowGeometry>::const_iterator it = geometriesToUpdate.begin(); it != end; ++it) {
1561         HWND window = it->first;
1562         if (!::IsWindow(window))
1563             continue;
1564 
1565         const ChildWindowGeometry& geometry = it->second;
1566 
1567         const IntRect& windowRect = geometry.rectInParentClientCoordinates;
1568         deferWindowPos = ::DeferWindowPos(deferWindowPos, window, 0, windowRect.x(), windowRect.y(), windowRect.width(), windowRect.height(), SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
1569 
1570         const IntRect& clipRect = geometry.clipRectInChildClientCoordinates;
1571         setWindowRegion(window, adoptPtr(::CreateRectRgn(clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY())));
1572     }
1573 
1574     ::EndDeferWindowPos(deferWindowPos);
1575 }
1576 
1577 // WebCore::WindowMessageListener
1578 
windowReceivedMessage(HWND,UINT message,WPARAM wParam,LPARAM)1579 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
1580 {
1581     switch (message) {
1582     case WM_NCACTIVATE:
1583         updateActiveStateSoon();
1584         break;
1585     case WM_SETTINGCHANGE:
1586         // systemParameterChanged(wParam);
1587         break;
1588     }
1589 }
1590 
QueryInterface(REFIID riid,void ** ppvObject)1591 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
1592 {
1593     *ppvObject = 0;
1594     if (IsEqualGUID(riid, IID_IUnknown))
1595         *ppvObject = static_cast<IUnknown*>(this);
1596     else if (IsEqualGUID(riid, IID_IDropTarget))
1597         *ppvObject = static_cast<IDropTarget*>(this);
1598     else
1599         return E_NOINTERFACE;
1600 
1601     AddRef();
1602     return S_OK;
1603 }
1604 
AddRef(void)1605 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
1606 {
1607     ref();
1608     return refCount();
1609 }
1610 
Release(void)1611 ULONG STDMETHODCALLTYPE WebView::Release(void)
1612 {
1613     deref();
1614     return refCount();
1615 }
1616 
dragOperationToDragCursor(DragOperation op)1617 static DWORD dragOperationToDragCursor(DragOperation op)
1618 {
1619     DWORD res = DROPEFFECT_NONE;
1620     if (op & DragOperationCopy)
1621         res = DROPEFFECT_COPY;
1622     else if (op & DragOperationLink)
1623         res = DROPEFFECT_LINK;
1624     else if (op & DragOperationMove)
1625         res = DROPEFFECT_MOVE;
1626     else if (op & DragOperationGeneric)
1627         res = DROPEFFECT_MOVE; // This appears to be the Firefox behaviour
1628     return res;
1629 }
1630 
keyStateToDragOperation(DWORD grfKeyState) const1631 WebCore::DragOperation WebView::keyStateToDragOperation(DWORD grfKeyState) const
1632 {
1633     if (!m_page)
1634         return DragOperationNone;
1635 
1636     // Conforms to Microsoft's key combinations as documented for
1637     // IDropTarget::DragOver. Note, grfKeyState is the current
1638     // state of the keyboard modifier keys on the keyboard. See:
1639     // <http://msdn.microsoft.com/en-us/library/ms680129(VS.85).aspx>.
1640     DragOperation operation = m_page->dragOperation();
1641 
1642     if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT))
1643         operation = DragOperationLink;
1644     else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
1645         operation = DragOperationCopy;
1646     else if ((grfKeyState & MK_SHIFT) == MK_SHIFT)
1647         operation = DragOperationGeneric;
1648 
1649     return operation;
1650 }
1651 
DragEnter(IDataObject * pDataObject,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)1652 HRESULT STDMETHODCALLTYPE WebView::DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1653 {
1654     m_dragData = 0;
1655     m_page->resetDragOperation();
1656 
1657     if (m_dropTargetHelper)
1658         m_dropTargetHelper->DragEnter(m_window, pDataObject, (POINT*)&pt, *pdwEffect);
1659 
1660     POINTL localpt = pt;
1661     ::ScreenToClient(m_window, (LPPOINT)&localpt);
1662     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
1663     m_page->dragEntered(&data);
1664     *pdwEffect = dragOperationToDragCursor(m_page->dragOperation());
1665 
1666     m_lastDropEffect = *pdwEffect;
1667     m_dragData = pDataObject;
1668 
1669     return S_OK;
1670 }
1671 
DragOver(DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)1672 HRESULT STDMETHODCALLTYPE WebView::DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1673 {
1674     if (m_dropTargetHelper)
1675         m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
1676 
1677     if (m_dragData) {
1678         POINTL localpt = pt;
1679         ::ScreenToClient(m_window, (LPPOINT)&localpt);
1680         DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
1681         m_page->dragUpdated(&data);
1682         *pdwEffect = dragOperationToDragCursor(m_page->dragOperation());
1683     } else
1684         *pdwEffect = DROPEFFECT_NONE;
1685 
1686     m_lastDropEffect = *pdwEffect;
1687     return S_OK;
1688 }
1689 
DragLeave()1690 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
1691 {
1692     if (m_dropTargetHelper)
1693         m_dropTargetHelper->DragLeave();
1694 
1695     if (m_dragData) {
1696         DragData data(m_dragData.get(), IntPoint(), IntPoint(), DragOperationNone);
1697         m_page->dragExited(&data);
1698         m_dragData = 0;
1699         m_page->resetDragOperation();
1700     }
1701     return S_OK;
1702 }
1703 
Drop(IDataObject * pDataObject,DWORD grfKeyState,POINTL pt,DWORD * pdwEffect)1704 HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1705 {
1706     if (m_dropTargetHelper)
1707         m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
1708 
1709     m_dragData = 0;
1710     *pdwEffect = m_lastDropEffect;
1711     POINTL localpt = pt;
1712     ::ScreenToClient(m_window, (LPPOINT)&localpt);
1713     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
1714 
1715     SandboxExtension::Handle sandboxExtensionHandle;
1716     m_page->performDrag(&data, String(), sandboxExtensionHandle);
1717     return S_OK;
1718 }
1719 
1720 #if ENABLE(FULLSCREEN_API)
fullScreenController()1721 FullScreenController* WebView::fullScreenController()
1722 {
1723     if (!m_fullScreenController)
1724         m_fullScreenController = adoptPtr(new FullScreenController(this));
1725     return m_fullScreenController.get();
1726 }
1727 
fullScreenClientWindow() const1728 HWND WebView::fullScreenClientWindow() const
1729 {
1730     return m_window;
1731 }
1732 
fullScreenClientParentWindow() const1733 HWND WebView::fullScreenClientParentWindow() const
1734 {
1735     return ::GetParent(m_window);
1736 }
1737 
fullScreenClientSetParentWindow(HWND hostWindow)1738 void WebView::fullScreenClientSetParentWindow(HWND hostWindow)
1739 {
1740     setParentWindow(hostWindow);
1741 }
1742 
fullScreenClientWillEnterFullScreen()1743 void WebView::fullScreenClientWillEnterFullScreen()
1744 {
1745     page()->fullScreenManager()->willEnterFullScreen();
1746 }
1747 
fullScreenClientDidEnterFullScreen()1748 void WebView::fullScreenClientDidEnterFullScreen()
1749 {
1750     page()->fullScreenManager()->didEnterFullScreen();
1751 }
1752 
fullScreenClientWillExitFullScreen()1753 void WebView::fullScreenClientWillExitFullScreen()
1754 {
1755     page()->fullScreenManager()->willExitFullScreen();
1756 }
1757 
fullScreenClientDidExitFullScreen()1758 void WebView::fullScreenClientDidExitFullScreen()
1759 {
1760     page()->fullScreenManager()->didExitFullScreen();
1761 }
1762 
1763 #endif
1764 } // namespace WebKit
1765