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 "Cursor.h" 30#include "DragActions.h" 31#include "FocusDirection.h" 32#include "HitTestRequest.h" 33#include "LayoutPoint.h" 34#include "PlatformMouseEvent.h" 35#include "PlatformWheelEvent.h" 36#include "ScrollTypes.h" 37#include "TextEventInputType.h" 38#include "TextGranularity.h" 39#include "Timer.h" 40#include "UserGestureIndicator.h" 41#include <wtf/Deque.h> 42#include <wtf/Forward.h> 43#include <wtf/OwnPtr.h> 44#include <wtf/RefPtr.h> 45 46#if PLATFORM(MAC) && !defined(__OBJC__) 47class NSView; 48#endif 49 50#if ENABLE(TOUCH_EVENTS) 51#include <wtf/HashMap.h> 52#endif 53 54namespace WebCore { 55 56class AutoscrollController; 57class Clipboard; 58class Document; 59class Element; 60class Event; 61class EventTarget; 62class FloatPoint; 63class FloatQuad; 64class Frame; 65class HTMLFrameSetElement; 66class HitTestRequest; 67class HitTestResult; 68class KeyboardEvent; 69class MouseEventWithHitTestResults; 70class Node; 71class OptionalCursor; 72class PlatformKeyboardEvent; 73class PlatformTouchEvent; 74class PlatformWheelEvent; 75class RenderLayer; 76class RenderObject; 77class RenderWidget; 78class SVGElementInstance; 79class Scrollbar; 80class TextEvent; 81class TouchEvent; 82class VisibleSelection; 83class WheelEvent; 84class Widget; 85 86struct DragState; 87 88#if ENABLE(GESTURE_EVENTS) 89class PlatformGestureEvent; 90#endif 91 92#if ENABLE(DRAG_SUPPORT) 93extern const int LinkDragHysteresis; 94extern const int ImageDragHysteresis; 95extern const int TextDragHysteresis; 96extern const int GeneralDragHysteresis; 97#endif // ENABLE(DRAG_SUPPORT) 98 99enum AppendTrailingWhitespace { ShouldAppendTrailingWhitespace, DontAppendTrailingWhitespace }; 100enum CheckDragHysteresis { ShouldCheckDragHysteresis, DontCheckDragHysteresis }; 101 102class EventHandler { 103 WTF_MAKE_NONCOPYABLE(EventHandler); 104public: 105 explicit EventHandler(Frame*); 106 ~EventHandler(); 107 108 void clear(); 109 void nodeWillBeRemoved(Node*); 110 111#if ENABLE(DRAG_SUPPORT) 112 void updateSelectionForMouseDrag(); 113#endif 114 115 Node* mousePressNode() const; 116 void setMousePressNode(PassRefPtr<Node>); 117 118#if ENABLE(PAN_SCROLLING) 119 void didPanScrollStart(); 120 void didPanScrollStop(); 121 void startPanScrolling(RenderObject*); 122#endif 123 124 void stopAutoscrollTimer(bool rendererIsBeingDestroyed = false); 125 RenderObject* autoscrollRenderer() const; 126 void updateAutoscrollRenderer(); 127 bool autoscrollInProgress() const; 128 bool mouseDownWasInSubframe() const { return m_mouseDownWasInSubframe; } 129 bool panScrollInProgress() const; 130 131 void dispatchFakeMouseMoveEventSoon(); 132 void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&); 133 134 HitTestResult hitTestResultAtPoint(const LayoutPoint&, 135 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent, 136 const LayoutSize& padding = LayoutSize()); 137 138 bool mousePressed() const { return m_mousePressed; } 139 void setMousePressed(bool pressed) { m_mousePressed = pressed; } 140 141 void setCapturingMouseEventsNode(PassRefPtr<Node>); // A caller is responsible for resetting capturing node to 0. 142 143#if ENABLE(DRAG_SUPPORT) 144 bool updateDragAndDrop(const PlatformMouseEvent&, Clipboard*); 145 void cancelDragAndDrop(const PlatformMouseEvent&, Clipboard*); 146 bool performDragAndDrop(const PlatformMouseEvent&, Clipboard*); 147 void updateDragStateAfterEditDragIfNeeded(Element* rootEditableElement); 148#endif 149 150 void scheduleHoverStateUpdate(); 151 void scheduleCursorUpdate(); 152 153 void setResizingFrameSet(HTMLFrameSetElement*); 154 155 void resizeLayerDestroyed(); 156 157 IntPoint lastKnownMousePosition() const; 158 Cursor currentMouseCursor() const { return m_currentMouseCursor; } 159 160 static Frame* subframeForTargetNode(Node*); 161 static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&); 162 163 bool scrollOverflow(ScrollDirection, ScrollGranularity, Node* startingNode = 0); 164 bool scrollRecursively(ScrollDirection, ScrollGranularity, Node* startingNode = 0); 165 bool logicalScrollRecursively(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0); 166 167 bool tabsToLinks(KeyboardEvent*) const; 168 bool tabsToAllFormControls(KeyboardEvent*) const; 169 170 bool mouseMoved(const PlatformMouseEvent&); 171 bool passMouseMovedEventToScrollbars(const PlatformMouseEvent&); 172 173 void lostMouseCapture(); 174 175 bool handleMousePressEvent(const PlatformMouseEvent&); 176 bool handleMouseMoveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0, bool onlyUpdateScrollbars = false); 177 bool handleMouseReleaseEvent(const PlatformMouseEvent&); 178 bool handleWheelEvent(const PlatformWheelEvent&); 179 void defaultWheelEventHandler(Node*, WheelEvent*); 180 bool handlePasteGlobalSelection(const PlatformMouseEvent&); 181 182#if ENABLE(GESTURE_EVENTS) 183 bool handleGestureEvent(const PlatformGestureEvent&); 184 bool handleGestureTap(const PlatformGestureEvent&); 185 bool handleGestureLongPress(const PlatformGestureEvent&); 186 bool handleGestureLongTap(const PlatformGestureEvent&); 187 bool handleGestureTwoFingerTap(const PlatformGestureEvent&); 188 bool handleGestureScrollUpdate(const PlatformGestureEvent&); 189 bool handleGestureScrollBegin(const PlatformGestureEvent&); 190 void clearGestureScrollNodes(); 191 bool isScrollbarHandlingGestures() const; 192#endif 193 194#if ENABLE(TOUCH_ADJUSTMENT) 195 bool shouldApplyTouchAdjustment(const PlatformGestureEvent&) const; 196 197 bool bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode); 198 bool bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode); 199 bool bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode); 200 201 bool adjustGesturePosition(const PlatformGestureEvent&, IntPoint& adjustedPoint); 202#endif 203 204#if ENABLE(CONTEXT_MENUS) 205 bool sendContextMenuEvent(const PlatformMouseEvent&); 206 bool sendContextMenuEventForKey(); 207#if ENABLE(GESTURE_EVENTS) 208 bool sendContextMenuEventForGesture(const PlatformGestureEvent&); 209#endif 210#endif 211 212 void setMouseDownMayStartAutoscroll() { m_mouseDownMayStartAutoscroll = true; } 213 214 bool needsKeyboardEventDisambiguationQuirks() const; 215 216 static unsigned accessKeyModifiers(); 217 bool handleAccessKey(const PlatformKeyboardEvent&); 218 bool keyEvent(const PlatformKeyboardEvent&); 219 void defaultKeyboardEventHandler(KeyboardEvent*); 220 221 void handleKeyboardSelectionMovementForAccessibility(KeyboardEvent*); 222 223 bool handleTextInputEvent(const String& text, Event* underlyingEvent = 0, TextEventInputType = TextEventInputKeyboard); 224 void defaultTextInputEventHandler(TextEvent*); 225 226#if ENABLE(DRAG_SUPPORT) 227 bool eventMayStartDrag(const PlatformMouseEvent&) const; 228 229 void dragSourceEndedAt(const PlatformMouseEvent&, DragOperation); 230#endif 231 232 void focusDocumentView(); 233 234 void capsLockStateMayHaveChanged(); // Only called by FrameSelection 235 236 void sendScrollEvent(); // Ditto 237 238#if PLATFORM(MAC) && defined(__OBJC__) 239 void mouseDown(NSEvent *); 240 void mouseDragged(NSEvent *); 241 void mouseUp(NSEvent *); 242 void mouseMoved(NSEvent *); 243 bool keyEvent(NSEvent *); 244 bool wheelEvent(NSEvent *); 245 246 void passMouseMovedEventToScrollbars(NSEvent *); 247 248 void sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent); 249 250 void setActivationEventNumber(int num) { m_activationEventNumber = num; } 251 252 static NSEvent *currentNSEvent(); 253#endif 254 255#if ENABLE(TOUCH_EVENTS) 256 bool handleTouchEvent(const PlatformTouchEvent&); 257#endif 258 259 bool useHandCursor(Node*, bool isOverLink, bool shiftKey); 260 void updateCursor(); 261 262 bool isHandlingWheelEvent() const { return m_isHandlingWheelEvent; } 263 264private: 265#if ENABLE(DRAG_SUPPORT) 266 static DragState& dragState(); 267 static const double TextDragDelay; 268 269 PassRefPtr<Clipboard> createDraggingClipboard() const; 270#endif // ENABLE(DRAG_SUPPORT) 271 272 bool eventActivatedView(const PlatformMouseEvent&) const; 273 bool updateSelectionForMouseDownDispatchingSelectStart(Node*, const VisibleSelection&, TextGranularity); 274 void selectClosestWordFromHitTestResult(const HitTestResult&, AppendTrailingWhitespace); 275 void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults&); 276 void selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults&); 277 278 bool handleMouseDoubleClickEvent(const PlatformMouseEvent&); 279 280 bool handleMousePressEvent(const MouseEventWithHitTestResults&); 281 bool handleMousePressEventSingleClick(const MouseEventWithHitTestResults&); 282 bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&); 283 bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&); 284#if ENABLE(DRAG_SUPPORT) 285 bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&); 286#endif 287 bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&); 288 289 OptionalCursor selectCursor(const HitTestResult&, bool shiftKey); 290 291 void hoverTimerFired(Timer<EventHandler>*); 292 void cursorUpdateTimerFired(Timer<EventHandler>*); 293 294 bool logicalScrollOverflow(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0); 295 296 bool shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&, const PlatformWheelEvent&) const; 297 void recordWheelEventDelta(const PlatformWheelEvent&); 298 enum DominantScrollGestureDirection { 299 DominantScrollDirectionNone, 300 DominantScrollDirectionVertical, 301 DominantScrollDirectionHorizontal 302 }; 303 DominantScrollGestureDirection dominantScrollGestureDirection() const; 304 305 bool mouseDownMayStartSelect() const { return m_mouseDownMayStartSelect; } 306 307 static bool isKeyboardOptionTab(KeyboardEvent*); 308 static bool eventInvertsTabsToLinksClientCallResult(KeyboardEvent*); 309 310 void fakeMouseMoveEventTimerFired(Timer<EventHandler>*); 311 void cancelFakeMouseMoveEvent(); 312 313 bool isInsideScrollbar(const IntPoint&) const; 314 315#if ENABLE(TOUCH_EVENTS) 316 bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&); 317 HitTestResult hitTestResultInFrame(Frame*, const LayoutPoint&, HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 318#endif 319 320 void invalidateClick(); 321 322 Node* nodeUnderMouse() const; 323 324 void updateMouseEventTargetNode(Node*, const PlatformMouseEvent&, bool fireMouseOverOut); 325 void fireMouseOverOut(bool fireMouseOver = true, bool fireMouseOut = true, bool updateLastNodeUnderMouse = true); 326 327 MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const PlatformMouseEvent&); 328 329 bool dispatchMouseEvent(const AtomicString& eventType, Node* target, bool cancelable, int clickCount, const PlatformMouseEvent&, bool setUnder); 330#if ENABLE(DRAG_SUPPORT) 331 bool dispatchDragEvent(const AtomicString& eventType, Node* target, const PlatformMouseEvent&, Clipboard*); 332 333 void freeClipboard(); 334 335 bool handleDrag(const MouseEventWithHitTestResults&, CheckDragHysteresis); 336#endif 337 bool handleMouseUp(const MouseEventWithHitTestResults&); 338#if ENABLE(DRAG_SUPPORT) 339 void clearDragState(); 340 341 bool dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent&); 342 343 bool dragHysteresisExceeded(const FloatPoint&) const; 344 bool dragHysteresisExceeded(const IntPoint&) const; 345#endif // ENABLE(DRAG_SUPPORT) 346 347 bool passMousePressEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe); 348 bool passMouseMoveEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe, HitTestResult* hoveredNode = 0); 349 bool passMouseReleaseEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe); 350 351 bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe, HitTestResult* hoveredNode = 0); 352 353 bool passMousePressEventToScrollbar(MouseEventWithHitTestResults&, Scrollbar*); 354 355 bool passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&); 356 bool passWidgetMouseDownEventToWidget(RenderWidget*); 357 358 bool passMouseDownEventToWidget(Widget*); 359 bool passWheelEventToWidget(const PlatformWheelEvent&, Widget*); 360 361 void defaultSpaceEventHandler(KeyboardEvent*); 362 void defaultBackspaceEventHandler(KeyboardEvent*); 363 void defaultTabEventHandler(KeyboardEvent*); 364 void defaultArrowEventHandler(FocusDirection, KeyboardEvent*); 365 366#if ENABLE(DRAG_SUPPORT) 367 DragSourceAction updateDragSourceActionsAllowed() const; 368#endif 369 370 // The following are called at the beginning of handleMouseUp and handleDrag. 371 // If they return true it indicates that they have consumed the event. 372 bool eventLoopHandleMouseUp(const MouseEventWithHitTestResults&); 373#if ENABLE(DRAG_SUPPORT) 374 bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&); 375#endif 376 377#if ENABLE(DRAG_SUPPORT) 378 void updateSelectionForMouseDrag(const HitTestResult&); 379#endif 380 381 void updateLastScrollbarUnderMouse(Scrollbar*, bool); 382 383 void setFrameWasScrolledByUser(); 384 385 bool capturesDragging() const { return m_capturesDragging; } 386 387#if PLATFORM(MAC) && defined(__OBJC__) 388 NSView *mouseDownViewIfStillGood(); 389 390 PlatformMouseEvent currentPlatformMouseEvent() const; 391#endif 392 393#if ENABLE(FULLSCREEN_API) 394 bool isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent&) const; 395#endif 396 397#if ENABLE(GESTURE_EVENTS) 398 bool handleGestureTapDown(); 399 bool handleGestureForTextSelectionOrContextMenu(const PlatformGestureEvent&); 400 bool passGestureEventToWidget(const PlatformGestureEvent&, Widget*); 401 bool passGestureEventToWidgetIfPossible(const PlatformGestureEvent&, RenderObject*); 402 bool sendScrollEventToView(const PlatformGestureEvent&, const FloatSize&); 403#endif 404 405 void setLastKnownMousePosition(const PlatformMouseEvent&); 406 407#if ENABLE(CURSOR_VISIBILITY) 408 void startAutoHideCursorTimer(); 409 void cancelAutoHideCursorTimer(); 410 void autoHideCursorTimerFired(Timer<EventHandler>*); 411#endif 412 413 Frame* m_frame; 414 415 bool m_mousePressed; 416 bool m_capturesDragging; 417 RefPtr<Node> m_mousePressNode; 418 419 bool m_mouseDownMayStartSelect; 420#if ENABLE(DRAG_SUPPORT) 421 bool m_mouseDownMayStartDrag; 422 bool m_dragMayStartSelectionInstead; 423#endif 424 bool m_mouseDownWasSingleClickInSelection; 425 enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection }; 426 SelectionInitiationState m_selectionInitiationState; 427 428#if ENABLE(DRAG_SUPPORT) 429 LayoutPoint m_dragStartPos; 430#endif 431 432 bool m_panScrollButtonPressed; 433 434 Timer<EventHandler> m_hoverTimer; 435 Timer<EventHandler> m_cursorUpdateTimer; 436 437 OwnPtr<AutoscrollController> m_autoscrollController; 438 bool m_mouseDownMayStartAutoscroll; 439 bool m_mouseDownWasInSubframe; 440 441 Timer<EventHandler> m_fakeMouseMoveEventTimer; 442 443#if ENABLE(SVG) 444 bool m_svgPan; 445 RefPtr<SVGElementInstance> m_instanceUnderMouse; 446 RefPtr<SVGElementInstance> m_lastInstanceUnderMouse; 447#endif 448 449 RenderLayer* m_resizeLayer; 450 451 RefPtr<Node> m_capturingMouseEventsNode; 452 bool m_eventHandlerWillResetCapturingMouseEventsNode; 453 454 RefPtr<Node> m_nodeUnderMouse; 455 RefPtr<Node> m_lastNodeUnderMouse; 456 RefPtr<Frame> m_lastMouseMoveEventSubframe; 457 RefPtr<Scrollbar> m_lastScrollbarUnderMouse; 458 Cursor m_currentMouseCursor; 459 460 int m_clickCount; 461 RefPtr<Node> m_clickNode; 462 463#if ENABLE(DRAG_SUPPORT) 464 RefPtr<Node> m_dragTarget; 465 bool m_shouldOnlyFireDragOverEvent; 466#endif 467 468 RefPtr<HTMLFrameSetElement> m_frameSetBeingResized; 469 470 LayoutSize m_offsetFromResizeCorner; // In the coords of m_resizeLayer. 471 472 bool m_mousePositionIsUnknown; 473 IntPoint m_lastKnownMousePosition; 474 IntPoint m_lastKnownMouseGlobalPosition; 475 IntPoint m_mouseDownPos; // In our view's coords. 476 double m_mouseDownTimestamp; 477 PlatformMouseEvent m_mouseDown; 478 RefPtr<UserGestureToken> m_lastMouseDownUserGestureToken; 479 480 Deque<FloatSize> m_recentWheelEventDeltas; 481 RefPtr<Node> m_latchedWheelEventNode; 482 bool m_inTrackingScrollGesturePhase; 483 bool m_widgetIsLatched; 484 485 RefPtr<Node> m_previousWheelScrolledNode; 486 487#if PLATFORM(MAC) 488 NSView *m_mouseDownView; 489 bool m_sendingEventToSubview; 490 int m_activationEventNumber; 491#endif 492#if ENABLE(TOUCH_EVENTS) 493 typedef HashMap<int, RefPtr<EventTarget> > TouchTargetMap; 494 TouchTargetMap m_originatingTouchPointTargets; 495 RefPtr<Document> m_originatingTouchPointDocument; 496 unsigned m_originatingTouchPointTargetKey; 497 bool m_touchPressed; 498#endif 499 500#if ENABLE(GESTURE_EVENTS) 501 RefPtr<Node> m_scrollGestureHandlingNode; 502 bool m_lastHitTestResultOverWidget; 503 RefPtr<Node> m_previousGestureScrolledNode; 504 RefPtr<Scrollbar> m_scrollbarHandlingScrollGesture; 505#endif 506 507 double m_maxMouseMovedDuration; 508 PlatformEvent::Type m_baseEventType; 509 bool m_didStartDrag; 510 bool m_didLongPressInvokeContextMenu; 511 bool m_isHandlingWheelEvent; 512 513#if ENABLE(CURSOR_VISIBILITY) 514 Timer<EventHandler> m_autoHideCursorTimer; 515#endif 516}; 517 518} // namespace WebCore 519 520#endif // EventHandler_h 521