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 THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_EVENT_HANDLER_H_ 27 #define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_EVENT_HANDLER_H_ 28 29 #include "base/macros.h" 30 #include "base/memory/scoped_refptr.h" 31 #include "base/optional.h" 32 #include "third_party/blink/public/common/input/web_input_event.h" 33 #include "third_party/blink/public/common/input/web_menu_source_type.h" 34 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" 35 #include "third_party/blink/public/platform/web_input_event_result.h" 36 #include "third_party/blink/renderer/core/core_export.h" 37 #include "third_party/blink/renderer/core/events/text_event_input_type.h" 38 #include "third_party/blink/renderer/core/input/fallback_cursor_event_manager.h" 39 #include "third_party/blink/renderer/core/input/gesture_manager.h" 40 #include "third_party/blink/renderer/core/input/keyboard_event_manager.h" 41 #include "third_party/blink/renderer/core/input/mouse_event_manager.h" 42 #include "third_party/blink/renderer/core/input/mouse_wheel_event_manager.h" 43 #include "third_party/blink/renderer/core/input/pointer_event_manager.h" 44 #include "third_party/blink/renderer/core/input/scroll_manager.h" 45 #include "third_party/blink/renderer/core/layout/hit_test_request.h" 46 #include "third_party/blink/renderer/core/page/drag_actions.h" 47 #include "third_party/blink/renderer/core/page/event_with_hit_test_results.h" 48 #include "third_party/blink/renderer/core/scroll/scroll_types.h" 49 #include "third_party/blink/renderer/core/style/computed_style_constants.h" 50 #include "third_party/blink/renderer/platform/geometry/layout_point.h" 51 #include "third_party/blink/renderer/platform/heap/handle.h" 52 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" 53 #include "third_party/blink/renderer/platform/wtf/forward.h" 54 #include "third_party/blink/renderer/platform/wtf/hash_map.h" 55 #include "third_party/blink/renderer/platform/wtf/hash_traits.h" 56 #include "ui/base/cursor/cursor.h" 57 58 namespace blink { 59 60 class DataTransfer; 61 class PaintLayer; 62 class Element; 63 class Event; 64 template <typename EventType> 65 class EventWithHitTestResults; 66 class HTMLFrameSetElement; 67 class HitTestRequest; 68 class HitTestResult; 69 class LayoutObject; 70 class LocalFrame; 71 class Node; 72 class ScrollableArea; 73 class Scrollbar; 74 class SelectionController; 75 class TextEvent; 76 class WebGestureEvent; 77 class WebMouseEvent; 78 class WebMouseWheelEvent; 79 80 // Handles events for Pointers (Mouse/Touch), HitTests, DragAndDrop, etc. 81 class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> { 82 public: 83 explicit EventHandler(LocalFrame&); 84 void Trace(Visitor*); 85 86 void Clear(); 87 88 void UpdateSelectionForMouseDrag(); 89 void StartMiddleClickAutoscroll(LayoutObject*); 90 91 // TODO(nzolghadr): Some of the APIs in this class only forward the action 92 // to the corresponding Manager class. We need to investigate whether it is 93 // better to expose the manager instance itself later or can the access to 94 // those APIs be more limited or removed. 95 96 void StopAutoscroll(); 97 98 HitTestResult HitTestResultAtLocation( 99 const HitTestLocation&, 100 HitTestRequest::HitTestRequestType hit_type = 101 HitTestRequest::kReadOnly | HitTestRequest::kActive | 102 HitTestRequest::kRetargetForInert, 103 const LayoutObject* stop_node = nullptr, 104 bool no_lifecycle_update = false); 105 MousePressed()106 bool MousePressed() const { return mouse_event_manager_->MousePressed(); } IsMousePositionUnknown()107 bool IsMousePositionUnknown() const { 108 return mouse_event_manager_->IsMousePositionUnknown(); 109 } ClearMouseEventManager()110 void ClearMouseEventManager() const { mouse_event_manager_->Clear(); } 111 112 WebInputEventResult UpdateDragAndDrop(const WebMouseEvent&, DataTransfer*); 113 void CancelDragAndDrop(const WebMouseEvent&, DataTransfer*); 114 WebInputEventResult PerformDragAndDrop(const WebMouseEvent&, DataTransfer*); 115 void UpdateDragStateAfterEditDragIfNeeded(Element* root_editable_element); 116 117 void ScheduleHoverStateUpdate(); 118 void ScheduleCursorUpdate(); 119 120 // Return whether a mouse cursor update is currently pending. Used for 121 // testing. 122 bool CursorUpdatePending(); 123 124 void SetResizingFrameSet(HTMLFrameSetElement*); 125 126 void ResizeScrollableAreaDestroyed(); 127 128 FloatPoint LastKnownMousePositionInRootFrame() const; 129 FloatPoint LastKnownMouseScreenPosition() const; 130 131 IntPoint DragDataTransferLocationForTesting(); 132 133 // Performs a logical scroll that chains, crossing frames, starting from 134 // the given node or a reasonable default (focus/last clicked). 135 bool BubblingScroll(mojom::blink::ScrollDirection, 136 ScrollGranularity, 137 Node* starting_node = nullptr); 138 139 WebInputEventResult HandleMouseMoveEvent( 140 const WebMouseEvent&, 141 const Vector<WebMouseEvent>& coalesced_events, 142 const Vector<WebMouseEvent>& predicted_events); 143 void HandleMouseLeaveEvent(const WebMouseEvent&); 144 145 WebInputEventResult HandlePointerEvent( 146 const WebPointerEvent&, 147 const Vector<WebPointerEvent>& coalesced_events, 148 const Vector<WebPointerEvent>& predicted_events); 149 150 WebInputEventResult DispatchBufferedTouchEvents(); 151 152 WebInputEventResult HandleMousePressEvent(const WebMouseEvent&); 153 WebInputEventResult HandleMouseReleaseEvent(const WebMouseEvent&); 154 WebInputEventResult HandleWheelEvent(const WebMouseWheelEvent&); 155 156 WebInputEventResult HandleTargetedMouseEvent( 157 Element* target, 158 const WebMouseEvent&, 159 const AtomicString& event_type, 160 const Vector<WebMouseEvent>& coalesced_events, 161 const Vector<WebMouseEvent>& predicted_events, 162 const String& canvas_node_id = String()); 163 164 // Called on the local root frame exactly once per gesture event. 165 WebInputEventResult HandleGestureEvent(const WebGestureEvent&); 166 WebInputEventResult HandleGestureEvent(const GestureEventWithHitTestResults&); 167 168 // Clear the old hover/active state within frames before moving the hover 169 // state to the another frame. |is_active| specifies whether the active state 170 // is being applied to or removed from the given element. This method should 171 // be initially called on the root document, it will recurse into child 172 // frames as needed. 173 void UpdateCrossFrameHoverActiveState(bool is_active, Element*); 174 175 // Hit-test the provided (non-scroll) gesture event, applying touch-adjustment 176 // and updating hover/active state across all frames if necessary. This should 177 // be called at most once per gesture event, and called on the local root 178 // frame. 179 // Note: This is similar to (the less clearly named) prepareMouseEvent. 180 // FIXME: Remove readOnly param when there is only ever a single call to this. 181 GestureEventWithHitTestResults TargetGestureEvent(const WebGestureEvent&, 182 bool read_only = false); 183 GestureEventWithHitTestResults HitTestResultForGestureEvent( 184 const WebGestureEvent&, 185 HitTestRequest::HitTestRequestType); 186 // Handle the provided non-scroll gesture event. Should be called only on the 187 // inner frame. 188 WebInputEventResult HandleGestureEventInFrame( 189 const GestureEventWithHitTestResults&); 190 191 // Handle the provided scroll gesture event, propagating down to child frames 192 // as necessary. 193 WebInputEventResult HandleGestureScrollEvent(const WebGestureEvent&); 194 bool IsScrollbarHandlingGestures() const; 195 196 bool BestClickableNodeForHitTestResult(const HitTestLocation& location, 197 const HitTestResult&, 198 IntPoint& target_point, 199 Node*& target_node); 200 bool BestContextMenuNodeForHitTestResult(const HitTestLocation& location, 201 const HitTestResult&, 202 IntPoint& target_point, 203 Node*& target_node); 204 void CacheTouchAdjustmentResult(uint32_t, FloatPoint); 205 206 WebInputEventResult SendContextMenuEvent( 207 const WebMouseEvent&, 208 Element* override_target_element = nullptr); 209 WebInputEventResult ShowNonLocatedContextMenu( 210 Element* override_target_element = nullptr, 211 WebMenuSourceType = kMenuSourceNone); 212 213 // Returns whether pointerId is active or not 214 bool IsPointerEventActive(PointerId); 215 216 void SetPointerCapture(PointerId, Element*); 217 void ReleasePointerCapture(PointerId, Element*); 218 void ReleaseMousePointerCapture(); 219 bool HasPointerCapture(PointerId, const Element*) const; 220 221 void ElementRemoved(Element*); 222 223 void SetMouseDownMayStartAutoscroll(); 224 225 bool HandleAccessKey(const WebKeyboardEvent&); 226 WebInputEventResult KeyEvent(const WebKeyboardEvent&); 227 void DefaultKeyboardEventHandler(KeyboardEvent*); 228 bool HandleFallbackCursorModeBackEvent(); 229 230 bool HandleTextInputEvent(const String& text, 231 Event* underlying_event = nullptr, 232 TextEventInputType = kTextEventInputKeyboard); 233 void DefaultTextInputEventHandler(TextEvent*); 234 235 void DragSourceEndedAt(const WebMouseEvent&, DragOperation); 236 237 void CapsLockStateMayHaveChanged(); // Only called by FrameSelection 238 239 bool UseHandCursor(Node*, bool is_over_link); 240 241 void NotifyElementActivated(); 242 GetSelectionController()243 SelectionController& GetSelectionController() const { 244 return *selection_controller_; 245 } 246 247 bool IsPointerIdActiveOnFrame(PointerId, LocalFrame*) const; 248 249 LocalFrame* DetermineActivePointerTrackerFrame(PointerId pointer_id) const; 250 251 // Clears drag target and related states. It is called when drag is done or 252 // canceled. 253 void ClearDragState(); 254 GetEventHandlerRegistry()255 EventHandlerRegistry& GetEventHandlerRegistry() const { 256 return *event_handler_registry_; 257 } 258 259 void AnimateSnapFling(base::TimeTicks monotonic_time); 260 261 void RecomputeMouseHoverStateIfNeeded(); 262 263 void MarkHoverStateDirty(); 264 265 void SetIsFallbackCursorModeOn(bool is_on); 266 267 // Reset the last mouse position so that movement after unlock will be 268 // restart from the lock position. 269 void ResetMousePositionForPointerUnlock(); 270 271 bool LongTapShouldInvokeContextMenu(); 272 273 private: 274 WebInputEventResult HandleMouseMoveOrLeaveEvent( 275 const WebMouseEvent&, 276 const Vector<WebMouseEvent>& coalesced_events, 277 const Vector<WebMouseEvent>& predicted_events, 278 HitTestResult* hovered_node = nullptr, 279 HitTestLocation* hit_test_location = nullptr); 280 281 // Updates the event, location and result to the adjusted target. 282 void ApplyTouchAdjustment(WebGestureEvent*, HitTestLocation&, HitTestResult*); 283 284 void PerformHitTest(const HitTestLocation& location, 285 HitTestResult&, 286 bool no_lifecycle_update) const; 287 288 void UpdateGestureTargetNodeForMouseEvent( 289 const GestureEventWithHitTestResults&); 290 291 bool ShouldApplyTouchAdjustment(const WebGestureEvent&) const; 292 bool GestureCorrespondsToAdjustedTouch(const WebGestureEvent&); 293 bool IsSelectingLink(const HitTestResult&); 294 bool ShouldShowIBeamForNode(const Node*, const HitTestResult&); 295 bool ShouldShowResizeForNode(const Node*, const HitTestLocation&); 296 base::Optional<ui::Cursor> SelectCursor(const HitTestLocation& location, 297 const HitTestResult&); 298 base::Optional<ui::Cursor> SelectAutoCursor(const HitTestResult&, 299 Node*, 300 const ui::Cursor& i_beam); 301 302 void HoverTimerFired(TimerBase*); 303 void CursorUpdateTimerFired(TimerBase*); 304 void ActiveIntervalTimerFired(TimerBase*); 305 306 void UpdateCursor(); 307 308 ScrollableArea* AssociatedScrollableArea(const PaintLayer*) const; 309 310 Element* EffectiveMouseEventTargetElement(Element*); 311 312 // Dispatches ME after corresponding PE provided the PE has not been 313 // canceled. The |mouse_event_type| arg must be one of {mousedown, 314 // mousemove, mouseup}. 315 WebInputEventResult DispatchMousePointerEvent( 316 const WebInputEvent::Type, 317 Element* target, 318 const String& canvas_region_id, 319 const WebMouseEvent&, 320 const Vector<WebMouseEvent>& coalesced_events, 321 const Vector<WebMouseEvent>& predicted_events, 322 bool skip_click_dispatch = false); 323 324 WebInputEventResult PassMousePressEventToSubframe( 325 MouseEventWithHitTestResults&, 326 LocalFrame* subframe); 327 WebInputEventResult PassMouseMoveEventToSubframe( 328 MouseEventWithHitTestResults&, 329 const Vector<WebMouseEvent>& coalesced_events, 330 const Vector<WebMouseEvent>& predicted_events, 331 LocalFrame* subframe, 332 HitTestResult* hovered_node = nullptr, 333 HitTestLocation* hit_test_location = nullptr); 334 WebInputEventResult PassMouseReleaseEventToSubframe( 335 MouseEventWithHitTestResults&, 336 LocalFrame* subframe); 337 338 bool PassMousePressEventToScrollbar(MouseEventWithHitTestResults&); 339 340 void DefaultSpaceEventHandler(KeyboardEvent*); 341 void DefaultBackspaceEventHandler(KeyboardEvent*); 342 void DefaultTabEventHandler(KeyboardEvent*); 343 void DefaultEscapeEventHandler(KeyboardEvent*); 344 void DefaultArrowEventHandler(mojom::blink::FocusType, KeyboardEvent*); 345 346 // |last_scrollbar_under_mouse_| is set when the mouse moves off of a 347 // scrollbar, and used to notify it of MouseUp events to release mouse 348 // capture. 349 void UpdateLastScrollbarUnderMouse(Scrollbar*, bool); 350 351 WebInputEventResult HandleGestureShowPress(); 352 353 bool ShouldBrowserControlsConsumeScroll(FloatSize) const; 354 355 bool RootFrameTrackedActivePointerInCurrentFrame(PointerId pointer_id) const; 356 357 void CaptureMouseEventsToWidget(bool); 358 359 void ReleaseMouseCaptureFromLocalRoot(); 360 void ReleaseMouseCaptureFromCurrentFrame(); 361 362 MouseEventWithHitTestResults GetMouseEventTarget( 363 const HitTestRequest& request, 364 const WebMouseEvent& mev); 365 366 // NOTE: If adding a new field to this class please ensure that it is 367 // cleared in |EventHandler::clear()|. 368 369 const Member<LocalFrame> frame_; 370 371 const Member<SelectionController> selection_controller_; 372 373 // TODO(lanwei): Remove the below timers for updating hover and cursor. 374 TaskRunnerTimer<EventHandler> hover_timer_; 375 376 // TODO(rbyers): Mouse cursor update is page-wide, not per-frame. Page-wide 377 // state should move out of EventHandler to a new PageEventHandler class. 378 // crbug.com/449649 379 TaskRunnerTimer<EventHandler> cursor_update_timer_; 380 381 Member<Element> capturing_mouse_events_element_; 382 // |capturing_subframe_element_| has similar functionality as 383 // |capturing_mouse_events_element_|. It replaces |capturing_..| when 384 // UnifiedPointerCapture enabled. 385 Member<Element> capturing_subframe_element_; 386 387 // Indicates whether the current widget is capturing mouse input. 388 // Only used for local frame root EventHandlers. 389 bool is_widget_capturing_mouse_events_ = false; 390 391 Member<LocalFrame> last_mouse_move_event_subframe_; 392 Member<Scrollbar> last_scrollbar_under_mouse_; 393 394 Member<Node> drag_target_; 395 bool should_only_fire_drag_over_event_; 396 397 Member<HTMLFrameSetElement> frame_set_being_resized_; 398 399 // Local frames in the same local root share the same EventHandlerRegistry. 400 Member<EventHandlerRegistry> event_handler_registry_; 401 Member<ScrollManager> scroll_manager_; 402 Member<MouseEventManager> mouse_event_manager_; 403 Member<MouseWheelEventManager> mouse_wheel_event_manager_; 404 Member<KeyboardEventManager> keyboard_event_manager_; 405 Member<PointerEventManager> pointer_event_manager_; 406 Member<GestureManager> gesture_manager_; 407 Member<FallbackCursorEventManager> fallback_cursor_event_manager_; 408 409 double max_mouse_moved_duration_; 410 411 TaskRunnerTimer<EventHandler> active_interval_timer_; 412 413 // last_show_press_timestamp_ prevents the active state rewrited by 414 // following events too soon (less than 0.15s). It is ok we only record 415 // last_show_press_timestamp_ in root frame since root frame will have 416 // subframe as active element if subframe has active element. 417 base::Optional<base::TimeTicks> last_show_press_timestamp_; 418 Member<Element> last_deferred_tap_element_; 419 420 // Set on GestureTapDown if unique_touch_event_id_ matches cached adjusted 421 // touchstart event id. 422 bool should_use_touch_event_adjusted_point_; 423 424 // Stored the last touch type primary pointer down adjustment result. 425 // This is used in gesture event hit test. 426 TouchAdjustmentResult touch_adjustment_result_; 427 428 // ShouldShowIBeamForNode's unit tests: 429 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, HitOnNothingDoesNotShowIBeam); 430 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, HitOnTextShowsIBeam); 431 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 432 HitOnUserSelectNoneDoesNotShowIBeam); 433 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 434 ShadowChildCanOverrideUserSelectNone); 435 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 436 UserSelectAllCanOverrideUserSelectNone); 437 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 438 UserSelectNoneCanOverrideUserSelectAll); 439 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 440 UserSelectTextCanOverrideUserSelectNone); 441 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 442 UserSelectNoneCanOverrideUserSelectText); 443 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 444 ShadowChildCanOverrideUserSelectText); 445 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, InputFieldsCanStartSelection); 446 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, ImagesCannotStartSelection); 447 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, AnchorTextCannotStartSelection); 448 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 449 EditableAnchorTextCanStartSelection); 450 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 451 ReadOnlyInputDoesNotInheritUserSelect); 452 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 453 CursorForVerticalResizableTextArea); 454 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 455 CursorForHorizontalResizableTextArea); 456 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForResizableTextArea); 457 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForRtlResizableTextArea); 458 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, 459 CursorForInlineVerticalWritingMode); 460 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForBlockVerticalWritingMode); 461 462 FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, 463 MouseMoveCursorLockOnDiv); 464 FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, 465 MouseMoveCursorLockOnIFrame); 466 FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, KeyBackAndMouseMove); 467 FRIEND_TEST_ALL_PREFIXES(FallbackCursorEventManagerTest, MouseDownOnEditor); 468 469 DISALLOW_COPY_AND_ASSIGN(EventHandler); 470 }; 471 472 } // namespace blink 473 474 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_EVENT_HANDLER_H_ 475