Fix Windows build.
[WebKit-https.git] / Source / WebKit2 / UIProcess / win / WebView.cpp
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 "FindIndicator.h"
31 #include "LayerBackedDrawingAreaProxy.h"
32 #include "Logging.h"
33 #include "NativeWebKeyboardEvent.h"
34 #include "RunLoop.h"
35 #include "WKAPICast.h"
36 #include "WebContext.h"
37 #include "WebContextMenuProxyWin.h"
38 #include "WebEditCommandProxy.h"
39 #include "WebEventFactory.h"
40 #include "WebPageProxy.h"
41 #include "WebPopupMenuProxyWin.h"
42 #include <Commctrl.h>
43 #include <WebCore/BitmapInfo.h>
44 #include <WebCore/Cursor.h>
45 #include <WebCore/FloatRect.h>
46 #include <WebCore/GraphicsContextCG.h>
47 #include <WebCore/IntRect.h>
48 #include <WebCore/SoftLinking.h>
49 #include <WebCore/WebCoreInstanceHandle.h>
50 #include <WebCore/WindowMessageBroadcaster.h>
51 #include <wtf/text/WTFString.h>
52
53 namespace Ime {
54 // We need these functions in a separate namespace, because in the global namespace they conflict
55 // with the definitions in imm.h only by the type modifier (the macro defines them as static) and
56 // imm.h is included by windows.h
57 SOFT_LINK_LIBRARY(IMM32)
58 SOFT_LINK(IMM32, ImmGetContext, HIMC, WINAPI, (HWND hwnd), (hwnd))
59 SOFT_LINK(IMM32, ImmReleaseContext, BOOL, WINAPI, (HWND hWnd, HIMC hIMC), (hWnd, hIMC))
60 SOFT_LINK(IMM32, ImmGetCompositionStringW, LONG, WINAPI, (HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen), (hIMC, dwIndex, lpBuf, dwBufLen))
61 SOFT_LINK(IMM32, ImmSetCandidateWindow, BOOL, WINAPI, (HIMC hIMC, LPCANDIDATEFORM lpCandidate), (hIMC, lpCandidate))
62 SOFT_LINK(IMM32, ImmSetOpenStatus, BOOL, WINAPI, (HIMC hIMC, BOOL fOpen), (hIMC, fOpen))
63 SOFT_LINK(IMM32, ImmNotifyIME, BOOL, WINAPI, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue), (hIMC, dwAction, dwIndex, dwValue))
64 SOFT_LINK(IMM32, ImmAssociateContextEx, BOOL, WINAPI, (HWND hWnd, HIMC hIMC, DWORD dwFlags), (hWnd, hIMC, dwFlags))
65 };
66
67 using namespace WebCore;
68
69 namespace WebKit {
70
71 static const LPCWSTR kWebKit2WebViewWindowClassName = L"WebKit2WebViewWindowClass";
72
73 // Constants not available on all platforms.
74 const int WM_XP_THEMECHANGED = 0x031A;
75 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
76
77 static const int kMaxToolTipWidth = 250;
78
79 enum {
80     UpdateActiveStateTimer = 1,
81 };
82
83 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
84 {
85     LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
86     
87     if (WebView* webView = reinterpret_cast<WebView*>(longPtr))
88         return webView->wndProc(hWnd, message, wParam, lParam);
89
90     if (message == WM_CREATE) {
91         LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
92
93         // Associate the WebView with the window.
94         ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
95         return 0;
96     }
97
98     return ::DefWindowProc(hWnd, message, wParam, lParam);
99 }
100
101 LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
102 {
103     LRESULT lResult = 0;
104     bool handled = true;
105
106     switch (message) {
107     case WM_CLOSE:
108         m_page->tryClose();
109         break;
110     case WM_DESTROY:
111         m_isBeingDestroyed = true;
112         close();
113         break;
114     case WM_ERASEBKGND:
115         lResult = 1;
116         break;
117     case WM_PAINT:
118         lResult = onPaintEvent(hWnd, message, wParam, lParam, handled);
119         break;
120     case WM_PRINTCLIENT:
121         lResult = onPrintClientEvent(hWnd, message, wParam, lParam, handled);
122         break;
123     case WM_MOUSEACTIVATE:
124         setWasActivatedByMouseEvent(true);
125         handled = false;
126         break;
127     case WM_MOUSEMOVE:
128     case WM_LBUTTONDOWN:
129     case WM_MBUTTONDOWN:
130     case WM_RBUTTONDOWN:
131     case WM_LBUTTONDBLCLK:
132     case WM_MBUTTONDBLCLK:
133     case WM_RBUTTONDBLCLK:
134     case WM_LBUTTONUP:
135     case WM_MBUTTONUP:
136     case WM_RBUTTONUP:
137     case WM_MOUSELEAVE:
138         lResult = onMouseEvent(hWnd, message, wParam, lParam, handled);
139         break;
140     case WM_MOUSEWHEEL:
141     case WM_VISTA_MOUSEHWHEEL:
142         lResult = onWheelEvent(hWnd, message, wParam, lParam, handled);
143         break;
144     case WM_SYSKEYDOWN:
145     case WM_KEYDOWN:
146     case WM_SYSCHAR:
147     case WM_CHAR:
148     case WM_SYSKEYUP:
149     case WM_KEYUP:
150         lResult = onKeyEvent(hWnd, message, wParam, lParam, handled);
151         break;
152     case WM_SIZE:
153         lResult = onSizeEvent(hWnd, message, wParam, lParam, handled);
154         break;
155     case WM_WINDOWPOSCHANGED:
156         lResult = onWindowPositionChangedEvent(hWnd, message, wParam, lParam, handled);
157         break;
158     case WM_SETFOCUS:
159         lResult = onSetFocusEvent(hWnd, message, wParam, lParam, handled);
160         break;
161     case WM_KILLFOCUS:
162         lResult = onKillFocusEvent(hWnd, message, wParam, lParam, handled);
163         break;
164     case WM_TIMER:
165         lResult = onTimerEvent(hWnd, message, wParam, lParam, handled);
166         break;
167     case WM_SHOWWINDOW:
168         lResult = onShowWindowEvent(hWnd, message, wParam, lParam, handled);
169         break;
170     case WM_SETCURSOR:
171         lResult = onSetCursor(hWnd, message, wParam, lParam, handled);
172         break;
173     case WM_IME_STARTCOMPOSITION:
174         handled = onIMEStartComposition();
175         break;
176     case WM_IME_REQUEST:
177         lResult = onIMERequest(wParam, lParam);
178         break;
179     case WM_IME_COMPOSITION:
180         handled = onIMEComposition(lParam);
181         break;
182     case WM_IME_ENDCOMPOSITION:
183         handled = onIMEEndComposition();
184         break;
185     case WM_IME_SELECT:
186         handled = onIMESelect(wParam, lParam);
187         break;
188     case WM_IME_SETCONTEXT:
189         handled = onIMESetContext(wParam, lParam);
190         break;
191     default:
192         handled = false;
193         break;
194     }
195
196     if (!handled)
197         lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
198
199     return lResult;
200 }
201
202 bool WebView::registerWebViewWindowClass()
203 {
204     static bool haveRegisteredWindowClass = false;
205     if (haveRegisteredWindowClass)
206         return true;
207     haveRegisteredWindowClass = true;
208
209     WNDCLASSEX wcex;
210
211     wcex.cbSize = sizeof(WNDCLASSEX);
212     wcex.style          = CS_DBLCLKS;
213     wcex.lpfnWndProc    = WebView::WebViewWndProc;
214     wcex.cbClsExtra     = 0;
215     wcex.cbWndExtra     = sizeof(WebView*);
216     wcex.hInstance      = instanceHandle();
217     wcex.hIcon          = 0;
218     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
219     wcex.hbrBackground  = 0;
220     wcex.lpszMenuName   = 0;
221     wcex.lpszClassName  = kWebKit2WebViewWindowClassName;
222     wcex.hIconSm        = 0;
223
224     return !!::RegisterClassEx(&wcex);
225 }
226
227 WebView::WebView(RECT rect, WebContext* context, WebPageGroup* pageGroup, HWND parentWindow)
228     : m_topLevelParentWindow(0)
229     , m_toolTipWindow(0)
230     , m_lastCursorSet(0)
231     , m_webCoreCursor(0)
232     , m_overrideCursor(0)
233     , m_trackingMouseLeave(false)
234     , m_isInWindow(false)
235     , m_isVisible(false)
236     , m_wasActivatedByMouseEvent(false)
237     , m_isBeingDestroyed(false)
238     , m_inIMEComposition(0)
239     , m_findIndicatorCallback(0)
240     , m_findIndicatorCallbackContext(0)
241 {
242     registerWebViewWindowClass();
243
244     m_page = context->createWebPage(this, pageGroup);
245
246     m_window = ::CreateWindowEx(0, kWebKit2WebViewWindowClassName, 0, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
247         rect.top, rect.left, rect.right - rect.left, rect.bottom - rect.top, parentWindow ? parentWindow : HWND_MESSAGE, 0, instanceHandle(), this);
248     ASSERT(::IsWindow(m_window));
249
250     m_page->initializeWebPage();
251
252     CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper, (void**)&m_dropTargetHelper);
253
254     ::ShowWindow(m_window, SW_SHOW);
255
256     // FIXME: Initializing the tooltip window here matches WebKit win, but seems like something
257     // we could do on demand to save resources.
258     initializeToolTipWindow();
259
260     // Initialize the top level parent window and register it with the WindowMessageBroadcaster.
261     windowAncestryDidChange();
262 }
263
264 WebView::~WebView()
265 {
266     // Tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD.
267     if (::IsWindow(m_toolTipWindow))
268         ::DestroyWindow(m_toolTipWindow);
269 }
270
271 void WebView::initialize()
272 {
273     ::RegisterDragDrop(m_window, this);
274 }
275
276 void WebView::setParentWindow(HWND parentWindow)
277 {
278     if (m_window) {
279         // If the host window hasn't changed, bail.
280         if (::GetParent(m_window) == parentWindow)
281             return;
282         if (parentWindow)
283             ::SetParent(m_window, parentWindow);
284         else if (!m_isBeingDestroyed) {
285             // Turn the WebView into a message-only window so it will no longer be a child of the
286             // old parent window and will be hidden from screen. We only do this when
287             // isBeingDestroyed() is false because doing this while handling WM_DESTROY can leave
288             // m_window in a weird state (see <http://webkit.org/b/29337>).
289             ::SetParent(m_window, HWND_MESSAGE);
290         }
291     }
292
293     windowAncestryDidChange();
294 }
295
296 static HWND findTopLevelParentWindow(HWND window)
297 {
298     if (!window)
299         return 0;
300
301     HWND current = window;
302     for (HWND parent = GetParent(current); current; current = parent, parent = GetParent(parent)) {
303         if (!parent || !(GetWindowLongPtr(current, GWL_STYLE) & (WS_POPUP | WS_CHILD)))
304             return current;
305     }
306     ASSERT_NOT_REACHED();
307     return 0;
308 }
309
310 void WebView::windowAncestryDidChange()
311 {
312     HWND newTopLevelParentWindow;
313     if (m_window)
314         newTopLevelParentWindow = findTopLevelParentWindow(m_window);
315     else {
316         // There's no point in tracking active state changes of our parent window if we don't have
317         // a window ourselves.
318         newTopLevelParentWindow = 0;
319     }
320
321     if (newTopLevelParentWindow == m_topLevelParentWindow)
322         return;
323
324     if (m_topLevelParentWindow)
325         WindowMessageBroadcaster::removeListener(m_topLevelParentWindow, this);
326
327     m_topLevelParentWindow = newTopLevelParentWindow;
328
329     if (m_topLevelParentWindow)
330         WindowMessageBroadcaster::addListener(m_topLevelParentWindow, this);
331
332     updateActiveState();
333 }
334
335 LRESULT WebView::onMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
336 {
337     WebMouseEvent mouseEvent = WebEventFactory::createWebMouseEvent(hWnd, message, wParam, lParam, m_wasActivatedByMouseEvent);
338     setWasActivatedByMouseEvent(false);
339     
340     switch (message) {
341     case WM_LBUTTONDOWN:
342     case WM_MBUTTONDOWN:
343     case WM_RBUTTONDOWN:
344         ::SetFocus(m_window);
345         ::SetCapture(m_window);
346         break; 
347     case WM_LBUTTONUP:
348     case WM_MBUTTONUP:
349     case WM_RBUTTONUP:
350         ::ReleaseCapture();
351         break;
352     case WM_MOUSEMOVE:
353         startTrackingMouseLeave();
354         break;
355     case WM_MOUSELEAVE:
356         stopTrackingMouseLeave();
357         break;
358     case WM_LBUTTONDBLCLK:
359     case WM_MBUTTONDBLCLK:
360     case WM_RBUTTONDBLCLK:
361         break;
362     default:
363         ASSERT_NOT_REACHED();
364     }
365
366     m_page->handleMouseEvent(mouseEvent);
367
368     handled = true;
369     return 0;
370 }
371
372 LRESULT WebView::onWheelEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
373 {
374     WebWheelEvent wheelEvent = WebEventFactory::createWebWheelEvent(hWnd, message, wParam, lParam);
375     if (wheelEvent.controlKey()) {
376         // We do not want WebKit to handle Control + Wheel, this should be handled by the client application
377         // to zoom the page.
378         handled = false;
379         return 0;
380     }
381
382     m_page->handleWheelEvent(wheelEvent);
383
384     handled = true;
385     return 0;
386 }
387
388 LRESULT WebView::onKeyEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
389 {
390     m_page->handleKeyboardEvent(NativeWebKeyboardEvent(hWnd, message, wParam, lParam));
391
392     // We claim here to always have handled the event. If the event is not in fact handled, we will
393     // find out later in didNotHandleKeyEvent.
394     handled = true;
395     return 0;
396 }
397
398 LRESULT WebView::onPaintEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled)
399 {
400     PAINTSTRUCT paintStruct;
401     HDC hdc = ::BeginPaint(m_window, &paintStruct);
402
403     if (m_page->isValid() && m_page->drawingArea() && m_page->drawingArea()->paint(IntRect(paintStruct.rcPaint), hdc))
404         m_page->didDraw();
405     else {
406         // Mac checks WebPageProxy::drawsBackground and
407         // WebPageProxy::drawsTransparentBackground here, but those are always false on Windows
408         // currently (see <http://webkit.org/b/52009>).
409         ::FillRect(hdc, &paintStruct.rcPaint, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
410     }
411
412     ::EndPaint(m_window, &paintStruct);
413
414     handled = true;
415     return 0;
416 }
417
418 LRESULT WebView::onPrintClientEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
419 {
420     HDC hdc = reinterpret_cast<HDC>(wParam);
421     RECT winRect;
422     ::GetClientRect(hWnd, &winRect);
423     IntRect rect = winRect;
424
425     m_page->drawingArea()->paint(rect, hdc);
426
427     handled = true;
428     return 0;
429 }
430
431 LRESULT WebView::onSizeEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
432 {
433     int width = LOWORD(lParam);
434     int height = HIWORD(lParam);
435
436     if (m_page->drawingArea())
437         m_page->drawingArea()->setSize(IntSize(width, height));
438
439     handled = true;
440     return 0;
441 }
442
443 LRESULT WebView::onWindowPositionChangedEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
444 {
445     if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
446         updateActiveStateSoon();
447
448     handled = false;
449     return 0;
450 }
451
452 LRESULT WebView::onSetFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
453 {
454     m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
455     handled = true;
456     return 0;
457 }
458
459 LRESULT WebView::onKillFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
460 {
461     m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
462     handled = true;
463     return 0;
464 }
465
466 LRESULT WebView::onTimerEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
467 {
468     switch (wParam) {
469     case UpdateActiveStateTimer:
470         ::KillTimer(hWnd, UpdateActiveStateTimer);
471         updateActiveState();
472         break;
473     }
474
475     handled = true;
476     return 0;
477 }
478
479 LRESULT WebView::onShowWindowEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
480 {
481     // lParam is 0 when the message is sent because of a ShowWindow call.
482     // FIXME: Is WM_SHOWWINDOW sent when ShowWindow is called on an ancestor of our window?
483     if (!lParam) {
484         m_isVisible = wParam;
485         m_page->viewStateDidChange(WebPageProxy::ViewIsVisible);
486
487         handled = true;
488     }
489
490     return 0;
491 }
492
493 LRESULT WebView::onSetCursor(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
494 {
495     if (!m_lastCursorSet) {
496         handled = false;
497         return 0;
498     }
499
500     ::SetCursor(m_lastCursorSet);
501     return 0;
502 }
503
504 void WebView::updateActiveState()
505 {
506     m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
507 }
508
509 void WebView::updateActiveStateSoon()
510 {
511     // This function is called while processing the WM_NCACTIVATE message.
512     // While processing WM_NCACTIVATE when we are being deactivated, GetActiveWindow() will
513     // still return our window. If we were to call updateActiveState() in that case, we would
514     // wrongly think that we are still the active window. To work around this, we update our
515     // active state after a 0-delay timer fires, at which point GetActiveWindow() will return
516     // the newly-activated window.
517
518     ::SetTimer(m_window, UpdateActiveStateTimer, 0, 0);
519 }
520
521 static bool initCommonControls()
522 {
523     static bool haveInitialized = false;
524     if (haveInitialized)
525         return true;
526
527     INITCOMMONCONTROLSEX init;
528     init.dwSize = sizeof(init);
529     init.dwICC = ICC_TREEVIEW_CLASSES;
530     haveInitialized = !!::InitCommonControlsEx(&init);
531     return haveInitialized;
532 }
533
534 void WebView::initializeToolTipWindow()
535 {
536     if (!initCommonControls())
537         return;
538
539     m_toolTipWindow = ::CreateWindowEx(WS_EX_TRANSPARENT, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
540                                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
541                                        m_window, 0, 0, 0);
542     if (!m_toolTipWindow)
543         return;
544
545     TOOLINFO info = {0};
546     info.cbSize = sizeof(info);
547     info.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
548     info.uId = reinterpret_cast<UINT_PTR>(m_window);
549
550     ::SendMessage(m_toolTipWindow, TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&info));
551     ::SendMessage(m_toolTipWindow, TTM_SETMAXTIPWIDTH, 0, kMaxToolTipWidth);
552     ::SetWindowPos(m_toolTipWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
553 }
554
555 void WebView::startTrackingMouseLeave()
556 {
557     if (m_trackingMouseLeave)
558         return;
559     m_trackingMouseLeave = true;
560
561     TRACKMOUSEEVENT trackMouseEvent;
562     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
563     trackMouseEvent.dwFlags = TME_LEAVE;
564     trackMouseEvent.hwndTrack = m_window;
565
566     ::TrackMouseEvent(&trackMouseEvent);
567 }
568
569 void WebView::stopTrackingMouseLeave()
570 {
571     if (!m_trackingMouseLeave)
572         return;
573     m_trackingMouseLeave = false;
574
575     TRACKMOUSEEVENT trackMouseEvent;
576     trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
577     trackMouseEvent.dwFlags = TME_LEAVE | TME_CANCEL;
578     trackMouseEvent.hwndTrack = m_window;
579
580     ::TrackMouseEvent(&trackMouseEvent);
581 }
582
583 void WebView::close()
584 {
585     ::RevokeDragDrop(m_window);
586     setParentWindow(0);
587     m_page->close();
588 }
589
590 // PageClient
591
592 PassOwnPtr<DrawingAreaProxy> WebView::createDrawingAreaProxy()
593 {
594     return ChunkedUpdateDrawingAreaProxy::create(this, m_page.get());
595 }
596
597 void WebView::setViewNeedsDisplay(const WebCore::IntRect& rect)
598 {
599     RECT r = rect;
600     ::InvalidateRect(m_window, &r, false);
601 }
602
603 void WebView::displayView()
604 {
605     ::UpdateWindow(m_window);
606 }
607
608 void WebView::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
609 {
610     // FIXME: Actually scroll the view contents.
611     setViewNeedsDisplay(scrollRect);
612 }
613
614 WebCore::IntSize WebView::viewSize()
615 {
616     RECT clientRect;
617     GetClientRect(m_window, &clientRect);
618
619     return IntRect(clientRect).size();
620 }
621
622 bool WebView::isViewWindowActive()
623 {    
624     HWND activeWindow = ::GetActiveWindow();
625     return (activeWindow && m_topLevelParentWindow == findTopLevelParentWindow(activeWindow));
626 }
627
628 bool WebView::isViewFocused()
629 {
630     return ::GetFocus() == m_window;
631 }
632
633 bool WebView::isViewVisible()
634 {
635     return m_isVisible;
636 }
637
638 bool WebView::isViewInWindow()
639 {
640     return m_isInWindow;
641 }
642
643 void WebView::pageClosed()
644 {
645 }
646
647 void WebView::processDidCrash()
648 {
649     updateNativeCursor();
650     ::InvalidateRect(m_window, 0, TRUE);
651 }
652
653 void WebView::didRelaunchProcess()
654 {
655     updateNativeCursor();
656     ::InvalidateRect(m_window, 0, TRUE);
657 }
658
659 void WebView::takeFocus(bool)
660 {
661 }
662
663 void WebView::toolTipChanged(const String&, const String& newToolTip)
664 {
665     if (!m_toolTipWindow)
666         return;
667
668     if (!newToolTip.isEmpty()) {
669         // This is necessary because String::charactersWithNullTermination() is not const.
670         String toolTip = newToolTip;
671
672         TOOLINFO info = {0};
673         info.cbSize = sizeof(info);
674         info.uFlags = TTF_IDISHWND;
675         info.uId = reinterpret_cast<UINT_PTR>(m_window);
676         info.lpszText = const_cast<UChar*>(toolTip.charactersWithNullTermination());
677         ::SendMessage(m_toolTipWindow, TTM_UPDATETIPTEXT, 0, reinterpret_cast<LPARAM>(&info));
678     }
679
680     ::SendMessage(m_toolTipWindow, TTM_ACTIVATE, !newToolTip.isEmpty(), 0);
681 }
682
683 HCURSOR WebView::cursorToShow() const
684 {
685     if (!m_page->isValid())
686         return 0;
687
688     // We only show the override cursor if the default (arrow) cursor is showing.
689     static HCURSOR arrowCursor = ::LoadCursor(0, IDC_ARROW);
690     if (m_overrideCursor && m_webCoreCursor == arrowCursor)
691         return m_overrideCursor;
692
693     return m_webCoreCursor;
694 }
695
696 void WebView::updateNativeCursor()
697 {
698     m_lastCursorSet = cursorToShow();
699     if (!m_lastCursorSet)
700         return;
701     ::SetCursor(m_lastCursorSet);
702 }
703
704 void WebView::setCursor(const WebCore::Cursor& cursor)
705 {
706     if (!cursor.platformCursor()->nativeCursor())
707         return;
708     m_webCoreCursor = cursor.platformCursor()->nativeCursor();
709     updateNativeCursor();
710 }
711
712 void WebView::setOverrideCursor(HCURSOR overrideCursor)
713 {
714     m_overrideCursor = overrideCursor;
715     updateNativeCursor();
716 }
717
718 void WebView::setInitialFocus(bool forward)
719 {
720     m_page->setInitialFocus(forward);
721 }
722
723 void WebView::setViewportArguments(const WebCore::ViewportArguments&)
724 {
725 }
726
727 void WebView::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo)
728 {
729 }
730
731 void WebView::clearAllEditCommands()
732 {
733 }
734
735 void WebView::setEditCommandState(const String&, bool, int)
736 {
737 }
738
739 FloatRect WebView::convertToDeviceSpace(const FloatRect& rect)
740 {
741     return rect;
742 }
743
744 FloatRect WebView::convertToUserSpace(const FloatRect& rect)
745 {
746     return rect;
747 }
748
749 HIMC WebView::getIMMContext() 
750 {
751     return Ime::ImmGetContext(m_window);
752 }
753
754 void WebView::prepareCandidateWindow(HIMC hInputContext) 
755 {
756     IntRect caret = m_page->firstRectForCharacterInSelectedRange(0);
757     CANDIDATEFORM form;
758     form.dwIndex = 0;
759     form.dwStyle = CFS_EXCLUDE;
760     form.ptCurrentPos.x = caret.x();
761     form.ptCurrentPos.y = caret.bottom();
762     form.rcArea.top = caret.y();
763     form.rcArea.bottom = caret.bottom();
764     form.rcArea.left = caret.x();
765     form.rcArea.right = caret.right();
766     Ime::ImmSetCandidateWindow(hInputContext, &form);
767 }
768
769 void WebView::resetIME()
770 {
771     HIMC hInputContext = getIMMContext();
772     if (!hInputContext)
773         return;
774     Ime::ImmNotifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
775     Ime::ImmReleaseContext(m_window, hInputContext);
776 }
777
778 void WebView::setInputMethodState(bool enabled)
779 {
780     Ime::ImmAssociateContextEx(m_window, 0, enabled ? IACE_DEFAULT : 0);
781 }
782
783 void WebView::compositionSelectionChanged(bool hasChanged)
784 {
785     if (m_page->selectionState().hasComposition && !hasChanged)
786         resetIME();
787 }
788
789 bool WebView::onIMEStartComposition()
790 {
791     LOG(TextInput, "onIMEStartComposition");
792     m_inIMEComposition++;
793
794     HIMC hInputContext = getIMMContext();
795     if (!hInputContext)
796         return false;
797     prepareCandidateWindow(hInputContext);
798     Ime::ImmReleaseContext(m_window, hInputContext);
799     return true;
800 }
801
802 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
803 {
804     LONG compositionLength = Ime::ImmGetCompositionStringW(hInputContext, type, 0, 0);
805     if (compositionLength <= 0)
806         return false;
807     Vector<UChar> compositionBuffer(compositionLength / 2);
808     compositionLength = Ime::ImmGetCompositionStringW(hInputContext, type, compositionBuffer.data(), compositionLength);
809     result = String::adopt(compositionBuffer);
810     return true;
811 }
812
813 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
814 {
815     if (clauses.isEmpty()) {
816         underlines.clear();
817         return;
818     }
819   
820     size_t numBoundaries = clauses.size() - 1;
821     underlines.resize(numBoundaries);
822     for (unsigned i = 0; i < numBoundaries; ++i) {
823         underlines[i].startOffset = clauses[i];
824         underlines[i].endOffset = clauses[i + 1];
825         BYTE attribute = attributes[clauses[i]];
826         underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
827         underlines[i].color = Color::black;
828     }
829 }
830
831 #if !LOG_DISABLED
832 #define APPEND_ARGUMENT_NAME(name) \
833     if (lparam & name) { \
834         if (needsComma) \
835             result += ", "; \
836             result += #name; \
837         needsComma = true; \
838     }
839
840 static String imeCompositionArgumentNames(LPARAM lparam)
841 {
842     String result;
843     bool needsComma = false;
844
845     APPEND_ARGUMENT_NAME(GCS_COMPATTR);
846     APPEND_ARGUMENT_NAME(GCS_COMPCLAUSE);
847     APPEND_ARGUMENT_NAME(GCS_COMPREADSTR);
848     APPEND_ARGUMENT_NAME(GCS_COMPREADATTR);
849     APPEND_ARGUMENT_NAME(GCS_COMPREADCLAUSE);
850     APPEND_ARGUMENT_NAME(GCS_COMPSTR);
851     APPEND_ARGUMENT_NAME(GCS_CURSORPOS);
852     APPEND_ARGUMENT_NAME(GCS_DELTASTART);
853     APPEND_ARGUMENT_NAME(GCS_RESULTCLAUSE);
854     APPEND_ARGUMENT_NAME(GCS_RESULTREADCLAUSE);
855     APPEND_ARGUMENT_NAME(GCS_RESULTREADSTR);
856     APPEND_ARGUMENT_NAME(GCS_RESULTSTR);
857     APPEND_ARGUMENT_NAME(CS_INSERTCHAR);
858     APPEND_ARGUMENT_NAME(CS_NOMOVECARET);
859
860     return result;
861 }
862
863 static String imeRequestName(WPARAM wparam)
864 {
865     switch (wparam) {
866     case IMR_CANDIDATEWINDOW:
867         return "IMR_CANDIDATEWINDOW";
868     case IMR_COMPOSITIONFONT:
869         return "IMR_COMPOSITIONFONT";
870     case IMR_COMPOSITIONWINDOW:
871         return "IMR_COMPOSITIONWINDOW";
872     case IMR_CONFIRMRECONVERTSTRING:
873         return "IMR_CONFIRMRECONVERTSTRING";
874     case IMR_DOCUMENTFEED:
875         return "IMR_DOCUMENTFEED";
876     case IMR_QUERYCHARPOSITION:
877         return "IMR_QUERYCHARPOSITION";
878     case IMR_RECONVERTSTRING:
879         return "IMR_RECONVERTSTRING";
880     default:
881         return "Unknown (" + String::number(wparam) + ")";
882     }
883 }
884 #endif
885
886 bool WebView::onIMEComposition(LPARAM lparam)
887 {
888     LOG(TextInput, "onIMEComposition %s", imeCompositionArgumentNames(lparam).latin1().data());
889     HIMC hInputContext = getIMMContext();
890     if (!hInputContext)
891         return true;
892
893     if (!m_page->selectionState().isContentEditable)
894         return true;
895
896     prepareCandidateWindow(hInputContext);
897
898     if (lparam & GCS_RESULTSTR || !lparam) {
899         String compositionString;
900         if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
901             return true;
902         
903         m_page->confirmComposition(compositionString);
904         return true;
905     }
906
907     String compositionString;
908     if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
909         return true;
910     
911     // Composition string attributes
912     int numAttributes = Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPATTR, 0, 0);
913     Vector<BYTE> attributes(numAttributes);
914     Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPATTR, attributes.data(), numAttributes);
915
916     // Get clauses
917     int numBytes = Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPCLAUSE, 0, 0);
918     Vector<DWORD> clauses(numBytes / sizeof(DWORD));
919     Ime::ImmGetCompositionStringW(hInputContext, GCS_COMPCLAUSE, clauses.data(), numBytes);
920
921     Vector<CompositionUnderline> underlines;
922     compositionToUnderlines(clauses, attributes, underlines);
923
924     int cursorPosition = LOWORD(Ime::ImmGetCompositionStringW(hInputContext, GCS_CURSORPOS, 0, 0));
925
926     m_page->setComposition(compositionString, underlines, cursorPosition);
927
928     return true;
929 }
930
931 bool WebView::onIMEEndComposition()
932 {
933     LOG(TextInput, "onIMEEndComposition");
934     // If the composition hasn't been confirmed yet, it needs to be cancelled.
935     // This happens after deleting the last character from inline input hole.
936     if (m_page->selectionState().hasComposition)
937         m_page->confirmComposition(String());
938
939     if (m_inIMEComposition)
940         m_inIMEComposition--;
941
942     return true;
943 }
944
945 LRESULT WebView::onIMERequestCharPosition(IMECHARPOSITION* charPos)
946 {
947     if (charPos->dwCharPos && !m_page->selectionState().hasComposition)
948         return 0;
949     IntRect caret = m_page->firstRectForCharacterInSelectedRange(charPos->dwCharPos);
950     charPos->pt.x = caret.x();
951     charPos->pt.y = caret.y();
952     ::ClientToScreen(m_window, &charPos->pt);
953     charPos->cLineHeight = caret.height();
954     ::GetWindowRect(m_window, &charPos->rcDocument);
955     return true;
956 }
957
958 LRESULT WebView::onIMERequestReconvertString(RECONVERTSTRING* reconvertString)
959 {
960     String text = m_page->getSelectedText();
961     unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
962     
963     if (!reconvertString)
964         return totalSize;
965
966     if (totalSize > reconvertString->dwSize)
967         return 0;
968     reconvertString->dwCompStrLen = text.length();
969     reconvertString->dwStrLen = text.length();
970     reconvertString->dwTargetStrLen = text.length();
971     reconvertString->dwStrOffset = sizeof(RECONVERTSTRING);
972     memcpy(reconvertString + 1, text.characters(), text.length() * sizeof(UChar));
973     return totalSize;
974 }
975
976 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data)
977 {
978     LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data());
979     if (!m_page->selectionState().isContentEditable)
980         return 0;
981
982     switch (request) {
983     case IMR_RECONVERTSTRING:
984         return onIMERequestReconvertString(reinterpret_cast<RECONVERTSTRING*>(data));
985
986     case IMR_QUERYCHARPOSITION:
987         return onIMERequestCharPosition(reinterpret_cast<IMECHARPOSITION*>(data));
988     }
989     return 0;
990 }
991
992 bool WebView::onIMESelect(WPARAM wparam, LPARAM lparam)
993 {
994     UNUSED_PARAM(wparam);
995     UNUSED_PARAM(lparam);
996     LOG(TextInput, "onIMESelect locale %ld %s", lparam, wparam ? "select" : "deselect");
997     return false;
998 }
999
1000 bool WebView::onIMESetContext(WPARAM wparam, LPARAM)
1001 {
1002     LOG(TextInput, "onIMESetContext %s", wparam ? "active" : "inactive");
1003     return false;
1004 }
1005
1006 void WebView::didNotHandleKeyEvent(const NativeWebKeyboardEvent& event)
1007 {
1008     // Calling ::DefWindowProcW will ensure that pressing the Alt key will generate a WM_SYSCOMMAND
1009     // event, e.g. See <http://webkit.org/b/47671>.
1010     ::DefWindowProcW(event.nativeEvent()->hwnd, event.nativeEvent()->message, event.nativeEvent()->wParam, event.nativeEvent()->lParam);
1011 }
1012
1013 PassRefPtr<WebPopupMenuProxy> WebView::createPopupMenuProxy(WebPageProxy* page)
1014 {
1015     return WebPopupMenuProxyWin::create(this, page);
1016 }
1017
1018 PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy* page)
1019 {
1020     return WebContextMenuProxyWin::create(m_window, page);
1021 }
1022
1023 void WebView::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut)
1024 {
1025     if (!m_findIndicatorCallback)
1026         return;
1027     
1028     HBITMAP hbmp = 0;
1029     ShareableBitmap* contentImage = findIndicator->contentImage();
1030     
1031     if (contentImage) {
1032         // Render the contentImage to an HBITMAP.
1033         void* bits;
1034         HDC hdc = ::CreateCompatibleDC(0);
1035         int width = contentImage->bounds().width();
1036         int height = contentImage->bounds().height();
1037         BitmapInfo bitmapInfo = BitmapInfo::create(contentImage->size());
1038
1039         hbmp = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, static_cast<void**>(&bits), 0, 0);
1040         HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc, hbmp));
1041         RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(bits, width, height,
1042             8, width * sizeof(RGBQUAD), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
1043
1044         GraphicsContext graphicsContext(context.get());
1045         contentImage->paint(graphicsContext, IntPoint(), contentImage->bounds());
1046
1047         ::SelectObject(hdc, hbmpOld);
1048         ::DeleteDC(hdc);
1049     }
1050
1051     IntRect selectionRect(findIndicator->selectionRectInWindowCoordinates());
1052     
1053     // The callback is responsible for calling ::DeleteObject(hbmp).
1054     (*m_findIndicatorCallback)(toAPI(this), hbmp, selectionRect, fadeOut, m_findIndicatorCallbackContext);
1055 }
1056
1057 void WebView::setFindIndicatorCallback(WKViewFindIndicatorCallback callback, void* context)
1058 {
1059     m_findIndicatorCallback = callback;
1060     m_findIndicatorCallbackContext = context;
1061 }
1062
1063 WKViewFindIndicatorCallback WebView::getFindIndicatorCallback(void** context)
1064 {
1065     if (context)
1066         *context = m_findIndicatorCallbackContext;
1067     
1068     return m_findIndicatorCallback;
1069 }
1070
1071 void WebView::didCommitLoadForMainFrame(bool useCustomRepresentation)
1072 {
1073 }
1074
1075 void WebView::didFinishLoadingDataForCustomRepresentation(const CoreIPC::DataReference&)
1076 {
1077 }
1078
1079 double WebView::customRepresentationZoomFactor()
1080 {
1081     return 1;
1082 }
1083
1084 void WebView::setCustomRepresentationZoomFactor(double)
1085 {
1086 }
1087
1088 void WebView::setIsInWindow(bool isInWindow)
1089 {
1090     m_isInWindow = isInWindow;
1091     m_page->viewStateDidChange(WebPageProxy::ViewIsInWindow);
1092 }
1093
1094 #if USE(ACCELERATED_COMPOSITING)
1095
1096 void WebView::enterAcceleratedCompositingMode(const LayerTreeContext&)
1097 {
1098     // FIXME: Implement.
1099 }
1100
1101 void WebView::exitAcceleratedCompositingMode()
1102 {
1103     // FIXME: Implement.
1104 }
1105
1106 void WebView::pageDidEnterAcceleratedCompositing()
1107 {
1108     switchToDrawingAreaTypeIfNecessary(DrawingAreaInfo::LayerBacked);
1109 }
1110
1111 void WebView::pageDidLeaveAcceleratedCompositing()
1112 {
1113     switchToDrawingAreaTypeIfNecessary(DrawingAreaInfo::ChunkedUpdate);
1114 }
1115
1116 void WebView::switchToDrawingAreaTypeIfNecessary(DrawingAreaInfo::Type type)
1117 {
1118     DrawingAreaInfo::Type existingDrawingAreaType = m_page->drawingArea() ? m_page->drawingArea()->info().type : DrawingAreaInfo::None;
1119     if (existingDrawingAreaType == type)
1120         return;
1121
1122     OwnPtr<DrawingAreaProxy> newDrawingArea;
1123     switch (type) {
1124     case DrawingAreaInfo::None:
1125         break;
1126     case DrawingAreaInfo::ChunkedUpdate:
1127         newDrawingArea = ChunkedUpdateDrawingAreaProxy::create(this, m_page.get());
1128         break;
1129     case DrawingAreaInfo::LayerBacked:
1130         newDrawingArea = LayerBackedDrawingAreaProxy::create(this, m_page.get());
1131         break;
1132     }
1133
1134     if (m_page->drawingArea())
1135         newDrawingArea->setSize(m_page->drawingArea()->size());
1136
1137     m_page->drawingArea()->detachCompositingContext();
1138     m_page->setDrawingArea(newDrawingArea.release());
1139 }
1140
1141 #endif // USE(ACCELERATED_COMPOSITING)
1142
1143 HWND WebView::nativeWindow()
1144 {
1145     return m_window;
1146 }
1147
1148 // WebCore::WindowMessageListener
1149
1150 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
1151 {
1152     switch (message) {
1153     case WM_NCACTIVATE:
1154         updateActiveStateSoon();
1155         break;
1156     case WM_SETTINGCHANGE:
1157         // systemParameterChanged(wParam);
1158         break;
1159     }
1160 }
1161
1162 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
1163 {
1164     *ppvObject = 0;
1165     if (IsEqualGUID(riid, IID_IUnknown))
1166         *ppvObject = static_cast<IUnknown*>(this);
1167     else if (IsEqualGUID(riid, IID_IDropTarget))
1168         *ppvObject = static_cast<IDropTarget*>(this);
1169     else
1170         return E_NOINTERFACE;
1171
1172     AddRef();
1173     return S_OK;
1174 }
1175
1176 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
1177 {
1178     ref();
1179     return refCount();
1180 }
1181
1182 ULONG STDMETHODCALLTYPE WebView::Release(void)
1183 {
1184     deref();
1185     return refCount();
1186 }
1187
1188 static DWORD dragOperationToDragCursor(DragOperation op)
1189 {
1190     DWORD res = DROPEFFECT_NONE;
1191     if (op & DragOperationCopy) 
1192         res = DROPEFFECT_COPY;
1193     else if (op & DragOperationLink) 
1194         res = DROPEFFECT_LINK;
1195     else if (op & DragOperationMove) 
1196         res = DROPEFFECT_MOVE;
1197     else if (op & DragOperationGeneric) 
1198         res = DROPEFFECT_MOVE; // This appears to be the Firefox behaviour
1199     return res;
1200 }
1201
1202 WebCore::DragOperation WebView::keyStateToDragOperation(DWORD grfKeyState) const
1203 {
1204     if (!m_page)
1205         return DragOperationNone;
1206
1207     // Conforms to Microsoft's key combinations as documented for 
1208     // IDropTarget::DragOver. Note, grfKeyState is the current 
1209     // state of the keyboard modifier keys on the keyboard. See:
1210     // <http://msdn.microsoft.com/en-us/library/ms680129(VS.85).aspx>.
1211     DragOperation operation = m_page->dragOperation();
1212
1213     if ((grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT))
1214         operation = DragOperationLink;
1215     else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
1216         operation = DragOperationCopy;
1217     else if ((grfKeyState & MK_SHIFT) == MK_SHIFT)
1218         operation = DragOperationGeneric;
1219
1220     return operation;
1221 }
1222
1223 HRESULT STDMETHODCALLTYPE WebView::DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1224 {
1225     m_dragData = 0;
1226     m_page->resetDragOperation();
1227
1228     if (m_dropTargetHelper)
1229         m_dropTargetHelper->DragEnter(m_window, pDataObject, (POINT*)&pt, *pdwEffect);
1230
1231     POINTL localpt = pt;
1232     ::ScreenToClient(m_window, (LPPOINT)&localpt);
1233     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
1234     m_page->performDragControllerAction(DragControllerActionEntered, &data);
1235     *pdwEffect = dragOperationToDragCursor(m_page->dragOperation());
1236
1237     m_lastDropEffect = *pdwEffect;
1238     m_dragData = pDataObject;
1239
1240     return S_OK;
1241 }
1242
1243 HRESULT STDMETHODCALLTYPE WebView::DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1244 {
1245     if (m_dropTargetHelper)
1246         m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
1247
1248     if (m_dragData) {
1249         POINTL localpt = pt;
1250         ::ScreenToClient(m_window, (LPPOINT)&localpt);
1251         DragData data(m_dragData.get(), IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
1252         m_page->performDragControllerAction(DragControllerActionUpdated, &data);
1253         *pdwEffect = dragOperationToDragCursor(m_page->dragOperation());
1254     } else
1255         *pdwEffect = DROPEFFECT_NONE;
1256
1257     m_lastDropEffect = *pdwEffect;
1258     return S_OK;
1259 }
1260
1261 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
1262 {
1263     if (m_dropTargetHelper)
1264         m_dropTargetHelper->DragLeave();
1265
1266     if (m_dragData) {
1267         DragData data(m_dragData.get(), IntPoint(), IntPoint(), DragOperationNone);
1268         m_page->performDragControllerAction(DragControllerActionExited, &data);
1269         m_dragData = 0;
1270         m_page->resetDragOperation();
1271     }
1272     return S_OK;
1273 }
1274
1275 HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1276 {
1277     if (m_dropTargetHelper)
1278         m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
1279
1280     m_dragData = 0;
1281     *pdwEffect = m_lastDropEffect;
1282     POINTL localpt = pt;
1283     ::ScreenToClient(m_window, (LPPOINT)&localpt);
1284     DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState));
1285     m_page->performDragControllerAction(DragControllerActionPerformDrag, &data);
1286     return S_OK;
1287 }
1288
1289 } // namespace WebKit