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