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