| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_COMMON_INPUT_INPUT_ROUTER_IMPL_H_ |
| #define CONTENT_COMMON_INPUT_INPUT_ROUTER_IMPL_H_ |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <queue> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "cc/input/touch_action.h" |
| #include "content/common/content_export.h" |
| #include "content/common/input/gesture_event_queue.h" |
| #include "content/common/input/input_event_stream_validator.h" |
| #include "content/common/input/input_router.h" |
| #include "content/common/input/input_router_client.h" |
| #include "content/common/input/mouse_wheel_event_queue.h" |
| #include "content/common/input/passthrough_touch_event_queue.h" |
| #include "content/common/input/touch_action_filter.h" |
| #include "content/common/input/touchpad_pinch_event_queue.h" |
| #include "mojo/public/cpp/bindings/pending_remote.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" |
| #include "third_party/blink/public/mojom/input/input_handler.mojom.h" |
| |
| namespace ui { |
| class LatencyInfo; |
| } // namespace ui |
| |
| namespace content { |
| |
| class InputDispositionHandler; |
| |
| class MockRenderWidgetHost; |
| |
| class StylusInterface { |
| public: |
| virtual ~StylusInterface() = default; |
| |
| virtual bool ShouldInitiateStylusWriting() = 0; |
| virtual void NotifyHoverActionStylusWritable(bool stylus_writable) = 0; |
| }; |
| |
| class CONTENT_EXPORT InputRouterImplClient : public InputRouterClient { |
| public: |
| virtual blink::mojom::WidgetInputHandler* GetWidgetInputHandler() = 0; |
| virtual void OnImeCancelComposition() = 0; |
| virtual void OnImeCompositionRangeChanged( |
| const gfx::Range& range, |
| const std::optional<std::vector<gfx::Rect>>& character_bounds, |
| const std::optional<std::vector<gfx::Rect>>& line_bounds) = 0; |
| virtual StylusInterface* GetStylusInterface() = 0; |
| virtual void OnStartStylusWriting() = 0; |
| }; |
| |
| // A default implementation for browser input event routing. |
| class CONTENT_EXPORT InputRouterImpl |
| : public InputRouter, |
| public GestureEventQueueClient, |
| public input::FlingControllerEventSenderClient, |
| public MouseWheelEventQueueClient, |
| public PassthroughTouchEventQueueClient, |
| public TouchpadPinchEventQueueClient, |
| public blink::mojom::WidgetInputHandlerHost { |
| public: |
| InputRouterImpl(InputRouterImplClient* client, |
| InputDispositionHandler* disposition_handler, |
| input::FlingControllerSchedulerClient* fling_scheduler_client, |
| const Config& config); |
| |
| InputRouterImpl(const InputRouterImpl&) = delete; |
| InputRouterImpl& operator=(const InputRouterImpl&) = delete; |
| |
| ~InputRouterImpl() override; |
| |
| // InputRouter |
| void SendMouseEvent(const input::MouseEventWithLatencyInfo& mouse_event, |
| MouseEventCallback event_result_callback) override; |
| void SendWheelEvent( |
| const input::MouseWheelEventWithLatencyInfo& wheel_event) override; |
| void SendKeyboardEvent( |
| const input::NativeWebKeyboardEventWithLatencyInfo& key_event, |
| KeyboardEventCallback event_result_callback) override; |
| void SendGestureEvent( |
| const input::GestureEventWithLatencyInfo& gesture_event) override; |
| void SendTouchEvent( |
| const input::TouchEventWithLatencyInfo& touch_event) override; |
| void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override; |
| bool HasPendingEvents() const override; |
| void SetDeviceScaleFactor(float device_scale_factor) override; |
| void SetForceEnableZoom(bool enabled) override; |
| std::optional<cc::TouchAction> AllowedTouchAction() override; |
| std::optional<cc::TouchAction> ActiveTouchAction() override; |
| mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewHost( |
| scoped_refptr<base::SequencedTaskRunner> task_runner) override; |
| void StopFling() override; |
| void ForceSetTouchActionAuto() override; |
| |
| // InputHandlerHost impl |
| void SetTouchActionFromMain(cc::TouchAction touch_action) override; |
| void SetPanAction(blink::mojom::PanAction pan_action) override; |
| void DidOverscroll(blink::mojom::DidOverscrollParamsPtr params) override; |
| void ImeCancelComposition() override; |
| void DidStartScrollingViewport() override; |
| void ImeCompositionRangeChanged( |
| const gfx::Range& range, |
| const std::optional<std::vector<gfx::Rect>>& character_bounds, |
| const std::optional<std::vector<gfx::Rect>>& line_bounds) override; |
| void SetMouseCapture(bool capture) override; |
| void SetAutoscrollSelectionActiveInMainFrame( |
| bool autoscroll_selection) override; |
| void RequestMouseLock(bool from_user_gesture, |
| bool unadjusted_movement, |
| RequestMouseLockCallback response) override; |
| // Notifies touch action filter and touch event queue whether there are |
| // JavaScript touch event handlers or not, or whether the platform has |
| // hit-testable scrollbars. |
| void OnHasTouchEventConsumers( |
| blink::mojom::TouchEventConsumersPtr consumers) override; |
| void WaitForInputProcessed(base::OnceClosure callback) override; |
| void FlushTouchEventQueue() override; |
| |
| // Exposed so that tests can swap out the implementation and intercept calls. |
| mojo::Receiver<blink::mojom::WidgetInputHandlerHost>& |
| host_receiver_for_testing() { |
| return host_receiver_; |
| } |
| |
| void ForceResetTouchActionForTest(); |
| |
| bool IsFlingActiveForTest(); |
| |
| private: |
| friend class InputRouterImplTest; |
| friend class InputRouterImplTestBase; |
| friend class MockRenderWidgetHost; |
| friend class RenderWidgetHostSitePerProcessTest; |
| friend class SitePerProcessBrowserTouchActionTest; |
| |
| // Keeps track of last position of touch points and sets MovementXY for them. |
| void SetMovementXYForTouchPoints(blink::WebTouchEvent* event); |
| |
| void SendMouseEventImmediately( |
| const input::MouseEventWithLatencyInfo& mouse_event, |
| MouseEventCallback event_result_callback); |
| |
| // PassthroughTouchEventQueueClient |
| void SendTouchEventImmediately( |
| const input::TouchEventWithLatencyInfo& touch_event) override; |
| void OnTouchEventAck(const input::TouchEventWithLatencyInfo& event, |
| blink::mojom::InputEventResultSource ack_source, |
| blink::mojom::InputEventResultState ack_result) override; |
| void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override; |
| void FlushDeferredGestureQueue() override; |
| |
| // GestureEventFilterClient |
| void SendGestureEventImmediately( |
| const input::GestureEventWithLatencyInfo& gesture_event) override; |
| void OnGestureEventAck( |
| const input::GestureEventWithLatencyInfo& event, |
| blink::mojom::InputEventResultSource ack_source, |
| blink::mojom::InputEventResultState ack_result) override; |
| |
| // FlingControllerEventSenderClient |
| void SendGeneratedWheelEvent( |
| const input::MouseWheelEventWithLatencyInfo& wheel_event) override; |
| void SendGeneratedGestureScrollEvents( |
| const input::GestureEventWithLatencyInfo& gesture_event) override; |
| gfx::Size GetRootWidgetViewportSize() override; |
| |
| // MouseWheelEventQueueClient |
| void SendMouseWheelEventImmediately( |
| const input::MouseWheelEventWithLatencyInfo& touch_event, |
| MouseWheelEventQueueClient::MouseWheelEventHandledCallback callback) |
| override; |
| void OnMouseWheelEventAck( |
| const input::MouseWheelEventWithLatencyInfo& event, |
| blink::mojom::InputEventResultSource ack_source, |
| blink::mojom::InputEventResultState ack_result) override; |
| void ForwardGestureEventWithLatencyInfo( |
| const blink::WebGestureEvent& gesture_event, |
| const ui::LatencyInfo& latency_info) override; |
| bool IsWheelScrollInProgress() override; |
| bool IsAutoscrollInProgress() override; |
| |
| // TouchpadPinchEventQueueClient |
| void SendMouseWheelEventForPinchImmediately( |
| const input::MouseWheelEventWithLatencyInfo& event, |
| TouchpadPinchEventQueueClient::MouseWheelEventHandledCallback callback) |
| override; |
| void OnGestureEventForPinchAck( |
| const input::GestureEventWithLatencyInfo& event, |
| blink::mojom::InputEventResultSource ack_source, |
| blink::mojom::InputEventResultState ack_result) override; |
| |
| bool HandleGestureScrollForStylusWriting(const blink::WebGestureEvent& event); |
| |
| void FilterAndSendWebInputEvent( |
| const blink::WebInputEvent& input_event, |
| const ui::LatencyInfo& latency_info, |
| blink::mojom::WidgetInputHandler::DispatchEventCallback callback); |
| |
| void KeyboardEventHandled( |
| const input::NativeWebKeyboardEventWithLatencyInfo& event, |
| KeyboardEventCallback event_result_callback, |
| blink::mojom::InputEventResultSource source, |
| const ui::LatencyInfo& latency, |
| blink::mojom::InputEventResultState state, |
| blink::mojom::DidOverscrollParamsPtr overscroll, |
| blink::mojom::TouchActionOptionalPtr touch_action); |
| void MouseEventHandled(const input::MouseEventWithLatencyInfo& event, |
| MouseEventCallback event_result_callback, |
| blink::mojom::InputEventResultSource source, |
| const ui::LatencyInfo& latency, |
| blink::mojom::InputEventResultState state, |
| blink::mojom::DidOverscrollParamsPtr overscroll, |
| blink::mojom::TouchActionOptionalPtr touch_action); |
| void TouchEventHandled(const input::TouchEventWithLatencyInfo& touch_event, |
| blink::mojom::InputEventResultSource source, |
| const ui::LatencyInfo& latency, |
| blink::mojom::InputEventResultState state, |
| blink::mojom::DidOverscrollParamsPtr overscroll, |
| blink::mojom::TouchActionOptionalPtr touch_action); |
| void GestureEventHandled( |
| const input::GestureEventWithLatencyInfo& gesture_event, |
| blink::mojom::InputEventResultSource source, |
| const ui::LatencyInfo& latency, |
| blink::mojom::InputEventResultState state, |
| blink::mojom::DidOverscrollParamsPtr overscroll, |
| blink::mojom::TouchActionOptionalPtr touch_action); |
| void MouseWheelEventHandled( |
| const input::MouseWheelEventWithLatencyInfo& event, |
| MouseWheelEventQueueClient::MouseWheelEventHandledCallback callback, |
| blink::mojom::InputEventResultSource source, |
| const ui::LatencyInfo& latency, |
| blink::mojom::InputEventResultState state, |
| blink::mojom::DidOverscrollParamsPtr overscroll, |
| blink::mojom::TouchActionOptionalPtr touch_action); |
| |
| // Called when a touch timeout-affecting bit has changed, in turn toggling the |
| // touch ack timeout feature of the |touch_event_queue_| as appropriate. Input |
| // to that determination includes current view properties and the allowed |
| // touch action. Note that this will only affect platforms that have a |
| // non-zero touch timeout configuration. |
| void UpdateTouchAckTimeoutEnabled(); |
| |
| void SendGestureEventWithoutQueueing( |
| input::GestureEventWithLatencyInfo& gesture_event, |
| const FilterGestureEventResult& existing_result); |
| void ProcessDeferredGestureEventQueue(); |
| void OnSetCompositorAllowedTouchAction(cc::TouchAction touch_action); |
| |
| raw_ptr<InputRouterImplClient> client_; |
| raw_ptr<InputDispositionHandler> disposition_handler_; |
| |
| // Whether the TouchScrollStarted event has been sent for the current |
| // gesture scroll yet. |
| bool touch_scroll_started_sent_; |
| |
| // Whether stylus writing has started. |
| bool stylus_writing_started_ = false; |
| |
| // Stores the pan action possible for element under hovering pointer. Ex: |
| // stylus writing, moving cursor or scrolling. This is set from main thread. |
| blink::mojom::PanAction pan_action_ = blink::mojom::PanAction::kNone; |
| |
| MouseWheelEventQueue wheel_event_queue_; |
| PassthroughTouchEventQueue touch_event_queue_; |
| TouchpadPinchEventQueue touchpad_pinch_event_queue_; |
| GestureEventQueue gesture_event_queue_; |
| TouchActionFilter touch_action_filter_; |
| InputEventStreamValidator input_stream_validator_; |
| InputEventStreamValidator output_stream_validator_; |
| |
| float device_scale_factor_; |
| |
| // Last touch position relative to screen. Used to compute movementX/Y. |
| base::flat_map<int, gfx::Point> global_touch_position_; |
| |
| // The host receiver associated with the widget input handler from |
| // the widget. |
| mojo::Receiver<blink::mojom::WidgetInputHandlerHost> host_receiver_{this}; |
| |
| base::WeakPtr<InputRouterImpl> weak_this_; |
| base::WeakPtrFactory<InputRouterImpl> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_COMMON_INPUT_INPUT_ROUTER_IMPL_H_ |