// 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 COMPONENTS_INPUT_FLING_CONTROLLER_H_ #define COMPONENTS_INPUT_FLING_CONTROLLER_H_ #include "base/component_export.h" #include "base/memory/raw_ptr.h" #include "base/time/time.h" #include "components/input/touchpad_tap_suppression_controller.h" #include "components/input/touchscreen_tap_suppression_controller.h" #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" #include "ui/events/blink/fling_booster.h" namespace blink { class WebGestureCurve; } namespace input { class FlingController; inline constexpr float kDefaultPixelsPerInch = 96.0f; // Interface with which the FlingController can forward generated fling progress // events. class COMPONENT_EXPORT(INPUT) FlingControllerEventSenderClient { public: virtual ~FlingControllerEventSenderClient() = default; virtual void SendGeneratedWheelEvent( const MouseWheelEventWithLatencyInfo& wheel_event) = 0; virtual void SendGeneratedGestureScrollEvents( const GestureEventWithLatencyInfo& gesture_event) = 0; // Returns the size of visible viewport in screen space, in DIPs. virtual gfx::Size GetRootWidgetViewportSize() = 0; }; // Interface with which the fling progress gets scheduled. class COMPONENT_EXPORT(INPUT) FlingControllerSchedulerClient { public: virtual ~FlingControllerSchedulerClient() = default; virtual void ScheduleFlingProgress( base::WeakPtr fling_controller) = 0; virtual void DidStopFlingingOnBrowser( base::WeakPtr fling_controller) = 0; virtual bool NeedsBeginFrameForFlingProgress() = 0; virtual bool ShouldUseMobileFlingCurve() = 0; virtual gfx::Vector2dF GetPixelsPerInch( const gfx::PointF& position_in_screen) = 0; }; class COMPONENT_EXPORT(INPUT) FlingController { public: struct COMPONENT_EXPORT(INPUT) Config { Config(); // Controls touchpad-related tap suppression, disabled by default. TapSuppressionController::Config touchpad_tap_suppression_config; // Controls touchscreen-related tap suppression, disabled by default. TapSuppressionController::Config touchscreen_tap_suppression_config; }; struct ActiveFlingParameters { gfx::Vector2dF velocity; gfx::PointF point; gfx::PointF global_point; int modifiers; blink::WebGestureDevice source_device; base::TimeTicks start_time; ActiveFlingParameters() : modifiers(0) {} }; FlingController(FlingControllerEventSenderClient* event_sender_client, FlingControllerSchedulerClient* scheduler_client, const Config& config); FlingController(const FlingController&) = delete; FlingController& operator=(const FlingController&) = delete; ~FlingController(); // Used to progress an active fling on every begin frame. void ProgressFling(base::TimeTicks current_time); // Used to halt an active fling progress whenever needed. void StopFling(); // The fling controller needs to observe all gesture events. It may consume // or filter some events. It will return true if the event was consumed or // filtered and should not be propagated further. bool ObserveAndMaybeConsumeGestureEvent( const GestureEventWithLatencyInfo& gesture_event); void ProcessGestureFlingStart( const GestureEventWithLatencyInfo& gesture_event); void ProcessGestureFlingCancel( const GestureEventWithLatencyInfo& gesture_event); bool fling_in_progress() const { return fling_curve_.get(); } gfx::Vector2dF CurrentFlingVelocity() const; // Returns the |TouchpadTapSuppressionController| instance. TouchpadTapSuppressionController* GetTouchpadTapSuppressionController(); void set_clock_for_testing(const base::TickClock* clock) { clock_ = clock; } // The fling controller observes wheel event acks to track whether the latest // wheel event was consumed, in which case we should not start a fling scroll // for flings generated by a touchpad source. void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event, blink::mojom::InputEventResultSource ack_source, blink::mojom::InputEventResultState ack_result); protected: ui::FlingBooster fling_booster_; private: // Sub-filter for suppressing taps immediately after a GestureFlingCancel. bool ObserveAndFilterForTapSuppression( const GestureEventWithLatencyInfo& gesture_event); void ScheduleFlingProgress(); // Used to generate synthetic wheel events from touchpad fling and send them. void GenerateAndSendWheelEvents(base::TimeTicks current_time, const gfx::Vector2dF& delta, blink::WebMouseWheelEvent::Phase phase); // Used to generate synthetic gesture scroll events from touchscreen fling and // send them. void GenerateAndSendGestureScrollEvents( base::TimeTicks current_time, blink::WebInputEvent::Type type, const gfx::Vector2dF& delta = gfx::Vector2dF()); // Calls one of the GenerateAndSendWheelEvents or // GenerateAndSendGestureScrollEvents functions depending on the source // device of the current_fling_parameters_. We send GSU and wheel events // to progress flings with touchscreen and touchpad source respectively. // The reason for this difference is that during the touchpad fling we still // send wheel events to JS and generating GSU events directly is not enough. void GenerateAndSendFlingProgressEvents(base::TimeTicks current_time, const gfx::Vector2dF& delta); void GenerateAndSendFlingEndEvents(base::TimeTicks current_time); void EndCurrentFling(base::TimeTicks current_time); // Used to update the fling_curve_ state based on the parameters of the fling // start event. Returns true if the fling curve was updated for a valid // fling. Returns false if the parameters should not cause a fling and the // fling_curve_ is not updated. bool UpdateCurrentFlingState(const blink::WebGestureEvent& fling_start_event); bool first_fling_update_sent() const { return !last_progress_time_.is_null(); } raw_ptr event_sender_client_; raw_ptr scheduler_client_; // An object tracking the state of touchpad on the delivery of mouse events to // the renderer to filter mouse immediately after a touchpad fling canceling // tap. TouchpadTapSuppressionController touchpad_tap_suppression_controller_; // An object tracking the state of touchscreen on the delivery of gesture tap // events to the renderer to filter taps immediately after a touchscreen fling // canceling tap. TouchscreenTapSuppressionController touchscreen_tap_suppression_controller_; // Gesture curve of the current active fling. nullptr while a fling is not // active. std::unique_ptr fling_curve_; ActiveFlingParameters current_fling_parameters_; // The last time fling progress events were sent. base::TimeTicks last_progress_time_; // The clock used; overridable for tests. raw_ptr clock_; // Time of the last seen scroll update that wasn't filtered. Used to know the // starting time for a possible fling gesture curve. base::TimeTicks last_seen_scroll_update_; // Whether the last wheel event was consumed, to determine whether we should // allow a fling scroll. bool last_wheel_event_consumed_ = false; base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace input #endif // COMPONENTS_INPUT_FLING_CONTROLLER_H_