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__) 41class NSView; 42#endif 43 44#if ENABLE(TOUCH_EVENTS) 45#include <wtf/HashMap.h> 46#endif 47 48namespace WebCore { 49 50class Clipboard; 51class Cursor; 52class Event; 53class EventTarget; 54class FloatPoint; 55class FloatQuad; 56class Frame; 57class HTMLFrameSetElement; 58class HitTestRequest; 59class HitTestResult; 60class KeyboardEvent; 61class MouseEventWithHitTestResults; 62class Node; 63class PlatformKeyboardEvent; 64class PlatformTouchEvent; 65class PlatformWheelEvent; 66class RenderLayer; 67class RenderObject; 68class RenderWidget; 69class SVGElementInstance; 70class Scrollbar; 71class TextEvent; 72class TouchEvent; 73class WheelEvent; 74class Widget; 75 76#if ENABLE(GESTURE_EVENTS) 77class PlatformGestureEvent; 78#endif 79 80#if ENABLE(GESTURE_RECOGNIZER) 81class PlatformGestureRecognizer; 82#endif 83 84#if ENABLE(DRAG_SUPPORT) 85extern const int LinkDragHysteresis; 86extern const int ImageDragHysteresis; 87extern const int TextDragHysteresis; 88extern const int GeneralDragHysteresis; 89#endif // ENABLE(DRAG_SUPPORT) 90 91enum HitTestScrollbars { ShouldHitTestScrollbars, DontHitTestScrollbars }; 92 93class EventHandler { 94 WTF_MAKE_NONCOPYABLE(EventHandler); 95public: 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 240private: 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