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