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