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