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