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