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