1 /* 2 * Copyright (C) 2006, 2007, 2009, 2010, 2011 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 COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef EventHandler_h 27 #define EventHandler_h 28 29 #include "core/editing/TextGranularity.h" 30 #include "core/events/TextEventInputType.h" 31 #include "core/page/DragActions.h" 32 #include "core/page/FocusType.h" 33 #include "core/rendering/HitTestRequest.h" 34 #include "core/rendering/style/RenderStyleConstants.h" 35 #include "platform/Cursor.h" 36 #include "platform/PlatformMouseEvent.h" 37 #include "platform/Timer.h" 38 #include "platform/UserGestureIndicator.h" 39 #include "platform/geometry/LayoutPoint.h" 40 #include "platform/heap/Handle.h" 41 #include "platform/scroll/ScrollTypes.h" 42 #include "wtf/Forward.h" 43 #include "wtf/HashMap.h" 44 #include "wtf/HashTraits.h" 45 #include "wtf/RefPtr.h" 46 47 namespace WebCore { 48 49 class AutoscrollController; 50 class Clipboard; 51 class Document; 52 class Element; 53 class Event; 54 class EventTarget; 55 class FloatPoint; 56 class FloatQuad; 57 class FullscreenElementStack; 58 class LocalFrame; 59 class HTMLFrameSetElement; 60 class HitTestRequest; 61 class HitTestResult; 62 class KeyboardEvent; 63 class MouseEventWithHitTestResults; 64 class Node; 65 class OptionalCursor; 66 class PlatformGestureEvent; 67 class PlatformKeyboardEvent; 68 class PlatformTouchEvent; 69 class PlatformWheelEvent; 70 class RenderLayer; 71 class RenderLayerScrollableArea; 72 class RenderObject; 73 class RenderWidget; 74 class ScrollableArea; 75 class Scrollbar; 76 class TextEvent; 77 class TouchEvent; 78 class VisibleSelection; 79 class WheelEvent; 80 class Widget; 81 82 class DragState; 83 84 enum AppendTrailingWhitespace { ShouldAppendTrailingWhitespace, DontAppendTrailingWhitespace }; 85 enum CheckDragHysteresis { ShouldCheckDragHysteresis, DontCheckDragHysteresis }; 86 87 class EventHandler : public NoBaseWillBeGarbageCollectedFinalized<EventHandler> { 88 WTF_MAKE_NONCOPYABLE(EventHandler); 89 public: 90 explicit EventHandler(LocalFrame*); 91 ~EventHandler(); 92 void trace(Visitor*); 93 94 void clear(); 95 void nodeWillBeRemoved(Node&); 96 97 void updateSelectionForMouseDrag(); 98 99 Node* mousePressNode() const; 100 101 #if OS(WIN) 102 void startPanScrolling(RenderObject*); 103 #endif 104 105 void stopAutoscroll(); 106 107 void dispatchFakeMouseMoveEventSoon(); 108 void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&); 109 110 HitTestResult hitTestResultAtPoint(const LayoutPoint&, 111 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active, 112 const LayoutSize& padding = LayoutSize()); 113 mousePressed()114 bool mousePressed() const { return m_mousePressed; } setMousePressed(bool pressed)115 void setMousePressed(bool pressed) { m_mousePressed = pressed; } 116 117 void setCapturingMouseEventsNode(PassRefPtrWillBeRawPtr<Node>); // A caller is responsible for resetting capturing node to 0. 118 119 bool updateDragAndDrop(const PlatformMouseEvent&, Clipboard*); 120 void cancelDragAndDrop(const PlatformMouseEvent&, Clipboard*); 121 bool performDragAndDrop(const PlatformMouseEvent&, Clipboard*); 122 void updateDragStateAfterEditDragIfNeeded(Element* rootEditableElement); 123 124 void scheduleHoverStateUpdate(); 125 void scheduleCursorUpdate(); 126 127 void setResizingFrameSet(HTMLFrameSetElement*); 128 129 void resizeScrollableAreaDestroyed(); 130 131 IntPoint lastKnownMousePosition() const; currentMouseCursor()132 Cursor currentMouseCursor() const { return m_currentMouseCursor; } 133 134 // Attempts to scroll the DOM tree. If that fails, scrolls the view. 135 // If the view can't be scrolled either, recursively bubble to the parent frame. 136 bool bubblingScroll(ScrollDirection, ScrollGranularity, Node* startingNode = 0); 137 138 bool handleMouseMoveEvent(const PlatformMouseEvent&); 139 void handleMouseLeaveEvent(const PlatformMouseEvent&); 140 141 bool handleMousePressEvent(const PlatformMouseEvent&); 142 bool handleMouseReleaseEvent(const PlatformMouseEvent&); 143 bool handleWheelEvent(const PlatformWheelEvent&); 144 void defaultWheelEventHandler(Node*, WheelEvent*); 145 146 bool handleGestureEvent(const PlatformGestureEvent&); 147 bool handleGestureScrollEnd(const PlatformGestureEvent&); 148 bool isScrollbarHandlingGestures() const; 149 150 bool bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode); 151 bool bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode); 152 bool bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode); 153 154 void adjustGesturePosition(const PlatformGestureEvent&, IntPoint& adjustedPoint); 155 156 bool sendContextMenuEvent(const PlatformMouseEvent&); 157 bool sendContextMenuEventForKey(); 158 bool sendContextMenuEventForGesture(const PlatformGestureEvent&); 159 setMouseDownMayStartAutoscroll()160 void setMouseDownMayStartAutoscroll() { m_mouseDownMayStartAutoscroll = true; } 161 162 static unsigned accessKeyModifiers(); 163 bool handleAccessKey(const PlatformKeyboardEvent&); 164 bool keyEvent(const PlatformKeyboardEvent&); 165 void defaultKeyboardEventHandler(KeyboardEvent*); 166 167 bool handleTextInputEvent(const String& text, Event* underlyingEvent = 0, TextEventInputType = TextEventInputKeyboard); 168 void defaultTextInputEventHandler(TextEvent*); 169 170 void dragSourceEndedAt(const PlatformMouseEvent&, DragOperation); 171 172 void focusDocumentView(); 173 174 void capsLockStateMayHaveChanged(); // Only called by FrameSelection 175 176 bool handleTouchEvent(const PlatformTouchEvent&); 177 178 bool useHandCursor(Node*, bool isOverLink); 179 180 void notifyElementActivated(); 181 takeLastMouseDownGestureToken()182 PassRefPtr<UserGestureToken> takeLastMouseDownGestureToken() { return m_lastMouseDownUserGestureToken.release(); } 183 184 private: 185 static DragState& dragState(); 186 187 PassRefPtrWillBeRawPtr<Clipboard> createDraggingClipboard() const; 188 189 bool updateSelectionForMouseDownDispatchingSelectStart(Node*, const VisibleSelection&, TextGranularity); 190 void selectClosestWordFromHitTestResult(const HitTestResult&, AppendTrailingWhitespace); 191 void selectClosestMisspellingFromHitTestResult(const HitTestResult&, AppendTrailingWhitespace); 192 void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults&); 193 void selectClosestMisspellingFromMouseEvent(const MouseEventWithHitTestResults&); 194 void selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults&); 195 196 bool handleMouseMoveOrLeaveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0, bool onlyUpdateScrollbars = false); 197 bool handleMousePressEvent(const MouseEventWithHitTestResults&); 198 bool handleMousePressEventSingleClick(const MouseEventWithHitTestResults&); 199 bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&); 200 bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&); 201 bool handleMouseFocus(const PlatformMouseEvent&); 202 bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&); 203 bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&); 204 205 bool handlePasteGlobalSelection(const PlatformMouseEvent&); 206 207 bool handleGestureTap(const PlatformGestureEvent&, const IntPoint& adjustedPoint); 208 bool handleGestureLongPress(const PlatformGestureEvent&, const IntPoint& adjustedPoint); 209 bool handleGestureLongTap(const PlatformGestureEvent&, const IntPoint& adjustedPoint); 210 bool handleGestureTwoFingerTap(const PlatformGestureEvent&, const IntPoint& adjustedPoint); 211 bool handleGestureScrollUpdate(const PlatformGestureEvent&); 212 bool handleGestureScrollBegin(const PlatformGestureEvent&); 213 void clearGestureScrollNodes(); 214 215 bool shouldApplyTouchAdjustment(const PlatformGestureEvent&) const; 216 217 OptionalCursor selectCursor(const HitTestResult&); 218 OptionalCursor selectAutoCursor(const HitTestResult&, Node*, const Cursor& iBeam); 219 220 void hoverTimerFired(Timer<EventHandler>*); 221 void cursorUpdateTimerFired(Timer<EventHandler>*); 222 void activeIntervalTimerFired(Timer<EventHandler>*); 223 mouseDownMayStartSelect()224 bool mouseDownMayStartSelect() const { return m_mouseDownMayStartSelect; } 225 226 void fakeMouseMoveEventTimerFired(Timer<EventHandler>*); 227 void cancelFakeMouseMoveEvent(); 228 bool isCursorVisible() const; 229 void updateCursor(); 230 231 bool isInsideScrollbar(const IntPoint&) const; 232 233 ScrollableArea* associatedScrollableArea(const RenderLayer*) const; 234 235 // Scrolls the elements of the DOM tree. Returns true if a node was scrolled. 236 // False if we reached the root and couldn't scroll anything. 237 // direction - The direction to scroll in. If this is a logicl direction, it will be 238 // converted to the physical direction based on a node's writing mode. 239 // granularity - The units that the scroll delta parameter is in. 240 // startNode - The node to start bubbling the scroll from. If a node can't scroll, 241 // the scroll bubbles up to the containing block. 242 // stopNode - On input, if provided and non-null, the node at which we should stop bubbling on input. 243 // On output, if provided and a node was scrolled stopNode will point to that node. 244 // delta - The delta to scroll by, in the units of the granularity parameter. (e.g. pixels, lines, pages, etc.) 245 // absolutePoint - For wheel scrolls - the location, in absolute coordinates, where the event occured. 246 bool scroll(ScrollDirection, ScrollGranularity, Node* startNode = 0, Node** stopNode = 0, float delta = 1.0f, IntPoint absolutePoint = IntPoint()); 247 248 TouchAction intersectTouchAction(const TouchAction, const TouchAction); 249 TouchAction computeEffectiveTouchAction(const Node&); 250 251 HitTestResult hitTestResultInFrame(LocalFrame*, const LayoutPoint&, HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); 252 253 void invalidateClick(); 254 255 void updateMouseEventTargetNode(Node*, const PlatformMouseEvent&, bool fireMouseOverOut); 256 257 MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const PlatformMouseEvent&); 258 259 bool dispatchMouseEvent(const AtomicString& eventType, Node* target, int clickCount, const PlatformMouseEvent&, bool setUnder); 260 bool dispatchDragEvent(const AtomicString& eventType, Node* target, const PlatformMouseEvent&, Clipboard*); 261 262 void freeClipboard(); 263 264 bool handleDrag(const MouseEventWithHitTestResults&, CheckDragHysteresis); 265 bool tryStartDrag(const MouseEventWithHitTestResults&); 266 void clearDragState(); 267 268 bool dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent&); 269 270 bool dragHysteresisExceeded(const FloatPoint&) const; 271 bool dragHysteresisExceeded(const IntPoint&) const; 272 273 bool passMousePressEventToSubframe(MouseEventWithHitTestResults&, LocalFrame* subframe); 274 bool passMouseMoveEventToSubframe(MouseEventWithHitTestResults&, LocalFrame* subframe, HitTestResult* hoveredNode = 0); 275 bool passMouseReleaseEventToSubframe(MouseEventWithHitTestResults&, LocalFrame* subframe); 276 277 bool passMousePressEventToScrollbar(MouseEventWithHitTestResults&); 278 279 bool passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&); 280 281 bool passWheelEventToWidget(const PlatformWheelEvent&, Widget*); 282 283 void defaultSpaceEventHandler(KeyboardEvent*); 284 void defaultBackspaceEventHandler(KeyboardEvent*); 285 void defaultTabEventHandler(KeyboardEvent*); 286 void defaultEscapeEventHandler(KeyboardEvent*); 287 void defaultArrowEventHandler(FocusType, KeyboardEvent*); 288 289 void updateSelectionForMouseDrag(const HitTestResult&); 290 291 void updateLastScrollbarUnderMouse(Scrollbar*, bool); 292 293 void setFrameWasScrolledByUser(); 294 capturesDragging()295 bool capturesDragging() const { return m_capturesDragging; } 296 297 bool isKeyEventAllowedInFullScreen(FullscreenElementStack*, const PlatformKeyboardEvent&) const; 298 299 bool handleGestureShowPress(); 300 301 bool handleScrollGestureOnResizer(Node*, const PlatformGestureEvent&); 302 303 bool passGestureEventToWidget(const PlatformGestureEvent&, Widget*); 304 bool passGestureEventToWidgetIfPossible(const PlatformGestureEvent&, RenderObject*); 305 bool sendScrollEventToView(const PlatformGestureEvent&, const FloatSize&); 306 LocalFrame* getSubFrameForGestureEvent(const IntPoint& touchAdjustedPoint, const PlatformGestureEvent&); 307 308 AutoscrollController* autoscrollController() const; 309 bool panScrollInProgress() const; 310 void setLastKnownMousePosition(const PlatformMouseEvent&); 311 312 LocalFrame* const m_frame; 313 314 bool m_mousePressed; 315 bool m_capturesDragging; 316 RefPtrWillBeMember<Node> m_mousePressNode; 317 318 bool m_mouseDownMayStartSelect; 319 bool m_mouseDownMayStartDrag; 320 bool m_mouseDownWasSingleClickInSelection; 321 enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection }; 322 SelectionInitiationState m_selectionInitiationState; 323 324 LayoutPoint m_dragStartPos; 325 326 Timer<EventHandler> m_hoverTimer; 327 Timer<EventHandler> m_cursorUpdateTimer; 328 329 bool m_mouseDownMayStartAutoscroll; 330 bool m_mouseDownWasInSubframe; 331 332 Timer<EventHandler> m_fakeMouseMoveEventTimer; 333 334 bool m_svgPan; 335 336 RenderLayerScrollableArea* m_resizeScrollableArea; 337 338 RefPtrWillBeMember<Node> m_capturingMouseEventsNode; 339 bool m_eventHandlerWillResetCapturingMouseEventsNode; 340 341 RefPtrWillBeMember<Node> m_nodeUnderMouse; 342 RefPtrWillBeMember<Node> m_lastNodeUnderMouse; 343 RefPtr<LocalFrame> m_lastMouseMoveEventSubframe; 344 RefPtr<Scrollbar> m_lastScrollbarUnderMouse; 345 Cursor m_currentMouseCursor; 346 347 int m_clickCount; 348 RefPtrWillBeMember<Node> m_clickNode; 349 350 RefPtrWillBeMember<Node> m_dragTarget; 351 bool m_shouldOnlyFireDragOverEvent; 352 353 RefPtrWillBeMember<HTMLFrameSetElement> m_frameSetBeingResized; 354 355 LayoutSize m_offsetFromResizeCorner; // In the coords of m_resizeScrollableArea. 356 357 bool m_mousePositionIsUnknown; 358 IntPoint m_lastKnownMousePosition; 359 IntPoint m_lastKnownMouseGlobalPosition; 360 IntPoint m_mouseDownPos; // In our view's coords. 361 double m_mouseDownTimestamp; 362 PlatformMouseEvent m_mouseDown; 363 RefPtr<UserGestureToken> m_lastMouseDownUserGestureToken; 364 365 RefPtrWillBeMember<Node> m_latchedWheelEventNode; 366 bool m_widgetIsLatched; 367 368 RefPtrWillBeMember<Node> m_previousWheelScrolledNode; 369 370 // The target of each active touch point indexed by the touch ID. 371 typedef WillBeHeapHashMap<unsigned, RefPtrWillBeMember<EventTarget>, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > TouchTargetMap; 372 TouchTargetMap m_targetForTouchID; 373 374 // If set, the document of the active touch sequence. Unset if no touch sequence active. 375 RefPtrWillBeMember<Document> m_touchSequenceDocument; 376 RefPtr<UserGestureToken> m_touchSequenceUserGestureToken; 377 378 bool m_touchPressed; 379 380 RefPtrWillBeMember<Node> m_scrollGestureHandlingNode; 381 bool m_lastHitTestResultOverWidget; 382 RefPtrWillBeMember<Node> m_previousGestureScrolledNode; 383 RefPtr<Scrollbar> m_scrollbarHandlingScrollGesture; 384 385 double m_maxMouseMovedDuration; 386 PlatformEvent::Type m_baseEventType; 387 bool m_didStartDrag; 388 389 bool m_longTapShouldInvokeContextMenu; 390 391 Timer<EventHandler> m_activeIntervalTimer; 392 double m_lastShowPressTimestamp; 393 RefPtrWillBeMember<Element> m_lastDeferredTapElement; 394 }; 395 396 } // namespace WebCore 397 398 #endif // EventHandler_h 399