1/* 2 * Copyright (C) 2012 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "PageWidgetDelegate.h" 33 34#include "PageOverlayList.h" 35#include "WebInputEvent.h" 36#include "WebInputEventConversion.h" 37#include "core/page/EventHandler.h" 38#include "core/page/Frame.h" 39#include "core/page/FrameView.h" 40#include "core/platform/graphics/GraphicsContext.h" 41#include "wtf/CurrentTime.h" 42 43using namespace WebCore; 44 45namespace WebKit { 46 47static inline FrameView* mainFrameView(Page* page) 48{ 49 if (!page) 50 return 0; 51 // FIXME: Can we remove this check? 52 if (!page->mainFrame()) 53 return 0; 54 return page->mainFrame()->view(); 55} 56 57void PageWidgetDelegate::animate(Page* page, double monotonicFrameBeginTime) 58{ 59 FrameView* view = mainFrameView(page); 60 if (!view) 61 return; 62 view->serviceScriptedAnimations(monotonicFrameBeginTime); 63} 64 65void PageWidgetDelegate::layout(Page* page) 66{ 67 FrameView* view = mainFrameView(page); 68 if (!view) 69 return; 70 // In order for our child HWNDs (NativeWindowWidgets) to update properly, 71 // they need to be told that we are updating the screen. The problem is that 72 // the native widgets need to recalculate their clip region and not overlap 73 // any of our non-native widgets. To force the resizing, call 74 // setFrameRect(). This will be a quick operation for most frames, but the 75 // NativeWindowWidgets will update a proper clipping region. 76 view->setFrameRect(view->frameRect()); 77 78 // setFrameRect may have the side-effect of causing existing page layout to 79 // be invalidated, so layout needs to be called last. 80 view->updateLayoutAndStyleIfNeededRecursive(); 81} 82 83void PageWidgetDelegate::paint(Page* page, PageOverlayList* overlays, WebCanvas* canvas, const WebRect& rect, CanvasBackground background) 84{ 85 if (rect.isEmpty()) 86 return; 87 GraphicsContext gc(canvas); 88 gc.setCertainlyOpaque(background == Opaque); 89 gc.applyDeviceScaleFactor(page->deviceScaleFactor()); 90 gc.setUseHighResMarkers(page->deviceScaleFactor() > 1.5f); 91 IntRect dirtyRect(rect); 92 gc.save(); 93 FrameView* view = mainFrameView(page); 94 // FIXME: Can we remove the mainFrame()->document() check? 95 if (view && page->mainFrame()->document()) { 96 gc.clip(dirtyRect); 97 view->paint(&gc, dirtyRect); 98 if (overlays) 99 overlays->paintWebFrame(gc); 100 } else { 101 gc.fillRect(dirtyRect, Color::white); 102 } 103 gc.restore(); 104} 105 106bool PageWidgetDelegate::handleInputEvent(Page* page, PageWidgetEventHandler& handler, const WebInputEvent& event) 107{ 108 Frame* frame = page ? page->mainFrame() : 0; 109 switch (event.type) { 110 111 // FIXME: WebKit seems to always return false on mouse events processing 112 // methods. For now we'll assume it has processed them (as we are only 113 // interested in whether keyboard events are processed). 114 case WebInputEvent::MouseMove: 115 if (!frame || !frame->view()) 116 return true; 117 handler.handleMouseMove(*frame, *static_cast<const WebMouseEvent*>(&event)); 118 return true; 119 case WebInputEvent::MouseLeave: 120 if (!frame || !frame->view()) 121 return true; 122 handler.handleMouseLeave(*frame, *static_cast<const WebMouseEvent*>(&event)); 123 return true; 124 case WebInputEvent::MouseDown: 125 if (!frame || !frame->view()) 126 return true; 127 handler.handleMouseDown(*frame, *static_cast<const WebMouseEvent*>(&event)); 128 return true; 129 case WebInputEvent::MouseUp: 130 if (!frame || !frame->view()) 131 return true; 132 handler.handleMouseUp(*frame, *static_cast<const WebMouseEvent*>(&event)); 133 return true; 134 135 case WebInputEvent::MouseWheel: 136 if (!frame || !frame->view()) 137 return false; 138 return handler.handleMouseWheel(*frame, *static_cast<const WebMouseWheelEvent*>(&event)); 139 140 case WebInputEvent::RawKeyDown: 141 case WebInputEvent::KeyDown: 142 case WebInputEvent::KeyUp: 143 return handler.handleKeyEvent(*static_cast<const WebKeyboardEvent*>(&event)); 144 145 case WebInputEvent::Char: 146 return handler.handleCharEvent(*static_cast<const WebKeyboardEvent*>(&event)); 147 case WebInputEvent::GestureScrollBegin: 148 case WebInputEvent::GestureScrollEnd: 149 case WebInputEvent::GestureScrollUpdate: 150 case WebInputEvent::GestureScrollUpdateWithoutPropagation: 151 case WebInputEvent::GestureFlingStart: 152 case WebInputEvent::GestureFlingCancel: 153 case WebInputEvent::GestureTap: 154 case WebInputEvent::GestureTapUnconfirmed: 155 case WebInputEvent::GestureTapDown: 156 case WebInputEvent::GestureTapCancel: 157 case WebInputEvent::GestureDoubleTap: 158 case WebInputEvent::GestureTwoFingerTap: 159 case WebInputEvent::GestureLongPress: 160 case WebInputEvent::GestureLongTap: 161 return handler.handleGestureEvent(*static_cast<const WebGestureEvent*>(&event)); 162 163 case WebInputEvent::TouchStart: 164 case WebInputEvent::TouchMove: 165 case WebInputEvent::TouchEnd: 166 case WebInputEvent::TouchCancel: 167 if (!frame || !frame->view()) 168 return false; 169 return handler.handleTouchEvent(*frame, *static_cast<const WebTouchEvent*>(&event)); 170 171 case WebInputEvent::GesturePinchBegin: 172 case WebInputEvent::GesturePinchEnd: 173 case WebInputEvent::GesturePinchUpdate: 174 // FIXME: Once PlatformGestureEvent is updated to support pinch, this 175 // should call handleGestureEvent, just like it currently does for 176 // gesture scroll. 177 return false; 178 179 default: 180 return false; 181 } 182} 183 184// ---------------------------------------------------------------- 185// Default handlers for PageWidgetEventHandler 186 187void PageWidgetEventHandler::handleMouseMove(Frame& mainFrame, const WebMouseEvent& event) 188{ 189 // We call mouseMoved here instead of handleMouseMovedEvent because we need 190 // our ChromeClientImpl to receive changes to the mouse position and tooltip 191 // text, and mouseMoved handles all of that. 192 mainFrame.eventHandler()->mouseMoved(PlatformMouseEventBuilder(mainFrame.view(), event)); 193} 194 195void PageWidgetEventHandler::handleMouseLeave(Frame& mainFrame, const WebMouseEvent& event) 196{ 197 mainFrame.eventHandler()->handleMouseMoveEvent(PlatformMouseEventBuilder(mainFrame.view(), event)); 198} 199 200void PageWidgetEventHandler::handleMouseDown(Frame& mainFrame, const WebMouseEvent& event) 201{ 202 mainFrame.eventHandler()->handleMousePressEvent(PlatformMouseEventBuilder(mainFrame.view(), event)); 203} 204 205void PageWidgetEventHandler::handleMouseUp(Frame& mainFrame, const WebMouseEvent& event) 206{ 207 mainFrame.eventHandler()->handleMouseReleaseEvent(PlatformMouseEventBuilder(mainFrame.view(), event)); 208} 209 210bool PageWidgetEventHandler::handleMouseWheel(Frame& mainFrame, const WebMouseWheelEvent& event) 211{ 212 return mainFrame.eventHandler()->handleWheelEvent(PlatformWheelEventBuilder(mainFrame.view(), event)); 213} 214 215bool PageWidgetEventHandler::handleTouchEvent(Frame& mainFrame, const WebTouchEvent& event) 216{ 217 return mainFrame.eventHandler()->handleTouchEvent(PlatformTouchEventBuilder(mainFrame.view(), event)); 218} 219 220} 221