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