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*); panScrollInProgress()109 bool panScrollInProgress() { return m_panScrollInProgress; } setPanScrollInProgress(bool inProgress)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 mousePressed()124 bool mousePressed() const { return m_mousePressed; } setMousePressed(bool pressed)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 mouseDownMayStartSelect()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 setMouseDownMayStartAutoscroll()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 setActivationEventNumber(int num)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: EventHandlerDragStateEventHandlerDragState251 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 capturesDragging()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