2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "DrawingAreaProxyImpl.h"
30 #include "FindIndicator.h"
32 #include "NativeWebKeyboardEvent.h"
33 #include "NativeWebMouseEvent.h"
34 #include "NativeWebWheelEvent.h"
36 #include "WKAPICast.h"
38 #include "WKCACFViewWindow.h"
40 #include "WebContext.h"
41 #include "WebContextMenuProxyWin.h"
42 #include "WebEditCommandProxy.h"
43 #include "WebEventFactory.h"
44 #include "WebPageProxy.h"
45 #include "WebPopupMenuProxyWin.h"
47 #include <WebCore/BitmapInfo.h>
48 #include <WebCore/Cursor.h>
49 #include <WebCore/Editor.h>
50 #include <WebCore/FloatRect.h>
52 #include <WebCore/GraphicsContextCG.h>
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>
63 #if ENABLE(FULLSCREEN_API)
64 #include "WebFullScreenManagerProxy.h"
65 #include <WebCore/FullScreenController.h>
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))
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));
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));
93 using namespace WebCore;
97 static const LPCWSTR kWebKit2WebViewWindowClassName = L"WebKit2WebViewWindowClass";
99 // Constants not available on all platforms.
100 const int WM_XP_THEMECHANGED = 0x031A;
101 const int WM_VISTA_MOUSEHWHEEL = 0x020E;
103 static const int kMaxToolTipWidth = 250;
106 UpdateActiveStateTimer = 1,
109 LRESULT CALLBACK WebView::WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
111 LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
113 if (WebView* webView = reinterpret_cast<WebView*>(longPtr))
114 return webView->wndProc(hWnd, message, wParam, lParam);
116 if (message == WM_CREATE) {
117 LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
119 // Associate the WebView with the window.
120 ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
124 return ::DefWindowProc(hWnd, message, wParam, lParam);
127 LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
137 m_isBeingDestroyed = true;
144 lResult = onPaintEvent(hWnd, message, wParam, lParam, handled);
147 lResult = onPrintClientEvent(hWnd, message, wParam, lParam, handled);
149 case WM_MOUSEACTIVATE:
150 setWasActivatedByMouseEvent(true);
157 case WM_LBUTTONDBLCLK:
158 case WM_MBUTTONDBLCLK:
159 case WM_RBUTTONDBLCLK:
164 lResult = onMouseEvent(hWnd, message, wParam, lParam, handled);
167 case WM_VISTA_MOUSEHWHEEL:
168 lResult = onWheelEvent(hWnd, message, wParam, lParam, handled);
171 lResult = onHorizontalScroll(hWnd, message, wParam, lParam, handled);
174 lResult = onVerticalScroll(hWnd, message, wParam, lParam, handled);
176 case WM_GESTURENOTIFY:
177 lResult = onGestureNotify(hWnd, message, wParam, lParam, handled);
180 lResult = onGesture(hWnd, message, wParam, lParam, handled);
188 lResult = onKeyEvent(hWnd, message, wParam, lParam, handled);
191 lResult = onSizeEvent(hWnd, message, wParam, lParam, handled);
193 case WM_WINDOWPOSCHANGED:
194 lResult = onWindowPositionChangedEvent(hWnd, message, wParam, lParam, handled);
197 lResult = onSetFocusEvent(hWnd, message, wParam, lParam, handled);
200 lResult = onKillFocusEvent(hWnd, message, wParam, lParam, handled);
203 lResult = onTimerEvent(hWnd, message, wParam, lParam, handled);
206 lResult = onShowWindowEvent(hWnd, message, wParam, lParam, handled);
209 lResult = onSetCursor(hWnd, message, wParam, lParam, handled);
211 case WM_IME_STARTCOMPOSITION:
212 handled = onIMEStartComposition();
215 lResult = onIMERequest(wParam, lParam);
217 case WM_IME_COMPOSITION:
218 handled = onIMEComposition(lParam);
220 case WM_IME_ENDCOMPOSITION:
221 handled = onIMEEndComposition();
224 handled = onIMESelect(wParam, lParam);
226 case WM_IME_SETCONTEXT:
227 handled = onIMESetContext(wParam, lParam);
235 lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
240 bool WebView::registerWebViewWindowClass()
242 static bool haveRegisteredWindowClass = false;
243 if (haveRegisteredWindowClass)
245 haveRegisteredWindowClass = true;
249 wcex.cbSize = sizeof(WNDCLASSEX);
250 wcex.style = CS_DBLCLKS;
251 wcex.lpfnWndProc = WebView::WebViewWndProc;
253 wcex.cbWndExtra = sizeof(WebView*);
254 wcex.hInstance = instanceHandle();
256 wcex.hCursor = ::LoadCursor(0, IDC_ARROW);
257 wcex.hbrBackground = 0;
258 wcex.lpszMenuName = 0;
259 wcex.lpszClassName = kWebKit2WebViewWindowClassName;
262 return !!::RegisterClassEx(&wcex);
265 WebView::WebView(RECT rect, WebContext* context, WebPageGroup* pageGroup, HWND parentWindow)
266 : m_topLevelParentWindow(0)
270 , m_overrideCursor(0)
271 , m_trackingMouseLeave(false)
272 , m_isInWindow(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)
283 , m_gestureReachedScrollingLimit(false)
284 #if USE(ACCELERATED_COMPOSITING)
285 , m_layerHostWindow(0)
288 registerWebViewWindowClass();
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));
298 m_page = context->createWebPage(this, pageGroup);
299 m_page->initializeWebPage();
301 CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, IID_IDropTargetHelper, (void**)&m_dropTargetHelper);
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();
307 // Initialize the top level parent window and register it with the WindowMessageBroadcaster.
308 windowAncestryDidChange();
310 #if ENABLE(FULLSCREEN_API)
311 m_page->fullScreenManager()->setWebView(this);
317 // Tooltip window needs to be explicitly destroyed since it isn't a WS_CHILD.
318 if (::IsWindow(m_toolTipWindow))
319 ::DestroyWindow(m_toolTipWindow);
322 void WebView::initialize()
324 ::RegisterDragDrop(m_window, this);
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);
336 void WebView::initializeUndoClient(const WKViewUndoClient* client)
338 m_undoClient.initialize(client);
341 void WebView::setParentWindow(HWND parentWindow)
344 // If the host window hasn't changed, bail.
345 if (::GetParent(m_window) == 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);
358 windowAncestryDidChange();
361 static HWND findTopLevelParentWindow(HWND window)
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)))
371 ASSERT_NOT_REACHED();
375 void WebView::windowAncestryDidChange()
377 HWND newTopLevelParentWindow;
379 newTopLevelParentWindow = findTopLevelParentWindow(m_window);
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;
386 if (newTopLevelParentWindow == m_topLevelParentWindow)
389 if (m_topLevelParentWindow)
390 WindowMessageBroadcaster::removeListener(m_topLevelParentWindow, this);
392 m_topLevelParentWindow = newTopLevelParentWindow;
394 if (m_topLevelParentWindow)
395 WindowMessageBroadcaster::addListener(m_topLevelParentWindow, this);
400 LRESULT WebView::onMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
402 NativeWebMouseEvent mouseEvent = NativeWebMouseEvent(hWnd, message, wParam, lParam, m_wasActivatedByMouseEvent);
403 setWasActivatedByMouseEvent(false);
409 ::SetFocus(m_window);
410 ::SetCapture(m_window);
418 startTrackingMouseLeave();
421 stopTrackingMouseLeave();
423 case WM_LBUTTONDBLCLK:
424 case WM_MBUTTONDBLCLK:
425 case WM_RBUTTONDBLCLK:
428 ASSERT_NOT_REACHED();
431 m_page->handleMouseEvent(mouseEvent);
437 LRESULT WebView::onWheelEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
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
447 m_page->handleWheelEvent(wheelEvent);
453 LRESULT WebView::onHorizontalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
455 ScrollDirection direction;
456 ScrollGranularity granularity;
457 switch (LOWORD(wParam)) {
459 granularity = ScrollByLine;
460 direction = ScrollLeft;
463 granularity = ScrollByLine;
464 direction = ScrollRight;
467 granularity = ScrollByDocument;
468 direction = ScrollLeft;
471 granularity = ScrollByDocument;
472 direction = ScrollRight;
479 m_page->scrollBy(direction, granularity);
485 LRESULT WebView::onVerticalScroll(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
487 ScrollDirection direction;
488 ScrollGranularity granularity;
489 switch (LOWORD(wParam)) {
491 granularity = ScrollByLine;
492 direction = ScrollDown;
495 granularity = ScrollByLine;
496 direction = ScrollUp;
499 granularity = ScrollByDocument;
500 direction = ScrollDown;
503 granularity = ScrollByDocument;
504 direction = ScrollUp;
511 m_page->scrollBy(direction, granularity);
517 LRESULT WebView::onGestureNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
519 // We shouldn't be getting any gesture messages without SetGestureConfig soft-linking correctly.
520 ASSERT(SetGestureConfigPtr());
522 GESTURENOTIFYSTRUCT* gn = reinterpret_cast<GESTURENOTIFYSTRUCT*>(lParam);
524 POINT localPoint = { gn->ptsLocation.x, gn->ptsLocation.y };
525 ::ScreenToClient(m_window, &localPoint);
527 bool canPan = m_page->gestureWillBegin(localPoint);
529 DWORD dwPanWant = GC_PAN | GC_PAN_WITH_INERTIA | GC_PAN_WITH_GUTTER;
530 DWORD dwPanBlock = GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
532 dwPanWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
534 dwPanBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
536 GESTURECONFIG gc = { GID_PAN, dwPanWant, dwPanBlock };
537 return SetGestureConfigPtr()(m_window, 0, 1, &gc, sizeof(gc));
540 LRESULT WebView::onGesture(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
542 ASSERT(GetGestureInfoPtr());
543 ASSERT(CloseGestureInfoHandlePtr());
544 ASSERT(UpdatePanningFeedbackPtr());
545 ASSERT(BeginPanningFeedbackPtr());
546 ASSERT(EndPanningFeedbackPtr());
548 if (!GetGestureInfoPtr() || !CloseGestureInfoHandlePtr() || !UpdatePanningFeedbackPtr() || !BeginPanningFeedbackPtr() || !EndPanningFeedbackPtr()) {
553 HGESTUREINFO gestureHandle = reinterpret_cast<HGESTUREINFO>(lParam);
554 GESTUREINFO gi = {0};
555 gi.cbSize = sizeof(GESTUREINFO);
557 if (!GetGestureInfoPtr()(gestureHandle, &gi)) {
564 m_lastPanX = gi.ptsLocation.x;
565 m_lastPanY = gi.ptsLocation.y;
568 m_page->gestureDidEnd();
571 int currentX = gi.ptsLocation.x;
572 int currentY = gi.ptsLocation.y;
574 // Reverse the calculations because moving your fingers up should move the screen down, and
576 int deltaX = m_lastPanX - currentX;
577 int deltaY = m_lastPanY - currentY;
579 m_lastPanX = currentX;
580 m_lastPanY = currentY;
582 // Calculate the overpan for window bounce.
583 m_overPanY -= deltaY;
585 if (deltaX || deltaY)
586 m_page->gestureDidScroll(IntSize(deltaX, deltaY));
588 if (gi.dwFlags & GF_BEGIN) {
589 BeginPanningFeedbackPtr()(m_window);
590 m_gestureReachedScrollingLimit = false;
592 } else if (gi.dwFlags & GF_END) {
593 EndPanningFeedbackPtr()(m_window, true);
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>.
600 if (m_gestureReachedScrollingLimit)
601 UpdatePanningFeedbackPtr()(m_window, 0, m_overPanY, gi.dwFlags & GF_INERTIA);
603 CloseGestureInfoHandlePtr()(gestureHandle);
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
620 LRESULT WebView::onKeyEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
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();
630 m_page->handleKeyboardEvent(NativeWebKeyboardEvent(hWnd, message, wParam, lParam));
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.
638 static void drawPageBackground(HDC dc, const WebPageProxy* page, const RECT& rect)
640 if (!page->drawsBackground() || page->drawsTransparentBackground())
643 ::FillRect(dc, &rect, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
646 void WebView::paint(HDC hdc, const IntRect& dirtyRect)
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);
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]);
660 drawPageBackground(hdc, m_page.get(), dirtyRect);
665 static void flashRects(HDC dc, const IntRect rects[], size_t rectCount, HBRUSH brush)
667 for (size_t i = 0; i < rectCount; ++i) {
668 RECT winRect = rects[i];
669 ::FillRect(dc, &winRect, brush);
676 static OwnPtr<HBRUSH> createBrush(const Color& color)
678 return adoptPtr(::CreateSolidBrush(RGB(color.red(), color.green(), color.blue())));
681 LRESULT WebView::onPaintEvent(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled)
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();
687 PAINTSTRUCT paintStruct;
688 HDC hdc = ::BeginPaint(m_window, &paintStruct);
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);
696 paint(hdc, paintStruct.rcPaint);
698 ::EndPaint(m_window, &paintStruct);
704 LRESULT WebView::onPrintClientEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
706 HDC hdc = reinterpret_cast<HDC>(wParam);
708 ::GetClientRect(hWnd, &winRect);
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.
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.
717 bool wasVisible = isViewVisible();
730 LRESULT WebView::onSizeEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
732 int width = LOWORD(lParam);
733 int height = HIWORD(lParam);
735 if (m_page && m_page->drawingArea()) {
736 m_page->drawingArea()->setSize(IntSize(width, height), m_nextResizeScrollOffset);
737 m_nextResizeScrollOffset = IntSize();
740 #if USE(ACCELERATED_COMPOSITING)
741 if (m_layerHostWindow)
742 ::MoveWindow(m_layerHostWindow, 0, 0, width, height, FALSE);
749 LRESULT WebView::onWindowPositionChangedEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
751 if (reinterpret_cast<WINDOWPOS*>(lParam)->flags & SWP_SHOWWINDOW)
752 updateActiveStateSoon();
758 LRESULT WebView::onSetFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
760 m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
765 LRESULT WebView::onKillFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool& handled)
767 m_page->viewStateDidChange(WebPageProxy::ViewIsFocused);
772 LRESULT WebView::onTimerEvent(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
775 case UpdateActiveStateTimer:
776 ::KillTimer(hWnd, UpdateActiveStateTimer);
785 LRESULT WebView::onShowWindowEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
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>
791 setIsVisible(wParam);
797 LRESULT WebView::onSetCursor(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
799 if (!m_lastCursorSet) {
804 ::SetCursor(m_lastCursorSet);
808 void WebView::updateActiveState()
810 m_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive);
813 void WebView::updateActiveStateSoon()
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.
822 ::SetTimer(m_window, UpdateActiveStateTimer, 0, 0);
825 static bool initCommonControls()
827 static bool haveInitialized = false;
831 INITCOMMONCONTROLSEX init;
832 init.dwSize = sizeof(init);
833 init.dwICC = ICC_TREEVIEW_CLASSES;
834 haveInitialized = !!::InitCommonControlsEx(&init);
835 return haveInitialized;
838 void WebView::initializeToolTipWindow()
840 if (!initCommonControls())
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,
846 if (!m_toolTipWindow)
850 info.cbSize = sizeof(info);
851 info.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
852 info.uId = reinterpret_cast<UINT_PTR>(m_window);
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);
859 void WebView::startTrackingMouseLeave()
861 if (m_trackingMouseLeave)
863 m_trackingMouseLeave = true;
865 TRACKMOUSEEVENT trackMouseEvent;
866 trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
867 trackMouseEvent.dwFlags = TME_LEAVE;
868 trackMouseEvent.hwndTrack = m_window;
870 ::TrackMouseEvent(&trackMouseEvent);
873 void WebView::stopTrackingMouseLeave()
875 if (!m_trackingMouseLeave)
877 m_trackingMouseLeave = false;
879 TRACKMOUSEEVENT trackMouseEvent;
880 trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
881 trackMouseEvent.dwFlags = TME_LEAVE | TME_CANCEL;
882 trackMouseEvent.hwndTrack = m_window;
884 ::TrackMouseEvent(&trackMouseEvent);
887 bool WebView::shouldInitializeTrackPointHack()
889 static bool shouldCreateScrollbars;
890 static bool hasRunTrackPointCheck;
892 if (hasRunTrackPointCheck)
893 return shouldCreateScrollbars;
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"
904 for (size_t i = 0; i < WTF_ARRAY_LENGTH(trackPointKeys); ++i) {
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;
914 return shouldCreateScrollbars;
917 void WebView::close()
919 m_undoClient.initialize(0);
920 ::RevokeDragDrop(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.
936 PassOwnPtr<DrawingAreaProxy> WebView::createDrawingAreaProxy()
938 return DrawingAreaProxyImpl::create(m_page.get());
941 void WebView::setViewNeedsDisplay(const WebCore::IntRect& rect)
944 ::InvalidateRect(m_window, &r, false);
947 void WebView::displayView()
949 ::UpdateWindow(m_window);
952 void WebView::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
954 // FIXME: Actually scroll the view contents.
955 setViewNeedsDisplay(scrollRect);
958 void WebView::flashBackingStoreUpdates(const Vector<IntRect>& updateRects)
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);
966 WebCore::IntSize WebView::viewSize()
969 GetClientRect(m_window, &clientRect);
971 return IntRect(clientRect).size();
974 bool WebView::isViewWindowActive()
976 HWND activeWindow = ::GetActiveWindow();
977 return (activeWindow && m_topLevelParentWindow == findTopLevelParentWindow(activeWindow));
980 bool WebView::isViewFocused()
982 return ::GetFocus() == m_window;
985 bool WebView::isViewVisible()
990 bool WebView::isViewInWindow()
995 void WebView::pageClosed()
999 void WebView::processDidCrash()
1001 updateNativeCursor();
1002 ::InvalidateRect(m_window, 0, TRUE);
1005 void WebView::didRelaunchProcess()
1007 updateNativeCursor();
1008 ::InvalidateRect(m_window, 0, TRUE);
1011 void WebView::toolTipChanged(const String&, const String& newToolTip)
1013 if (!m_toolTipWindow)
1016 if (!newToolTip.isEmpty()) {
1017 // This is necessary because String::charactersWithNullTermination() is not const.
1018 String toolTip = newToolTip;
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));
1028 ::SendMessage(m_toolTipWindow, TTM_ACTIVATE, !newToolTip.isEmpty(), 0);
1031 HCURSOR WebView::cursorToShow() const
1033 if (!m_page->isValid())
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;
1041 return m_webCoreCursor;
1044 void WebView::updateNativeCursor()
1046 m_lastCursorSet = cursorToShow();
1047 if (!m_lastCursorSet)
1049 ::SetCursor(m_lastCursorSet);
1052 void WebView::setCursor(const WebCore::Cursor& cursor)
1054 if (!cursor.platformCursor()->nativeCursor())
1056 m_webCoreCursor = cursor.platformCursor()->nativeCursor();
1057 updateNativeCursor();
1060 void WebView::setCursorHiddenUntilMouseMoves(bool)
1065 void WebView::setOverrideCursor(HCURSOR overrideCursor)
1067 m_overrideCursor = overrideCursor;
1068 updateNativeCursor();
1071 void WebView::setInitialFocus(bool forward)
1073 m_page->setInitialFocus(forward);
1076 void WebView::setScrollOffsetOnNextResize(const IntSize& scrollOffset)
1078 // The next time we get a WM_SIZE message, scroll by the specified amount in onSizeEvent().
1079 m_nextResizeScrollOffset = scrollOffset;
1082 void WebView::setViewportArguments(const WebCore::ViewportArguments&)
1086 void WebView::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo)
1088 RefPtr<WebEditCommandProxy> command = prpCommand;
1089 m_undoClient.registerEditCommand(this, command, undoOrRedo);
1092 void WebView::clearAllEditCommands()
1094 m_undoClient.clearAllEditCommands(this);
1097 bool WebView::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
1099 return m_undoClient.canUndoRedo(this, undoOrRedo);
1102 void WebView::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
1104 m_undoClient.executeUndoRedo(this, undoOrRedo);
1107 void WebView::reapplyEditCommand(WebEditCommandProxy* command)
1109 if (!m_page->isValid() || !m_page->isValidEditCommand(command))
1115 void WebView::unapplyEditCommand(WebEditCommandProxy* command)
1117 if (!m_page->isValid() || !m_page->isValidEditCommand(command))
1123 void WebView::setCustomDropTarget(IDropTarget* dropTarget)
1125 if (!m_page->isValid() || !m_window)
1128 ::RevokeDragDrop(m_window);
1131 ::RegisterDragDrop(m_window, dropTarget);
1133 ::RegisterDragDrop(m_window, this);
1136 FloatRect WebView::convertToDeviceSpace(const FloatRect& rect)
1141 IntPoint WebView::screenToWindow(const IntPoint& point)
1146 IntRect WebView::windowToScreen(const IntRect& rect)
1151 FloatRect WebView::convertToUserSpace(const FloatRect& rect)
1156 HIMC WebView::getIMMContext()
1158 return Ime::ImmGetContext(m_window);
1161 void WebView::prepareCandidateWindow(HIMC hInputContext)
1163 IntRect caret = m_page->firstRectForCharacterInSelectedRange(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);
1176 void WebView::resetIME()
1178 HIMC hInputContext = getIMMContext();
1181 Ime::ImmNotifyIME(hInputContext, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
1182 Ime::ImmReleaseContext(m_window, hInputContext);
1185 void WebView::setInputMethodState(bool enabled)
1187 Ime::ImmAssociateContextEx(m_window, 0, enabled ? IACE_DEFAULT : 0);
1190 void WebView::compositionSelectionChanged(bool hasChanged)
1192 if (m_page->editorState().hasComposition && !hasChanged)
1196 bool WebView::onIMEStartComposition()
1198 LOG(TextInput, "onIMEStartComposition");
1199 m_inIMEComposition++;
1201 HIMC hInputContext = getIMMContext();
1204 prepareCandidateWindow(hInputContext);
1205 Ime::ImmReleaseContext(m_window, hInputContext);
1209 static bool getCompositionString(HIMC hInputContext, DWORD type, String& result)
1211 LONG compositionLength = Ime::ImmGetCompositionStringW(hInputContext, type, 0, 0);
1212 if (compositionLength <= 0)
1214 Vector<UChar> compositionBuffer(compositionLength / 2);
1215 compositionLength = Ime::ImmGetCompositionStringW(hInputContext, type, compositionBuffer.data(), compositionLength);
1216 result = String::adopt(compositionBuffer);
1220 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
1222 if (clauses.isEmpty()) {
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;
1239 #define APPEND_ARGUMENT_NAME(name) \
1240 if (lparam & name) { \
1244 needsComma = true; \
1247 static String imeCompositionArgumentNames(LPARAM lparam)
1250 bool needsComma = false;
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);
1270 static String imeRequestName(WPARAM 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";
1288 return "Unknown (" + String::number(wparam) + ")";
1293 bool WebView::onIMEComposition(LPARAM lparam)
1295 LOG(TextInput, "onIMEComposition %s", imeCompositionArgumentNames(lparam).latin1().data());
1296 HIMC hInputContext = getIMMContext();
1300 if (!m_page->editorState().isContentEditable)
1303 prepareCandidateWindow(hInputContext);
1305 if (lparam & GCS_RESULTSTR || !lparam) {
1306 String compositionString;
1307 if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
1310 m_page->confirmComposition(compositionString);
1314 String compositionString;
1315 if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
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);
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);
1328 Vector<CompositionUnderline> underlines;
1329 compositionToUnderlines(clauses, attributes, underlines);
1331 int cursorPosition = LOWORD(Ime::ImmGetCompositionStringW(hInputContext, GCS_CURSORPOS, 0, 0));
1333 m_page->setComposition(compositionString, underlines, cursorPosition);
1338 bool WebView::onIMEEndComposition()
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());
1346 if (m_inIMEComposition)
1347 m_inIMEComposition--;
1352 LRESULT WebView::onIMERequestCharPosition(IMECHARPOSITION* charPos)
1354 if (charPos->dwCharPos && !m_page->editorState().hasComposition)
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);
1365 LRESULT WebView::onIMERequestReconvertString(RECONVERTSTRING* reconvertString)
1367 String text = m_page->getSelectedText();
1368 unsigned totalSize = sizeof(RECONVERTSTRING) + text.length() * sizeof(UChar);
1370 if (!reconvertString)
1373 if (totalSize > reconvertString->dwSize)
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));
1383 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data)
1385 LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data());
1386 if (!m_page->editorState().isContentEditable)
1390 case IMR_RECONVERTSTRING:
1391 return onIMERequestReconvertString(reinterpret_cast<RECONVERTSTRING*>(data));
1393 case IMR_QUERYCHARPOSITION:
1394 return onIMERequestCharPosition(reinterpret_cast<IMECHARPOSITION*>(data));
1399 bool WebView::onIMESelect(WPARAM wparam, LPARAM lparam)
1401 UNUSED_PARAM(wparam);
1402 UNUSED_PARAM(lparam);
1403 LOG(TextInput, "onIMESelect locale %ld %s", lparam, wparam ? "select" : "deselect");
1407 bool WebView::onIMESetContext(WPARAM wparam, LPARAM)
1409 LOG(TextInput, "onIMESetContext %s", wparam ? "active" : "inactive");
1413 void WebView::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled)
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);
1421 PassRefPtr<WebPopupMenuProxy> WebView::createPopupMenuProxy(WebPageProxy* page)
1423 return WebPopupMenuProxyWin::create(this, page);
1426 PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy* page)
1428 return WebContextMenuProxyWin::create(m_window, page);
1431 void WebView::setFindIndicator(PassRefPtr<FindIndicator> prpFindIndicator, bool fadeOut)
1433 if (!m_findIndicatorCallback)
1437 IntRect selectionRect;
1439 if (RefPtr<FindIndicator> findIndicator = prpFindIndicator) {
1440 if (ShareableBitmap* contentImage = findIndicator->contentImage()) {
1441 // Render the contentImage to an HBITMAP.
1443 HDC hdc = ::CreateCompatibleDC(0);
1444 int width = contentImage->bounds().width();
1445 int height = contentImage->bounds().height();
1446 BitmapInfo bitmapInfo = BitmapInfo::create(contentImage->size());
1448 hbmp = CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, static_cast<void**>(&bits), 0, 0);
1449 HBITMAP hbmpOld = static_cast<HBITMAP>(SelectObject(hdc, hbmp));
1451 RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(bits, width, height,
1452 8, width * sizeof(RGBQUAD), deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
1454 GraphicsContext graphicsContext(context.get());
1455 contentImage->paint(graphicsContext, IntPoint(), contentImage->bounds());
1457 // FIXME: Implement!
1460 ::SelectObject(hdc, hbmpOld);
1464 selectionRect = IntRect(findIndicator->selectionRectInWindowCoordinates());
1467 // The callback is responsible for calling ::DeleteObject(hbmp).
1468 (*m_findIndicatorCallback)(toAPI(this), hbmp, selectionRect, fadeOut, m_findIndicatorCallbackContext);
1471 void WebView::setFindIndicatorCallback(WKViewFindIndicatorCallback callback, void* context)
1473 m_findIndicatorCallback = callback;
1474 m_findIndicatorCallbackContext = context;
1477 WKViewFindIndicatorCallback WebView::getFindIndicatorCallback(void** context)
1480 *context = m_findIndicatorCallbackContext;
1482 return m_findIndicatorCallback;
1485 void WebView::didInstallOrUninstallPageOverlay(bool didInstall)
1487 m_pageOverlayInstalled = didInstall;
1490 void WebView::didCommitLoadForMainFrame(bool useCustomRepresentation)
1494 void WebView::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference&)
1498 double WebView::customRepresentationZoomFactor()
1503 void WebView::setCustomRepresentationZoomFactor(double)
1507 void WebView::didChangeScrollbarsForMainFrame() const
1511 void WebView::findStringInCustomRepresentation(const String&, FindOptions, unsigned)
1515 void WebView::countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned)
1519 void WebView::setIsInWindow(bool isInWindow)
1521 m_isInWindow = isInWindow;
1522 m_page->viewStateDidChange(WebPageProxy::ViewIsInWindow);
1525 void WebView::setIsVisible(bool isVisible)
1527 m_isVisible = isVisible;
1530 m_page->viewStateDidChange(WebPageProxy::ViewIsVisible);
1533 #if USE(ACCELERATED_COMPOSITING)
1535 void WebView::enterAcceleratedCompositingMode(const LayerTreeContext& context)
1538 ASSERT(!context.isEmpty());
1540 m_layerHostWindow = context.window;
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);
1546 ASSERT_NOT_REACHED();
1550 void WebView::exitAcceleratedCompositingMode()
1553 ASSERT(m_layerHostWindow);
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;
1560 ASSERT_NOT_REACHED();
1564 #endif // USE(ACCELERATED_COMPOSITING)
1566 HWND WebView::nativeWindow()
1571 void WebView::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
1573 m_geometriesUpdater.addPendingUpdate(geometry);
1576 void WebView::updateChildWindowGeometries()
1578 m_geometriesUpdater.updateGeometries(DoNotBringToTop);
1581 // WebCore::WindowMessageListener
1583 void WebView::windowReceivedMessage(HWND, UINT message, WPARAM wParam, LPARAM)
1587 updateActiveStateSoon();
1589 case WM_SETTINGCHANGE:
1590 // systemParameterChanged(wParam);
1595 HRESULT STDMETHODCALLTYPE WebView::QueryInterface(REFIID riid, void** ppvObject)
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);
1603 return E_NOINTERFACE;
1609 ULONG STDMETHODCALLTYPE WebView::AddRef(void)
1615 ULONG STDMETHODCALLTYPE WebView::Release(void)
1621 static DWORD dragOperationToDragCursor(DragOperation op)
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
1635 WebCore::DragOperation WebView::keyStateToDragOperation(DWORD grfKeyState) const
1638 return DragOperationNone;
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();
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;
1656 HRESULT STDMETHODCALLTYPE WebView::DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1659 m_page->resetDragOperation();
1661 if (m_dropTargetHelper)
1662 m_dropTargetHelper->DragEnter(m_window, pDataObject, (POINT*)&pt, *pdwEffect);
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());
1670 m_lastDropEffect = *pdwEffect;
1671 m_dragData = pDataObject;
1676 HRESULT STDMETHODCALLTYPE WebView::DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1678 if (m_dropTargetHelper)
1679 m_dropTargetHelper->DragOver((POINT*)&pt, *pdwEffect);
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());
1688 *pdwEffect = DROPEFFECT_NONE;
1690 m_lastDropEffect = *pdwEffect;
1694 HRESULT STDMETHODCALLTYPE WebView::DragLeave()
1696 if (m_dropTargetHelper)
1697 m_dropTargetHelper->DragLeave();
1700 DragData data(m_dragData.get(), IntPoint(), IntPoint(), DragOperationNone);
1701 m_page->dragExited(&data);
1703 m_page->resetDragOperation();
1708 HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
1710 if (m_dropTargetHelper)
1711 m_dropTargetHelper->Drop(pDataObject, (POINT*)&pt, *pdwEffect);
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));
1719 SandboxExtension::Handle sandboxExtensionHandle;
1720 m_page->performDrag(&data, String(), sandboxExtensionHandle);
1724 #if ENABLE(FULLSCREEN_API)
1725 FullScreenController* WebView::fullScreenController()
1727 if (!m_fullScreenController)
1728 m_fullScreenController = adoptPtr(new FullScreenController(this));
1729 return m_fullScreenController.get();
1732 HWND WebView::fullScreenClientWindow() const
1737 HWND WebView::fullScreenClientParentWindow() const
1739 return ::GetParent(m_window);
1742 void WebView::fullScreenClientSetParentWindow(HWND hostWindow)
1744 setParentWindow(hostWindow);
1747 void WebView::fullScreenClientWillEnterFullScreen()
1749 page()->fullScreenManager()->willEnterFullScreen();
1752 void WebView::fullScreenClientDidEnterFullScreen()
1754 page()->fullScreenManager()->didEnterFullScreen();
1757 void WebView::fullScreenClientWillExitFullScreen()
1759 page()->fullScreenManager()->willExitFullScreen();
1762 void WebView::fullScreenClientDidExitFullScreen()
1764 page()->fullScreenManager()->didExitFullScreen();
1767 static void fullScreenClientForceRepaintCompleted(WKErrorRef, void* context)
1770 static_cast<WebView*>(context)->fullScreenController()->repaintCompleted();
1773 void WebView::fullScreenClientForceRepaint()
1775 page()->forceRepaint(VoidCallback::create(this, &fullScreenClientForceRepaintCompleted));
1779 } // namespace WebKit