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