• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/editing/TextGranularity.h"
30 #include "core/events/TextEventInputType.h"
31 #include "core/page/DragActions.h"
32 #include "core/page/EventWithHitTestResults.h"
33 #include "core/page/FocusType.h"
34 #include "core/rendering/HitTestRequest.h"
35 #include "core/rendering/style/RenderStyleConstants.h"
36 #include "platform/Cursor.h"
37 #include "platform/PlatformMouseEvent.h"
38 #include "platform/Timer.h"
39 #include "platform/UserGestureIndicator.h"
40 #include "platform/geometry/LayoutPoint.h"
41 #include "platform/heap/Handle.h"
42 #include "platform/scroll/ScrollTypes.h"
43 #include "wtf/Forward.h"
44 #include "wtf/HashMap.h"
45 #include "wtf/HashTraits.h"
46 #include "wtf/RefPtr.h"
47 
48 namespace blink {
49 
50 class AutoscrollController;
51 class DataTransfer;
52 class Document;
53 class DragState;
54 class Element;
55 class Event;
56 class EventTarget;
57 template <typename EventType>
58 class EventWithHitTestResults;
59 class FloatPoint;
60 class FloatQuad;
61 class Fullscreen;
62 class HTMLFrameSetElement;
63 class HitTestRequest;
64 class HitTestResult;
65 class KeyboardEvent;
66 class LocalFrame;
67 class Node;
68 class OptionalCursor;
69 class PlatformGestureEvent;
70 class PlatformKeyboardEvent;
71 class PlatformTouchEvent;
72 class PlatformWheelEvent;
73 class RenderLayer;
74 class RenderLayerScrollableArea;
75 class RenderObject;
76 class ScrollableArea;
77 class Scrollbar;
78 class TextEvent;
79 class VisibleSelection;
80 class WheelEvent;
81 class Widget;
82 
83 enum AppendTrailingWhitespace { ShouldAppendTrailingWhitespace, DontAppendTrailingWhitespace };
84 enum CheckDragHysteresis { ShouldCheckDragHysteresis, DontCheckDragHysteresis };
85 
86 class EventHandler : public NoBaseWillBeGarbageCollectedFinalized<EventHandler> {
87     WTF_MAKE_NONCOPYABLE(EventHandler);
88 public:
89     explicit EventHandler(LocalFrame*);
90     ~EventHandler();
91     void trace(Visitor*);
92 
93     void clear();
94     void nodeWillBeRemoved(Node&);
95 
96     void updateSelectionForMouseDrag();
97 
98     Node* mousePressNode() const;
99 
100 #if OS(WIN)
101     void startPanScrolling(RenderObject*);
102 #endif
103 
104     void stopAutoscroll();
105 
106     void dispatchFakeMouseMoveEventSoon();
107     void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&);
108 
109     HitTestResult hitTestResultAtPoint(const LayoutPoint&,
110         HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active,
111         const LayoutSize& padding = LayoutSize());
112 
mousePressed()113     bool mousePressed() const { return m_mousePressed; }
setMousePressed(bool pressed)114     void setMousePressed(bool pressed) { m_mousePressed = pressed; }
115 
116     void setCapturingMouseEventsNode(PassRefPtrWillBeRawPtr<Node>); // A caller is responsible for resetting capturing node to 0.
117 
118     bool updateDragAndDrop(const PlatformMouseEvent&, DataTransfer*);
119     void cancelDragAndDrop(const PlatformMouseEvent&, DataTransfer*);
120     bool performDragAndDrop(const PlatformMouseEvent&, DataTransfer*);
121     void updateDragStateAfterEditDragIfNeeded(Element* rootEditableElement);
122 
123     void scheduleHoverStateUpdate();
124     void scheduleCursorUpdate();
125 
126     void setResizingFrameSet(HTMLFrameSetElement*);
127 
128     void resizeScrollableAreaDestroyed();
129 
130     IntPoint lastKnownMousePosition() const;
currentMouseCursor()131     Cursor currentMouseCursor() const { return m_currentMouseCursor; }
132 
133     // Attempts to scroll the DOM tree. If that fails, scrolls the view.
134     // If the view can't be scrolled either, recursively bubble to the parent frame.
135     bool bubblingScroll(ScrollDirection, ScrollGranularity, Node* startingNode = 0);
136 
137     bool handleMouseMoveEvent(const PlatformMouseEvent&);
138     void handleMouseLeaveEvent(const PlatformMouseEvent&);
139 
140     bool handleMousePressEvent(const PlatformMouseEvent&);
141     bool handleMouseReleaseEvent(const PlatformMouseEvent&);
142     bool handleWheelEvent(const PlatformWheelEvent&);
143     void defaultWheelEventHandler(Node*, WheelEvent*);
144 
145     // Called on the local root frame exactly once per gesture event.
146     bool handleGestureEvent(const PlatformGestureEvent&);
147     bool handleGestureEvent(const GestureEventWithHitTestResults&);
148 
149     // Hit-test the provided (non-scroll) gesture event, applying touch-adjustment and updating
150     // hover/active state across all frames if necessary. This should be called at most once
151     // per gesture event, and called on the local root frame.
152     // Note: This is similar to (the less clearly named) prepareMouseEvent.
153     // FIXME: Remove readOnly param when there is only ever a single call to this.
154     GestureEventWithHitTestResults targetGestureEvent(const PlatformGestureEvent&, bool readOnly = false);
155 
156     // Handle the provided non-scroll gesture event. Should be called only on the inner frame.
157     bool handleGestureEventInFrame(const GestureEventWithHitTestResults&);
158 
159     // Handle the provided scroll gesture event, propagating down to child frames as necessary.
160     bool handleGestureScrollEvent(const PlatformGestureEvent&);
161     bool handleGestureScrollEnd(const PlatformGestureEvent&);
162     bool isScrollbarHandlingGestures() const;
163 
164     bool bestClickableNodeForHitTestResult(const HitTestResult&, IntPoint& targetPoint, Node*& targetNode);
165     bool bestContextMenuNodeForHitTestResult(const HitTestResult&, IntPoint& targetPoint, Node*& targetNode);
166     // FIXME: This doesn't appear to be used outside tests anymore, what path are we using now and is it tested?
167     bool bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode);
168 
169     bool sendContextMenuEvent(const PlatformMouseEvent&);
170     bool sendContextMenuEventForKey();
171     bool sendContextMenuEventForGesture(const GestureEventWithHitTestResults&);
172 
setMouseDownMayStartAutoscroll()173     void setMouseDownMayStartAutoscroll() { m_mouseDownMayStartAutoscroll = true; }
174 
175     static unsigned accessKeyModifiers();
176     bool handleAccessKey(const PlatformKeyboardEvent&);
177     bool keyEvent(const PlatformKeyboardEvent&);
178     void defaultKeyboardEventHandler(KeyboardEvent*);
179 
180     bool handleTextInputEvent(const String& text, Event* underlyingEvent = 0, TextEventInputType = TextEventInputKeyboard);
181     void defaultTextInputEventHandler(TextEvent*);
182 
183     void dragSourceEndedAt(const PlatformMouseEvent&, DragOperation);
184 
185     void focusDocumentView();
186 
187     void capsLockStateMayHaveChanged(); // Only called by FrameSelection
188 
189     bool handleTouchEvent(const PlatformTouchEvent&);
190 
191     bool useHandCursor(Node*, bool isOverLink);
192 
193     void notifyElementActivated();
194     void notifySelectionChanged();
195 
takeLastMouseDownGestureToken()196     PassRefPtr<UserGestureToken> takeLastMouseDownGestureToken() { return m_lastMouseDownUserGestureToken.release(); }
197 
clickCount()198     int clickCount() { return m_clickCount; }
mouseDownWasSingleClickInSelection()199     bool mouseDownWasSingleClickInSelection() { return m_mouseDownWasSingleClickInSelection; }
200 
201 private:
202     static DragState& dragState();
203 
204     PassRefPtrWillBeRawPtr<DataTransfer> createDraggingDataTransfer() const;
205 
206     bool updateSelectionForMouseDownDispatchingSelectStart(Node*, const VisibleSelection&, TextGranularity);
207     void selectClosestWordFromHitTestResult(const HitTestResult&, AppendTrailingWhitespace);
208     void selectClosestMisspellingFromHitTestResult(const HitTestResult&, AppendTrailingWhitespace);
209     void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults&);
210     void selectClosestMisspellingFromMouseEvent(const MouseEventWithHitTestResults&);
211     void selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults&);
212 
213     bool handleMouseMoveOrLeaveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0, bool onlyUpdateScrollbars = false);
214     bool handleMousePressEvent(const MouseEventWithHitTestResults&);
215     bool handleMousePressEventSingleClick(const MouseEventWithHitTestResults&);
216     bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&);
217     bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&);
218     bool handleMouseFocus(const PlatformMouseEvent&);
219     bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&);
220     bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&);
221 
222     bool handlePasteGlobalSelection(const PlatformMouseEvent&);
223 
224     HitTestRequest::HitTestRequestType getHitTypeForGestureType(PlatformEvent::Type);
225     void applyTouchAdjustment(PlatformGestureEvent*, HitTestResult*);
226     bool handleGestureTap(const GestureEventWithHitTestResults&);
227     bool handleGestureLongPress(const GestureEventWithHitTestResults&);
228     bool handleGestureLongTap(const GestureEventWithHitTestResults&);
229     bool handleGestureScrollUpdate(const PlatformGestureEvent&);
230     bool handleGestureScrollBegin(const PlatformGestureEvent&);
231     void clearGestureScrollNodes();
232 
233     bool shouldApplyTouchAdjustment(const PlatformGestureEvent&) const;
234 
235     OptionalCursor selectCursor(const HitTestResult&);
236     OptionalCursor selectAutoCursor(const HitTestResult&, Node*, const Cursor& iBeam);
237 
238     void hoverTimerFired(Timer<EventHandler>*);
239     void cursorUpdateTimerFired(Timer<EventHandler>*);
240     void activeIntervalTimerFired(Timer<EventHandler>*);
241 
mouseDownMayStartSelect()242     bool mouseDownMayStartSelect() const { return m_mouseDownMayStartSelect; }
243 
244     void fakeMouseMoveEventTimerFired(Timer<EventHandler>*);
245     void cancelFakeMouseMoveEvent();
246     bool isCursorVisible() const;
247     void updateCursor();
248 
249     bool isInsideScrollbar(const IntPoint&) const;
250 
251     ScrollableArea* associatedScrollableArea(const RenderLayer*) const;
252 
253     // Scrolls the elements of the DOM tree. Returns true if a node was scrolled.
254     // False if we reached the root and couldn't scroll anything.
255     // direction - The direction to scroll in. If this is a logicl direction, it will be
256     //             converted to the physical direction based on a node's writing mode.
257     // granularity - The units that the  scroll delta parameter is in.
258     // startNode - The node to start bubbling the scroll from. If a node can't scroll,
259     //             the scroll bubbles up to the containing block.
260     // stopNode - On input, if provided and non-null, the node at which we should stop bubbling on input.
261     //            On output, if provided and a node was scrolled stopNode will point to that node.
262     // delta - The delta to scroll by, in the units of the granularity parameter. (e.g. pixels, lines, pages, etc.)
263     // absolutePoint - For wheel scrolls - the location, in absolute coordinates, where the event occured.
264     bool scroll(ScrollDirection, ScrollGranularity, Node* startNode = 0, Node** stopNode = 0, float delta = 1.0f, IntPoint absolutePoint = IntPoint());
265 
266     TouchAction intersectTouchAction(const TouchAction, const TouchAction);
267     TouchAction computeEffectiveTouchAction(const Node&);
268 
269     HitTestResult hitTestResultInFrame(LocalFrame*, const LayoutPoint&, HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active);
270 
271     void invalidateClick();
272 
273     void updateMouseEventTargetNode(Node*, const PlatformMouseEvent&, bool fireMouseOverOut);
274 
275     MouseEventWithHitTestResults prepareMouseEvent(const HitTestRequest&, const PlatformMouseEvent&);
276 
277     bool dispatchMouseEvent(const AtomicString& eventType, Node* target, int clickCount, const PlatformMouseEvent&, bool setUnder);
278     bool dispatchDragEvent(const AtomicString& eventType, Node* target, const PlatformMouseEvent&, DataTransfer*);
279 
280     void clearDragDataTransfer();
281 
282     bool handleDrag(const MouseEventWithHitTestResults&, CheckDragHysteresis);
283     bool tryStartDrag(const MouseEventWithHitTestResults&);
284     void clearDragState();
285 
286     bool dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent&);
287 
288     bool dragHysteresisExceeded(const FloatPoint&) const;
289     bool dragHysteresisExceeded(const IntPoint&) const;
290 
291     bool passMousePressEventToSubframe(MouseEventWithHitTestResults&, LocalFrame* subframe);
292     bool passMouseMoveEventToSubframe(MouseEventWithHitTestResults&, LocalFrame* subframe, HitTestResult* hoveredNode = 0);
293     bool passMouseReleaseEventToSubframe(MouseEventWithHitTestResults&, LocalFrame* subframe);
294 
295     bool passMousePressEventToScrollbar(MouseEventWithHitTestResults&);
296 
297     bool passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults&);
298 
299     bool passWheelEventToWidget(const PlatformWheelEvent&, Widget*);
300     void defaultSpaceEventHandler(KeyboardEvent*);
301     void defaultBackspaceEventHandler(KeyboardEvent*);
302     void defaultTabEventHandler(KeyboardEvent*);
303     void defaultEscapeEventHandler(KeyboardEvent*);
304     void defaultArrowEventHandler(FocusType, KeyboardEvent*);
305 
306     void updateSelectionForMouseDrag(const HitTestResult&);
307 
308     void updateLastScrollbarUnderMouse(Scrollbar*, bool);
309 
310     void setFrameWasScrolledByUser();
311 
capturesDragging()312     bool capturesDragging() const { return m_capturesDragging; }
313 
314     bool isKeyEventAllowedInFullScreen(Fullscreen*, const PlatformKeyboardEvent&) const;
315 
316     bool handleGestureShowPress();
317 
318     bool handleScrollGestureOnResizer(Node*, const PlatformGestureEvent&);
319 
320     bool passScrollGestureEventToWidget(const PlatformGestureEvent&, RenderObject*);
321     bool sendScrollEventToView(const PlatformGestureEvent&, const FloatSize&);
322 
323     AutoscrollController* autoscrollController() const;
324     bool panScrollInProgress() const;
325     void setLastKnownMousePosition(const PlatformMouseEvent&);
326 
327     LocalFrame* const m_frame;
328 
329     bool m_mousePressed;
330     bool m_capturesDragging;
331     RefPtrWillBeMember<Node> m_mousePressNode;
332 
333     bool m_mouseDownMayStartSelect;
334     bool m_mouseDownMayStartDrag;
335     bool m_mouseDownWasSingleClickInSelection;
336     enum SelectionInitiationState { HaveNotStartedSelection, PlacedCaret, ExtendedSelection };
337     SelectionInitiationState m_selectionInitiationState;
338 
339     LayoutPoint m_dragStartPos;
340 
341     Timer<EventHandler> m_hoverTimer;
342     Timer<EventHandler> m_cursorUpdateTimer;
343 
344     bool m_mouseDownMayStartAutoscroll;
345     bool m_mouseDownWasInSubframe;
346 
347     Timer<EventHandler> m_fakeMouseMoveEventTimer;
348 
349     bool m_svgPan;
350 
351     RenderLayerScrollableArea* m_resizeScrollableArea;
352 
353     RefPtrWillBeMember<Node> m_capturingMouseEventsNode;
354     bool m_eventHandlerWillResetCapturingMouseEventsNode;
355 
356     RefPtrWillBeMember<Node> m_nodeUnderMouse;
357     RefPtrWillBeMember<Node> m_lastNodeUnderMouse;
358     RefPtrWillBeMember<LocalFrame> m_lastMouseMoveEventSubframe;
359     RefPtr<Scrollbar> m_lastScrollbarUnderMouse;
360     Cursor m_currentMouseCursor;
361 
362     int m_clickCount;
363     RefPtrWillBeMember<Node> m_clickNode;
364 
365     RefPtrWillBeMember<Node> m_dragTarget;
366     bool m_shouldOnlyFireDragOverEvent;
367 
368     RefPtrWillBeMember<HTMLFrameSetElement> m_frameSetBeingResized;
369 
370     LayoutSize m_offsetFromResizeCorner; // In the coords of m_resizeScrollableArea.
371 
372     bool m_mousePositionIsUnknown;
373     IntPoint m_lastKnownMousePosition;
374     IntPoint m_lastKnownMouseGlobalPosition;
375     IntPoint m_mouseDownPos; // In our view's coords.
376     double m_mouseDownTimestamp;
377     PlatformMouseEvent m_mouseDown;
378     RefPtr<UserGestureToken> m_lastMouseDownUserGestureToken;
379 
380     RefPtrWillBeMember<Node> m_latchedWheelEventNode;
381     bool m_widgetIsLatched;
382 
383     RefPtrWillBeMember<Node> m_previousWheelScrolledNode;
384 
385     // The target of each active touch point indexed by the touch ID.
386     typedef WillBeHeapHashMap<unsigned, RefPtrWillBeMember<EventTarget>, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > TouchTargetMap;
387     TouchTargetMap m_targetForTouchID;
388 
389     // If set, the document of the active touch sequence. Unset if no touch sequence active.
390     RefPtrWillBeMember<Document> m_touchSequenceDocument;
391     RefPtr<UserGestureToken> m_touchSequenceUserGestureToken;
392 
393     bool m_touchPressed;
394 
395     RefPtrWillBeMember<Node> m_scrollGestureHandlingNode;
396     bool m_lastGestureScrollOverWidget;
397     RefPtrWillBeMember<Node> m_previousGestureScrolledNode;
398     RefPtr<Scrollbar> m_scrollbarHandlingScrollGesture;
399 
400     double m_maxMouseMovedDuration;
401     bool m_didStartDrag;
402 
403     bool m_longTapShouldInvokeContextMenu;
404 
405     Timer<EventHandler> m_activeIntervalTimer;
406     double m_lastShowPressTimestamp;
407     RefPtrWillBeMember<Element> m_lastDeferredTapElement;
408 };
409 
410 } // namespace blink
411 
412 #endif // EventHandler_h
413