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