2 * Copyright (C) 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_EVENT_HANDLER_H_
27 #define THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_EVENT_HANDLER_H_
29 #include "base/gtest_prod_util.h"
30 #include "base/time/time.h"
31 #include "third_party/abseil-cpp/absl/types/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/platform/web_input_event_result.h"
35 #include "third_party/blink/renderer/core/core_export.h"
36 #include "third_party/blink/renderer/core/events/text_event_input_type.h"
37 #include "third_party/blink/renderer/core/input/gesture_manager.h"
38 #include "third_party/blink/renderer/core/input/keyboard_event_manager.h"
39 #include "third_party/blink/renderer/core/input/mouse_event_manager.h"
40 #include "third_party/blink/renderer/core/input/mouse_wheel_event_manager.h"
41 #include "third_party/blink/renderer/core/input/pointer_event_manager.h"
42 #include "third_party/blink/renderer/core/input/scroll_manager.h"
43 #include "third_party/blink/renderer/core/layout/hit_test_request.h"
44 #include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
45 #include "third_party/blink/renderer/core/page/touch_adjustment.h"
46 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
58 class EventHandlerRegistry;
59 template <typename EventType>
60 class EventWithHitTestResults;
61 class HTMLFrameSetElement;
69 class SelectionController;
71 class WebGestureEvent;
73 class WebMouseWheelEvent;
75 // Handles events for Pointers (Mouse/Touch), HitTests, DragAndDrop, etc.
76 class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
78 explicit EventHandler(LocalFrame&);
79 EventHandler(const EventHandler&) = delete;
80 EventHandler& operator=(const EventHandler&) = delete;
81 void Trace(Visitor*) const;
85 void UpdateSelectionForMouseDrag();
86 void StartMiddleClickAutoscroll(LayoutObject*);
88 // TODO(nzolghadr): Some of the APIs in this class only forward the action
89 // to the corresponding Manager class. We need to investigate whether it is
90 // better to expose the manager instance itself later or can the access to
91 // those APIs be more limited or removed.
93 void StopAutoscroll();
95 HitTestResult HitTestResultAtLocation(
96 const HitTestLocation&,
97 HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kReadOnly |
98 HitTestRequest::kActive,
99 const LayoutObject* stop_node = nullptr,
100 bool no_lifecycle_update = false);
102 bool MousePressed() const { return mouse_event_manager_->MousePressed(); }
103 bool IsMousePositionUnknown() const {
104 return mouse_event_manager_->IsMousePositionUnknown();
106 void ClearMouseEventManager() const { mouse_event_manager_->Clear(); }
108 WebInputEventResult UpdateDragAndDrop(const WebMouseEvent&, DataTransfer*);
109 void CancelDragAndDrop(const WebMouseEvent&, DataTransfer*);
110 WebInputEventResult PerformDragAndDrop(const WebMouseEvent&, DataTransfer*);
111 void UpdateDragStateAfterEditDragIfNeeded(Element* root_editable_element);
113 void ScheduleHoverStateUpdate();
114 void ScheduleCursorUpdate();
116 // Return whether a mouse cursor update is currently pending. Used for
118 bool CursorUpdatePending();
120 bool IsHandlingKeyEvent() const;
122 void SetResizingFrameSet(HTMLFrameSetElement*);
124 void ResizeScrollableAreaDestroyed();
126 gfx::PointF LastKnownMousePositionInRootFrame() const;
127 gfx::PointF LastKnownMouseScreenPosition() const;
129 gfx::Point DragDataTransferLocationForTesting();
131 // Performs a logical scroll that chains, crossing frames, starting from
132 // the given node or a reasonable default (focus/last clicked).
133 bool BubblingScroll(mojom::blink::ScrollDirection,
134 ui::ScrollGranularity,
135 Node* starting_node = nullptr);
137 WebInputEventResult HandleMouseMoveEvent(
138 const WebMouseEvent&,
139 const Vector<WebMouseEvent>& coalesced_events,
140 const Vector<WebMouseEvent>& predicted_events);
141 void HandleMouseLeaveEvent(const WebMouseEvent&);
143 WebInputEventResult HandlePointerEvent(
144 const WebPointerEvent&,
145 const Vector<WebPointerEvent>& coalesced_events,
146 const Vector<WebPointerEvent>& predicted_events);
148 WebInputEventResult DispatchBufferedTouchEvents();
150 WebInputEventResult HandleMousePressEvent(const WebMouseEvent&);
151 WebInputEventResult HandleMouseReleaseEvent(const WebMouseEvent&);
152 WebInputEventResult HandleWheelEvent(const WebMouseWheelEvent&);
154 WebInputEventResult HandleTargetedMouseEvent(
156 const WebMouseEvent&,
157 const AtomicString& event_type,
158 const Vector<WebMouseEvent>& coalesced_events,
159 const Vector<WebMouseEvent>& predicted_events);
161 // Called on the local root frame exactly once per gesture event.
162 WebInputEventResult HandleGestureEvent(const WebGestureEvent&);
163 WebInputEventResult HandleGestureEvent(const GestureEventWithHitTestResults&);
165 // Clear the old hover/active state within frames before moving the hover
166 // state to the another frame. |is_active| specifies whether the active state
167 // is being applied to or removed from the given element. This method should
168 // be initially called on the root document, it will recurse into child
170 void UpdateCrossFrameHoverActiveState(bool is_active, Element*);
172 // Hit-test the provided (non-scroll) gesture event, applying touch-adjustment
173 // and updating hover/active state across all frames if necessary. This should
174 // be called at most once per gesture event, and called on the local root
176 // Note: This is similar to (the less clearly named) prepareMouseEvent.
177 // FIXME: Remove readOnly param when there is only ever a single call to this.
178 GestureEventWithHitTestResults TargetGestureEvent(const WebGestureEvent&,
179 bool read_only = false);
180 GestureEventWithHitTestResults HitTestResultForGestureEvent(
181 const WebGestureEvent&,
182 HitTestRequest::HitTestRequestType);
184 // Handle the provided scroll gesture event, propagating down to child frames
186 WebInputEventResult HandleGestureScrollEvent(const WebGestureEvent&);
187 bool IsScrollbarHandlingGestures() const;
189 bool BestNodeForHitTestResult(TouchAdjustmentCandidateType candidate_type,
190 const HitTestLocation& location,
191 const HitTestResult&,
192 gfx::Point& adjusted_point,
193 Node*& adjusted_node);
194 void CacheTouchAdjustmentResult(uint32_t, gfx::PointF);
196 // Dispatch a context menu event. If |override_target_element| is provided,
197 // the context menu event will use that, so that the browser-generated context
198 // menu will be filled with options relevant to it, rather than the element
199 // found via hit testing the event's screen point. This is used so that a
200 // context menu generated via the keyboard reliably uses the correct target.
201 WebInputEventResult SendContextMenuEvent(
202 const WebMouseEvent&,
203 Element* override_target_element = nullptr);
204 WebInputEventResult ShowNonLocatedContextMenu(
205 Element* override_target_element = nullptr,
206 WebMenuSourceType = kMenuSourceNone);
208 // Returns whether pointerId is active or not
209 bool IsPointerEventActive(PointerId);
211 void SetPointerCapture(PointerId, Element*, bool explicit_capture = false);
212 void ReleasePointerCapture(PointerId, Element*);
213 void ReleaseMousePointerCapture();
214 bool HasPointerCapture(PointerId, const Element*) const;
216 void ElementRemoved(Element*);
218 void SetMouseDownMayStartAutoscroll();
220 bool HandleAccessKey(const WebKeyboardEvent&);
221 WebInputEventResult KeyEvent(const WebKeyboardEvent&);
222 void DefaultKeyboardEventHandler(KeyboardEvent*);
224 bool HandleTextInputEvent(const String& text,
225 Event* underlying_event = nullptr,
226 TextEventInputType = kTextEventInputKeyboard);
227 void DefaultTextInputEventHandler(TextEvent*);
229 void DragSourceEndedAt(const WebMouseEvent&, ui::mojom::blink::DragOperation);
231 void CapsLockStateMayHaveChanged(); // Only called by FrameSelection
233 static bool UsesHandCursor(const Node*);
235 void NotifyElementActivated();
237 SelectionController& GetSelectionController() const {
238 return *selection_controller_;
241 bool IsPointerIdActiveOnFrame(PointerId, LocalFrame*) const;
243 LocalFrame* DetermineActivePointerTrackerFrame(PointerId pointer_id) const;
244 #if BUILDFLAG(IS_EFL)
245 void ContextMenuEventForWordOrLinkSelection(const WebGestureEvent&);
248 #if BUILDFLAG(IS_TIZEN)
249 void EnterDragState();
252 // Clears drag target and related states. It is called when drag is done or
254 void ClearDragState();
256 #if BUILDFLAG(IS_TIZEN_TV)
257 bool ScrollNewPosition(const ScrollOffset&, LocalFrameView*);
258 bool ScrollWithMultiplier(const ScrollOffset&, Node*);
261 EventHandlerRegistry& GetEventHandlerRegistry() const {
262 return *event_handler_registry_;
265 GestureManager& GetGestureManager() const { return *gesture_manager_; }
267 KeyboardEventManager& GetKeyboardEventManager() const {
268 return *keyboard_event_manager_;
271 void RecomputeMouseHoverStateIfNeeded();
273 void MarkHoverStateDirty();
275 // Reset the last mouse position so that movement after unlock will be
276 // restart from the lock position.
277 void ResetMousePositionForPointerUnlock();
279 bool LongTapShouldInvokeContextMenu();
283 float cursor_accessibility_scale_factor() const {
284 return cursor_accessibility_scale_factor_;
286 void set_cursor_accessibility_scale_factor(float scale) {
287 cursor_accessibility_scale_factor_ = scale;
290 Element* GetElementUnderMouse();
292 Element* CurrentTouchDownElement();
294 void SetDelayedNavigationTaskHandle(TaskHandle task_handle);
296 TaskHandle& GetDelayedNavigationTaskHandle();
299 WebInputEventResult HandleMouseMoveOrLeaveEvent(
300 const WebMouseEvent&,
301 const Vector<WebMouseEvent>& coalesced_events,
302 const Vector<WebMouseEvent>& predicted_events,
303 HitTestResult* hovered_node = nullptr,
304 HitTestLocation* hit_test_location = nullptr);
306 // Updates the event, location and result to the adjusted target.
307 void ApplyTouchAdjustment(WebGestureEvent*, HitTestLocation&, HitTestResult&);
309 void PerformHitTest(const HitTestLocation& location,
311 bool no_lifecycle_update) const;
313 void UpdateGestureTargetNodeForMouseEvent(
314 const GestureEventWithHitTestResults&);
316 // Handle the provided non-scroll gesture event. Should be called only on the
318 WebInputEventResult HandleGestureEventInFrame(
319 const GestureEventWithHitTestResults&);
321 bool ShouldApplyTouchAdjustment(const WebGestureEvent&) const;
322 bool GestureCorrespondsToAdjustedTouch(const WebGestureEvent&);
323 bool IsSelectingLink(const HitTestResult&);
324 bool ShouldShowIBeamForNode(const Node*, const HitTestResult&);
325 bool ShouldShowResizeForNode(const LayoutObject&, const HitTestLocation&);
326 absl::optional<ui::Cursor> SelectCursor(const HitTestLocation& location,
327 const HitTestResult&);
328 absl::optional<ui::Cursor> SelectAutoCursor(const HitTestResult&,
330 const ui::Cursor& i_beam);
332 #if BUILDFLAG(IS_TIZEN_TV)
333 bool CanRunArrowScrolling(const HitTestResult&);
336 void HoverTimerFired(TimerBase*);
337 void CursorUpdateTimerFired(TimerBase*);
338 void ActiveIntervalTimerFired(TimerBase*);
340 ScrollableArea* AssociatedScrollableArea(const PaintLayer*) const;
342 Element* EffectiveMouseEventTargetElement(Element*);
344 // Task handle used to distinguish single/double click with some modifiers.
346 // When single click with some modifiers occurred, this task handle is set.
347 // If double click follows, this is cancelled and renderer emit double click
348 // event. (By default, it is handled by renderer as text selection.) If not,
349 // the delayed navigation is emitted.
351 // Currently, the target navigations are the followings:
353 // - Download (Alt-click with/without some other modifiers.)
354 // - Link Preview (Alt-click)
356 // For more details, see https://crbug.com/1428816.
357 TaskHandle delayed_navigation_task_handle_;
359 // Dispatches ME after corresponding PE provided the PE has not been
360 // canceled. The |mouse_event_type| arg must be one of {mousedown,
361 // mousemove, mouseup}.
362 WebInputEventResult DispatchMousePointerEvent(
363 const WebInputEvent::Type,
365 const WebMouseEvent&,
366 const Vector<WebMouseEvent>& coalesced_events,
367 const Vector<WebMouseEvent>& predicted_events,
368 bool skip_click_dispatch = false);
370 WebInputEventResult PassMousePressEventToSubframe(
371 MouseEventWithHitTestResults&,
372 LocalFrame* subframe);
373 WebInputEventResult PassMouseMoveEventToSubframe(
374 MouseEventWithHitTestResults&,
375 const Vector<WebMouseEvent>& coalesced_events,
376 const Vector<WebMouseEvent>& predicted_events,
377 LocalFrame* subframe,
378 HitTestResult* hovered_node = nullptr,
379 HitTestLocation* hit_test_location = nullptr);
380 WebInputEventResult PassMouseReleaseEventToSubframe(
381 MouseEventWithHitTestResults&,
382 LocalFrame* subframe);
384 bool PassMousePressEventToScrollbar(MouseEventWithHitTestResults&);
386 // |last_scrollbar_under_mouse_| is set when the mouse moves off of a
387 // scrollbar, and used to notify it of MouseUp events to release mouse
389 void UpdateLastScrollbarUnderMouse(Scrollbar*, bool);
391 WebInputEventResult HandleGestureShowPress();
393 bool RootFrameTrackedActivePointerInCurrentFrame(PointerId pointer_id) const;
395 void CaptureMouseEventsToWidget(bool);
397 void ReleaseMouseCaptureFromLocalRoot();
398 void ReleaseMouseCaptureFromCurrentFrame();
400 MouseEventWithHitTestResults GetMouseEventTarget(
401 const HitTestRequest& request,
402 const WebMouseEvent& mev);
404 // Returned rect is in local root frame coordinates.
405 gfx::Rect GetFocusedElementRectForNonLocatedContextMenu(
406 Element* focused_element);
408 // NOTE: If adding a new field to this class please ensure that it is
409 // cleared in |EventHandler::clear()|.
411 const Member<LocalFrame> frame_;
413 const Member<SelectionController> selection_controller_;
415 // TODO(lanwei): Remove the below timers for updating hover and cursor.
416 HeapTaskRunnerTimer<EventHandler> hover_timer_;
418 // TODO(rbyers): Mouse cursor update is page-wide, not per-frame. Page-wide
419 // state should move out of EventHandler to a new PageEventHandler class.
421 HeapTaskRunnerTimer<EventHandler> cursor_update_timer_;
423 Member<Element> capturing_mouse_events_element_;
424 // |capturing_subframe_element_| has similar functionality as
425 // |capturing_mouse_events_element_|. It replaces |capturing_..| when
426 // UnifiedPointerCapture enabled.
427 Member<Element> capturing_subframe_element_;
429 // Indicates whether the current widget is capturing mouse input.
430 // Only used for local frame root EventHandlers.
431 bool is_widget_capturing_mouse_events_ = false;
433 Member<LocalFrame> last_mouse_move_event_subframe_;
434 Member<Scrollbar> last_scrollbar_under_mouse_;
436 Member<Node> drag_target_;
437 bool should_only_fire_drag_over_event_;
439 Member<HTMLFrameSetElement> frame_set_being_resized_;
441 // Local frames in the same local root share the same EventHandlerRegistry.
442 Member<EventHandlerRegistry> event_handler_registry_;
443 Member<ScrollManager> scroll_manager_;
444 Member<MouseEventManager> mouse_event_manager_;
445 Member<MouseWheelEventManager> mouse_wheel_event_manager_;
446 Member<KeyboardEventManager> keyboard_event_manager_;
447 Member<PointerEventManager> pointer_event_manager_;
448 Member<GestureManager> gesture_manager_;
450 double max_mouse_moved_duration_;
452 float cursor_accessibility_scale_factor_ = 1.f;
454 HeapTaskRunnerTimer<EventHandler> active_interval_timer_;
456 // last_show_press_timestamp_ prevents the active state rewrited by
457 // following events too soon (less than 0.15s). It is ok we only record
458 // last_show_press_timestamp_ in root frame since root frame will have
459 // subframe as active element if subframe has active element.
460 absl::optional<base::TimeTicks> last_show_press_timestamp_;
461 Member<Element> last_deferred_tap_element_;
463 // Set on GestureTapDown if unique_touch_event_id_ matches cached adjusted
464 // touchstart event id.
465 bool should_use_touch_event_adjusted_point_;
467 // Stored the last touch type primary pointer down adjustment result.
468 // This is used in gesture event hit test.
469 TouchAdjustmentResult touch_adjustment_result_;
472 DOMNodeId mouse_down_target = kInvalidDOMNodeId;
473 DOMNodeId tap_target = kInvalidDOMNodeId;
474 base::TimeTicks mouse_down_time;
475 base::TimeTicks tap_time;
478 #if BUILDFLAG(IS_TIZEN_TV)
479 bool handled_mouse_left_button_press_event_ = false;
482 // ShouldShowIBeamForNode's unit tests:
483 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, HitOnNothingDoesNotShowIBeam);
484 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, HitOnTextShowsIBeam);
485 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
486 HitOnUserSelectNoneDoesNotShowIBeam);
487 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
488 ShadowChildCanOverrideUserSelectNone);
489 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
490 UserSelectAllCanOverrideUserSelectNone);
491 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
492 UserSelectNoneCanOverrideUserSelectAll);
493 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
494 UserSelectTextCanOverrideUserSelectNone);
495 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
496 UserSelectNoneCanOverrideUserSelectText);
497 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
498 ShadowChildCanOverrideUserSelectText);
499 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, InputFieldsCanStartSelection);
500 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, ImagesCannotStartSelection);
501 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, AnchorTextCannotStartSelection);
502 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
503 EditableAnchorTextCanStartSelection);
504 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
505 ReadOnlyInputDoesNotInheritUserSelect);
506 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
507 CursorForVerticalResizableTextArea);
508 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
509 CursorForHorizontalResizableTextArea);
510 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForResizableTextArea);
511 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForRtlResizableTextArea);
512 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
513 CursorForInlineVerticalWritingMode);
514 FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, CursorForBlockVerticalWritingMode);
519 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_INPUT_EVENT_HANDLER_H_