2 * Copyright (C) 2006-2015 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. ``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.
26 #ifndef EventHandler_h
27 #define EventHandler_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"
40 #include "WheelEventDeltaTracker.h"
42 #include <wtf/Forward.h>
43 #include <wtf/RefPtr.h>
44 #include <wtf/WeakPtr.h>
50 #include "WAKAppKitStubs.h"
54 #endif // PLATFORM(IOS)
56 #if PLATFORM(COCOA) && !defined(__OBJC__)
60 #if ENABLE(TOUCH_EVENTS)
61 #include <wtf/HashMap.h>
64 #if ENABLE(IOS_TOUCH_EVENTS)
65 #include <wtf/HashSet.h>
66 #include <wtf/Vector.h>
71 class AutoscrollController;
81 class HTMLFrameSetElement;
85 class MouseEventWithHitTestResults;
88 class PlatformKeyboardEvent;
89 class PlatformTouchEvent;
90 class PlatformWheelEvent;
100 class VisibleSelection;
106 #if ENABLE(DRAG_SUPPORT)
107 extern const int LinkDragHysteresis;
108 extern const int ImageDragHysteresis;
109 extern const int TextDragHysteresis;
110 extern const int GeneralDragHysteresis;
111 #endif // ENABLE(DRAG_SUPPORT)
113 #if ENABLE(IOS_GESTURE_EVENTS)
114 extern const float GestureUnknown;
117 enum AppendTrailingWhitespace { ShouldAppendTrailingWhitespace, DontAppendTrailingWhitespace };
118 enum CheckDragHysteresis { ShouldCheckDragHysteresis, DontCheckDragHysteresis };
121 WTF_MAKE_NONCOPYABLE(EventHandler);
122 WTF_MAKE_FAST_ALLOCATED;
124 explicit EventHandler(Frame&);
128 void nodeWillBeRemoved(Node&);
130 #if ENABLE(DRAG_SUPPORT)
131 void updateSelectionForMouseDrag();
134 #if ENABLE(PAN_SCROLLING)
135 void didPanScrollStart();
136 void didPanScrollStop();
137 void startPanScrolling(RenderElement*);
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;
147 WEBCORE_EXPORT void dispatchFakeMouseMoveEventSoon();
148 void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&);
150 WEBCORE_EXPORT HitTestResult hitTestResultAtPoint(const LayoutPoint&,
151 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent,
152 const LayoutSize& padding = LayoutSize());
154 bool mousePressed() const { return m_mousePressed; }
155 Node* mousePressNode() const { return m_mousePressNode.get(); }
157 WEBCORE_EXPORT void setCapturingMouseEventsElement(PassRefPtr<Element>); // A caller is responsible for resetting capturing element to 0.
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);
166 void scheduleHoverStateUpdate();
167 #if ENABLE(CURSOR_SUPPORT)
168 void scheduleCursorUpdate();
171 void setResizingFrameSet(HTMLFrameSetElement*);
173 void resizeLayerDestroyed();
175 IntPoint lastKnownMousePosition() const;
176 Cursor currentMouseCursor() const { return m_currentMouseCursor; }
178 static Frame* subframeForTargetNode(Node*);
179 static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&);
181 WEBCORE_EXPORT bool scrollOverflow(ScrollDirection, ScrollGranularity, Node* startingNode = 0);
182 WEBCORE_EXPORT bool scrollRecursively(ScrollDirection, ScrollGranularity, Node* startingNode = 0);
183 WEBCORE_EXPORT bool logicalScrollRecursively(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
185 bool tabsToLinks(KeyboardEvent*) const;
186 bool tabsToAllFormControls(KeyboardEvent*) const;
188 WEBCORE_EXPORT bool mouseMoved(const PlatformMouseEvent&);
189 WEBCORE_EXPORT bool passMouseMovedEventToScrollbars(const PlatformMouseEvent&);
191 void lostMouseCapture();
193 WEBCORE_EXPORT bool handleMousePressEvent(const PlatformMouseEvent&);
194 bool handleMouseMoveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0, bool onlyUpdateScrollbars = false);
195 WEBCORE_EXPORT bool handleMouseReleaseEvent(const PlatformMouseEvent&);
196 WEBCORE_EXPORT bool handleWheelEvent(const PlatformWheelEvent&);
197 void defaultWheelEventHandler(Node*, WheelEvent*);
198 bool handlePasteGlobalSelection(const PlatformMouseEvent&);
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);
205 #if ENABLE(CSS_SCROLL_SNAP)
206 void platformNotifySnapIfNecessary(const PlatformWheelEvent&, ScrollableArea&);
209 #if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
210 typedef Vector<RefPtr<Touch>> TouchArray;
211 typedef HashMap<EventTarget*, TouchArray*> EventTargetTouchMap;
212 typedef HashSet<RefPtr<EventTarget>> EventTargetSet;
215 #if ENABLE(IOS_TOUCH_EVENTS)
216 bool dispatchTouchEvent(const PlatformTouchEvent&, const AtomicString&, const EventTargetTouchMap&, float, float);
217 bool dispatchSimulatedTouchEvent(IntPoint location);
220 #if ENABLE(IOS_GESTURE_EVENTS)
221 bool dispatchGestureEvent(const PlatformTouchEvent&, const AtomicString&, const EventTargetSet&, float, float);
225 void defaultTouchEventHandler(Node*, TouchEvent*);
228 #if ENABLE(CONTEXT_MENUS)
229 WEBCORE_EXPORT bool sendContextMenuEvent(const PlatformMouseEvent&);
230 bool sendContextMenuEventForKey();
233 void setMouseDownMayStartAutoscroll() { m_mouseDownMayStartAutoscroll = true; }
235 bool needsKeyboardEventDisambiguationQuirks() const;
237 static unsigned accessKeyModifiers();
238 WEBCORE_EXPORT bool handleAccessKey(const PlatformKeyboardEvent&);
239 WEBCORE_EXPORT bool keyEvent(const PlatformKeyboardEvent&);
240 void defaultKeyboardEventHandler(KeyboardEvent*);
242 bool accessibilityPreventsEventPropogation(KeyboardEvent*);
243 WEBCORE_EXPORT void handleKeyboardSelectionMovementForAccessibility(KeyboardEvent*);
245 bool handleTextInputEvent(const String& text, Event* underlyingEvent = 0, TextEventInputType = TextEventInputKeyboard);
246 void defaultTextInputEventHandler(TextEvent*);
248 #if ENABLE(DRAG_SUPPORT)
249 WEBCORE_EXPORT bool eventMayStartDrag(const PlatformMouseEvent&) const;
251 WEBCORE_EXPORT void dragSourceEndedAt(const PlatformMouseEvent&, DragOperation);
254 void focusDocumentView();
256 void capsLockStateMayHaveChanged(); // Only called by FrameSelection
258 WEBCORE_EXPORT void sendScrollEvent(); // Ditto
260 #if PLATFORM(COCOA) && defined(__OBJC__)
262 WEBCORE_EXPORT void mouseDown(NSEvent *);
263 WEBCORE_EXPORT void mouseDragged(NSEvent *);
264 WEBCORE_EXPORT void mouseUp(NSEvent *);
265 WEBCORE_EXPORT void mouseMoved(NSEvent *);
266 WEBCORE_EXPORT bool keyEvent(NSEvent *);
267 WEBCORE_EXPORT bool wheelEvent(NSEvent *);
269 WEBCORE_EXPORT void mouseDown(WebEvent *);
270 WEBCORE_EXPORT void mouseUp(WebEvent *);
271 WEBCORE_EXPORT void mouseMoved(WebEvent *);
272 WEBCORE_EXPORT bool keyEvent(WebEvent *);
273 WEBCORE_EXPORT bool wheelEvent(WebEvent *);
276 #if ENABLE(IOS_TOUCH_EVENTS)
277 WEBCORE_EXPORT void touchEvent(WebEvent *);
281 WEBCORE_EXPORT void passMouseMovedEventToScrollbars(NSEvent *);
283 WEBCORE_EXPORT void sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent);
287 void setActivationEventNumber(int num) { m_activationEventNumber = num; }
289 WEBCORE_EXPORT static NSEvent *currentNSEvent();
291 static WebEvent *currentEvent();
292 #endif // !PLATFORM(IOS)
293 #endif // PLATFORM(COCOA) && defined(__OBJC__)
296 void invalidateClick();
299 #if ENABLE(TOUCH_EVENTS)
300 WEBCORE_EXPORT bool handleTouchEvent(const PlatformTouchEvent&);
303 bool useHandCursor(Node*, bool isOverLink, bool shiftKey);
306 bool isHandlingWheelEvent() const { return m_isHandlingWheelEvent; }
309 #if ENABLE(DRAG_SUPPORT)
310 static DragState& dragState();
311 static const double TextDragDelay;
313 PassRefPtr<DataTransfer> createDraggingDataTransfer() const;
314 #endif // ENABLE(DRAG_SUPPORT)
316 bool eventActivatedView(const PlatformMouseEvent&) const;
317 bool updateSelectionForMouseDownDispatchingSelectStart(Node*, const VisibleSelection&, TextGranularity);
318 void selectClosestWordFromHitTestResult(const HitTestResult&, AppendTrailingWhitespace);
319 void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults&);
320 void selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults&);
322 bool handleMouseDoubleClickEvent(const PlatformMouseEvent&);
324 WEBCORE_EXPORT bool handleMousePressEvent(const MouseEventWithHitTestResults&);
325 bool handleMousePressEventSingleClick(const MouseEventWithHitTestResults&);
326 bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&);
327 bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&);
328 #if ENABLE(DRAG_SUPPORT)
329 bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&);
331 WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
333 OptionalCursor selectCursor(const HitTestResult&, bool shiftKey);
335 void hoverTimerFired();
336 #if ENABLE(CURSOR_SUPPORT)
337 void cursorUpdateTimerFired();
340 bool logicalScrollOverflow(ScrollLogicalDirection, ScrollGranularity, Node* startingNode = 0);
342 bool shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&, const PlatformWheelEvent&) const;
344 bool mouseDownMayStartSelect() const { return m_mouseDownMayStartSelect; }
346 static bool isKeyboardOptionTab(KeyboardEvent*);
347 static bool eventInvertsTabsToLinksClientCallResult(KeyboardEvent*);
349 #if !ENABLE(IOS_TOUCH_EVENTS)
350 void fakeMouseMoveEventTimerFired();
351 void cancelFakeMouseMoveEvent();
354 bool isInsideScrollbar(const IntPoint&) const;
356 #if ENABLE(TOUCH_EVENTS)
357 bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&);
361 void invalidateClick();
364 Node* nodeUnderMouse() const;
366 void updateMouseEventTargetNode(Node*, const PlatformMouseEvent&, bool fireMouseOverOut);
367 void fireMouseOverOut(bool fireMouseOver = true, bool fireMouseOut = true, bool updateLastNodeUnderMouse = true);
369 MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const PlatformMouseEvent&);
371 bool dispatchMouseEvent(const AtomicString& eventType, Node* target, bool cancelable, int clickCount, const PlatformMouseEvent&, bool setUnder);
372 #if ENABLE(DRAG_SUPPORT)
373 bool dispatchDragEvent(const AtomicString& eventType, Element& target, const PlatformMouseEvent&, DataTransfer*);
375 void freeDataTransfer();
377 bool handleDrag(const MouseEventWithHitTestResults&, CheckDragHysteresis);
379 bool handleMouseUp(const MouseEventWithHitTestResults&);
380 #if ENABLE(DRAG_SUPPORT)
381 void clearDragState();
383 bool dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent&);
385 bool dragHysteresisExceeded(const FloatPoint&) const;
386 bool dragHysteresisExceeded(const IntPoint&) const;
387 #endif // ENABLE(DRAG_SUPPORT)
389 bool mouseMovementExceedsThreshold(const FloatPoint&, int pointsThreshold) const;
391 bool passMousePressEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe);
392 bool passMouseMoveEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe, HitTestResult* hoveredNode = 0);
393 bool passMouseReleaseEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe);
395 bool passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame* subframe, HitTestResult* hoveredNode = 0);
397 bool passMousePressEventToScrollbar(MouseEventWithHitTestResults&, Scrollbar*);
399 bool passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&);
400 bool passWidgetMouseDownEventToWidget(RenderWidget*);
402 bool passMouseDownEventToWidget(Widget*);
403 bool passWheelEventToWidget(const PlatformWheelEvent&, Widget&);
405 void defaultSpaceEventHandler(KeyboardEvent*);
406 void defaultBackspaceEventHandler(KeyboardEvent*);
407 void defaultTabEventHandler(KeyboardEvent*);
408 void defaultArrowEventHandler(FocusDirection, KeyboardEvent*);
410 #if ENABLE(DRAG_SUPPORT)
411 DragSourceAction updateDragSourceActionsAllowed() const;
414 // The following are called at the beginning of handleMouseUp and handleDrag.
415 // If they return true it indicates that they have consumed the event.
416 bool eventLoopHandleMouseUp(const MouseEventWithHitTestResults&);
417 #if ENABLE(DRAG_SUPPORT)
418 bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&);
421 #if ENABLE(DRAG_SUPPORT)
422 void updateSelectionForMouseDrag(const HitTestResult&);
425 void updateLastScrollbarUnderMouse(Scrollbar*, bool);
427 void setFrameWasScrolledByUser();
429 bool capturesDragging() const { return m_capturesDragging; }
431 #if PLATFORM(COCOA) && defined(__OBJC__)
432 NSView *mouseDownViewIfStillGood();
434 PlatformMouseEvent currentPlatformMouseEvent() const;
437 #if ENABLE(FULLSCREEN_API)
438 bool isKeyEventAllowedInFullScreen(const PlatformKeyboardEvent&) const;
441 void setLastKnownMousePosition(const PlatformMouseEvent&);
443 #if ENABLE(CURSOR_VISIBILITY)
444 void startAutoHideCursorTimer();
445 void cancelAutoHideCursorTimer();
446 void autoHideCursorTimerFired();
449 void beginTrackingPotentialLongMousePress(const HitTestResult&);
450 void recognizeLongMousePress();
451 void cancelTrackingPotentialLongMousePress();
452 bool longMousePressHysteresisExceeded();
453 void clearLongMousePressState();
454 bool handleLongMousePressMouseMovedEvent(const PlatformMouseEvent&);
456 void clearLatchedState();
461 bool m_capturesDragging;
462 RefPtr<Node> m_mousePressNode;
464 bool m_mouseDownMayStartSelect;
465 #if ENABLE(DRAG_SUPPORT)
466 bool m_mouseDownMayStartDrag;
467 bool m_dragMayStartSelectionInstead;
469 bool m_mouseDownWasSingleClickInSelection;
470 enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection };
471 SelectionInitiationState m_selectionInitiationState;
473 #if ENABLE(DRAG_SUPPORT)
474 LayoutPoint m_dragStartPos;
477 bool m_panScrollButtonPressed;
480 #if ENABLE(CURSOR_SUPPORT)
481 Timer m_cursorUpdateTimer;
484 Timer m_longMousePressTimer;
485 bool m_didRecognizeLongMousePress;
487 std::unique_ptr<AutoscrollController> m_autoscrollController;
488 bool m_mouseDownMayStartAutoscroll;
489 bool m_mouseDownWasInSubframe;
491 #if !ENABLE(IOS_TOUCH_EVENTS)
492 Timer m_fakeMouseMoveEventTimer;
497 RenderLayer* m_resizeLayer;
499 RefPtr<Element> m_capturingMouseEventsElement;
500 bool m_eventHandlerWillResetCapturingMouseEventsElement;
502 RefPtr<Element> m_elementUnderMouse;
503 RefPtr<Element> m_lastElementUnderMouse;
504 RefPtr<Frame> m_lastMouseMoveEventSubframe;
505 WeakPtr<Scrollbar> m_lastScrollbarUnderMouse;
506 Cursor m_currentMouseCursor;
509 RefPtr<Node> m_clickNode;
511 #if ENABLE(IOS_GESTURE_EVENTS)
512 float m_gestureInitialDiameter;
513 float m_gestureLastDiameter;
514 float m_gestureInitialRotation;
515 float m_gestureLastRotation;
518 #if ENABLE(IOS_TOUCH_EVENTS)
519 unsigned m_firstTouchID;
521 TouchArray m_touches;
522 EventTargetSet m_gestureTargets;
523 RefPtr<Frame> m_touchEventTargetSubframe;
526 #if ENABLE(DRAG_SUPPORT)
527 RefPtr<Element> m_dragTarget;
528 bool m_shouldOnlyFireDragOverEvent;
531 RefPtr<HTMLFrameSetElement> m_frameSetBeingResized;
533 LayoutSize m_offsetFromResizeCorner; // In the coords of m_resizeLayer.
535 bool m_mousePositionIsUnknown;
536 IntPoint m_lastKnownMousePosition;
537 IntPoint m_lastKnownMouseGlobalPosition;
538 IntPoint m_mouseDownPos; // In our view's coords.
539 double m_mouseDownTimestamp;
540 PlatformMouseEvent m_mouseDown;
543 NSView *m_mouseDownView;
544 bool m_sendingEventToSubview;
545 bool m_startedGestureAtScrollLimit;
547 int m_activationEventNumber;
550 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
551 typedef HashMap<int, RefPtr<EventTarget>> TouchTargetMap;
552 TouchTargetMap m_originatingTouchPointTargets;
553 RefPtr<Document> m_originatingTouchPointDocument;
554 unsigned m_originatingTouchPointTargetKey;
558 double m_maxMouseMovedDuration;
559 PlatformEvent::Type m_baseEventType;
561 bool m_didLongPressInvokeContextMenu;
562 bool m_isHandlingWheelEvent;
564 #if ENABLE(CURSOR_VISIBILITY)
565 Timer m_autoHideCursorTimer;
569 } // namespace WebCore
571 #endif // EventHandler_h