1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INPUT_INPUT_HANDLER_PROXY_H_
6 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INPUT_INPUT_HANDLER_PROXY_H_
7 
8 #include <memory>
9 
10 #include "base/macros.h"
11 #include "cc/input/input_handler.h"
12 #include "cc/input/snap_fling_controller.h"
13 #include "cc/paint/element_id.h"
14 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
15 #include "third_party/blink/public/common/input/web_gesture_event.h"
16 #include "third_party/blink/public/platform/input/synchronous_input_handler_proxy.h"
17 #include "third_party/blink/public/platform/web_common.h"
18 
19 namespace base {
20 class TickClock;
21 }
22 
23 namespace cc {
24 class EventMetrics;
25 }
26 
27 namespace ui {
28 class LatencyInfo;
29 }
30 
31 namespace blink {
32 class WebInputEventAttribution;
33 class WebMouseWheelEvent;
34 class WebTouchEvent;
35 class ElasticOverscrollController;
36 }  // namespace blink
37 
38 namespace blink {
39 
40 namespace test {
41 class InputHandlerProxyTest;
42 class InputHandlerProxyEventQueueTest;
43 class InputHandlerProxyMomentumScrollJankTest;
44 class InputHandlerProxyForceHandlingOnMainThread;
45 class TestInputHandlerProxy;
46 class UnifiedScrollingInputHandlerProxyTest;
47 }  // namespace test
48 
49 class CompositorThreadEventQueue;
50 class EventWithCallback;
51 class InputHandlerProxyClient;
52 class ScrollPredictor;
53 class SynchronousInputHandler;
54 class SynchronousInputHandlerProxy;
55 class MomentumScrollJankTracker;
56 class CursorControlHandler;
57 
58 // This class is a proxy between the blink web input events for a WebWidget and
59 // the compositor's input handling logic. InputHandlerProxy instances live
60 // entirely on the compositor thread if one exists; however, it can exist on
61 // the main thread in web tests where only a single thread is used.
62 // Each InputHandler instance handles input events intended for a specific
63 // WebWidget.
64 class BLINK_PLATFORM_EXPORT InputHandlerProxy
65     : public cc::InputHandlerClient,
66       public SynchronousInputHandlerProxy,
67       public cc::SnapFlingClient {
68  public:
69   InputHandlerProxy(cc::InputHandler& input_handler,
70                     InputHandlerProxyClient* client);
71   ~InputHandlerProxy() override;
72 
elastic_overscroll_controller()73   ElasticOverscrollController* elastic_overscroll_controller() {
74     return elastic_overscroll_controller_.get();
75   }
76 
77   // TODO(dtapuska): Eventually move this to mojo.
78   struct DidOverscrollParams {
79     gfx::Vector2dF accumulated_overscroll;
80     gfx::Vector2dF latest_overscroll_delta;
81     gfx::Vector2dF current_fling_velocity;
82     gfx::PointF causal_event_viewport_point;
83     cc::OverscrollBehavior overscroll_behavior;
84   };
85 
86   // Result codes returned to the client indicating the status of handling the
87   // event on the compositor. Used to determine further event handling behavior
88   // (i.e. should the event be forwarded to the main thread, ACK'ed to the
89   // browser, etc.).
90   enum EventDisposition {
91     // The event was handled on the compositor and should not be forwarded to
92     // the main thread.
93     DID_HANDLE,
94 
95     // The compositor could not handle the event but the event may still be
96     // valid for handling so it should be forwarded to the main thread.
97     DID_NOT_HANDLE,
98 
99     // Set only from a touchstart that occurred while a fling was in progress.
100     // Indicates that the rest of the touch stream should be sent non-blocking
101     // to ensure the scroll remains smooth. Since it's non-blocking, the event
102     // will be ACK'ed to the browser before being dispatched to the main
103     // thread.
104     // TODO(bokan): It's not clear that we need a separate status for this
105     // case, why can't we just use the DID_HANDLE_NON_BLOCKING below?
106     DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING,
107 
108     // Set to indicate that the event needs to be sent to the main thread (e.g.
109     // because the touch event hits a touch-event handler) but the compositor
110     // has determined it shouldn't be cancellable (e.g. the event handler is
111     // passive). Because it isn't cancellable, the event (and future events)
112     // will be sent non-blocking and be acked to the browser before being
113     // dispatchehd to the main thread.
114     // TODO(bokan): The semantics of DID/DID_NOT HANDLE are whether the main
115     // thread needs to know about the event. In this case, we expect the event
116     // to be forwarded to the main thread so this should be DID_NOT_HANDLE.
117     DID_HANDLE_NON_BLOCKING,
118 
119     // The compositor didn't handle the event but has determined the main
120     // thread doesn't care about the event either (e.g. it's a touch event and
121     // the hit point doesn't have a touch handler). In this case, we should ACK
122     // the event immediately. Both this and DID_HANDLE will avoid forwarding
123     // the event to the main thread and ACK immediately; the difference is that
124     // DROP_EVENT tells the client the event wasn't consumed. For example, the
125     // browser may choose to use this to avoid forwarding touch events if there
126     // isn't a consumer for them (and send only the scroll events).
127     DROP_EVENT,
128 
129     // The compositor did handle the scroll event (so it wouldn't forward the
130     // event to the main thread.) but it didn't consume the scroll so it should
131     // pass it to the next consumer (either overscrolling or bubbling the event
132     // to the next renderer).
133     DID_HANDLE_SHOULD_BUBBLE,
134 
135     // Used only in scroll unification; the compositor couldn't determine the
136     // scroll node to handle the event and requires a second try with an
137     // ElementId provided by a hit test in Blink.
138     REQUIRES_MAIN_THREAD_HIT_TEST,
139   };
140   using EventDispositionCallback = base::OnceCallback<void(
141       EventDisposition,
142       std::unique_ptr<blink::WebCoalescedInputEvent> event,
143       std::unique_ptr<DidOverscrollParams>,
144       const blink::WebInputEventAttribution&,
145       std::unique_ptr<cc::EventMetrics> metrics)>;
146   void HandleInputEventWithLatencyInfo(
147       std::unique_ptr<blink::WebCoalescedInputEvent> event,
148       std::unique_ptr<cc::EventMetrics> metrics,
149       EventDispositionCallback callback);
150 
151   // In scroll unification, a scroll begin event may initially return unhandled
152   // due to requiring the main thread to perform a hit test. In that case, the
153   // client will perform the hit test by calling into Blink. When it has a
154   // result, it can try handling the event again by calling back through this
155   // method.
156   void ContinueScrollBeginAfterMainThreadHitTest(
157       std::unique_ptr<blink::WebCoalescedInputEvent> event,
158       std::unique_ptr<cc::EventMetrics> metrics,
159       EventDispositionCallback callback,
160       cc::ElementIdType hit_tests_result);
161 
162   // Handles creating synthetic gesture events. It is currently used for
163   // creating gesture event equivalents for mouse events on a composited
164   // scrollbar. `original_metrics` contains metrics for the original mouse event
165   // and is used to generated metrics for the new gesture event.
166   void InjectScrollbarGestureScroll(
167       const blink::WebInputEvent::Type type,
168       const gfx::PointF& position_in_widget,
169       const cc::InputHandlerPointerResult& pointer_result,
170       const ui::LatencyInfo& latency_info,
171       const base::TimeTicks now,
172       const cc::EventMetrics* original_metrics);
173 
174   // Attempts to perform attribution of the given WebInputEvent to a target
175   // frame. Intended for simple impl-side hit testing.
176   blink::WebInputEventAttribution PerformEventAttribution(
177       const blink::WebInputEvent& event);
178 
179   // cc::InputHandlerClient implementation.
180   void WillShutdown() override;
181   void Animate(base::TimeTicks time) override;
182   void ReconcileElasticOverscrollAndRootScroll() override;
183   void UpdateRootLayerStateForSynchronousInputHandler(
184       const gfx::ScrollOffset& total_scroll_offset,
185       const gfx::ScrollOffset& max_scroll_offset,
186       const gfx::SizeF& scrollable_size,
187       float page_scale_factor,
188       float min_page_scale_factor,
189       float max_page_scale_factor) override;
190   void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override;
191   void DeliverInputForHighLatencyMode() override;
192 
193   // SynchronousInputHandlerProxy implementation.
194   void SetSynchronousInputHandler(
195       SynchronousInputHandler* synchronous_input_handler) override;
196   void SynchronouslySetRootScrollOffset(
197       const gfx::ScrollOffset& root_offset) override;
198   void SynchronouslyZoomBy(float magnify_delta,
199                            const gfx::Point& anchor) override;
200 
201   // SnapFlingClient implementation.
202   bool GetSnapFlingInfoAndSetAnimatingSnapTarget(
203       const gfx::Vector2dF& natural_displacement,
204       gfx::Vector2dF* initial_offset,
205       gfx::Vector2dF* target_offset) const override;
206   gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) override;
207   void ScrollEndForSnapFling(bool did_finish) override;
208   void RequestAnimationForSnapFling() override;
209 
gesture_scroll_on_impl_thread_for_testing()210   bool gesture_scroll_on_impl_thread_for_testing() const {
211     return handling_gesture_on_impl_thread_;
212   }
213 
currently_active_gesture_device()214   blink::WebGestureDevice currently_active_gesture_device() const {
215     return currently_active_gesture_device_.value();
216   }
217 
218  protected:
219   void RecordMainThreadScrollingReasons(blink::WebGestureDevice device,
220                                         uint32_t reasons);
221   void RecordScrollingThreadStatus(blink::WebGestureDevice device,
222                                    uint32_t reasons);
223 
224  private:
225   friend class test::TestInputHandlerProxy;
226   friend class test::InputHandlerProxyTest;
227   friend class test::UnifiedScrollingInputHandlerProxyTest;
228   friend class test::InputHandlerProxyEventQueueTest;
229   friend class test::InputHandlerProxyMomentumScrollJankTest;
230   friend class test::InputHandlerProxyForceHandlingOnMainThread;
231 
232   void DispatchSingleInputEvent(std::unique_ptr<EventWithCallback>,
233                                 const base::TimeTicks);
234   void DispatchQueuedInputEvents();
235 
236   // Helper functions for handling more complicated input events.
237   EventDisposition HandleMouseWheel(const blink::WebMouseWheelEvent& event);
238   EventDisposition HandleGestureScrollBegin(
239       const blink::WebGestureEvent& event);
240   EventDisposition HandleGestureScrollUpdate(
241       const blink::WebGestureEvent& event,
242       const blink::WebInputEventAttribution& original_attribution,
243       const cc::EventMetrics* original_metrics);
244   EventDisposition HandleGestureScrollEnd(const blink::WebGestureEvent& event);
245   EventDisposition HandleTouchStart(EventWithCallback* event_with_callback);
246   EventDisposition HandleTouchMove(EventWithCallback* event_with_callback);
247   EventDisposition HandleTouchEnd(EventWithCallback* event_with_callback);
248 
249   const cc::InputHandlerPointerResult HandlePointerDown(
250       EventWithCallback* event_with_callback,
251       const gfx::PointF& position);
252   const cc::InputHandlerPointerResult HandlePointerMove(
253       EventWithCallback* event_with_callback,
254       const gfx::PointF& position);
255   const cc::InputHandlerPointerResult HandlePointerUp(
256       EventWithCallback* event_with_callback,
257       const gfx::PointF& position);
258 
259   void InputHandlerScrollEnd();
260 
261   // Request a frame of animation from the InputHandler or
262   // SynchronousInputHandler. They can provide that by calling Animate().
263   void RequestAnimation();
264 
265   // Used to send overscroll messages to the browser. It bundles the overscroll
266   // params with with event ack.
267   void HandleOverscroll(const gfx::PointF& causal_event_viewport_point,
268                         const cc::InputHandlerScrollResult& scroll_result);
269 
270   // Update the elastic overscroll controller with |gesture_event|.
271   void HandleScrollElasticityOverscroll(
272       const blink::WebGestureEvent& gesture_event,
273       const cc::InputHandlerScrollResult& scroll_result);
274 
275   // Overrides the internal clock for testing.
276   // This doesn't take the ownership of the clock. |tick_clock| must outlive the
277   // InputHandlerProxy instance.
278   void SetTickClockForTesting(const base::TickClock* tick_clock);
279 
280   // |is_touching_scrolling_layer| indicates if one of the points that has
281   // been touched hits a currently scrolling layer. |allowed_touch_action| is
282   // the touch_action we are sure will be allowed for the given touch event.
283   EventDisposition HitTestTouchEvent(const blink::WebTouchEvent& touch_event,
284                                      bool* is_touching_scrolling_layer,
285                                      cc::TouchAction* allowed_touch_action);
286 
287   EventDisposition RouteToTypeSpecificHandler(
288       EventWithCallback* event_with_callback,
289       const blink::WebInputEventAttribution& original_attribution);
290 
set_event_attribution_enabled(bool enabled)291   void set_event_attribution_enabled(bool enabled) {
292     event_attribution_enabled_ = enabled;
293   }
294 
295   InputHandlerProxyClient* client_;
296 
297   // The input handler object is owned by the compositor delegate. The input
298   // handler must call WillShutdown() on this class before it is deleted at
299   // which point this pointer will be cleared.
300   cc::InputHandler* input_handler_;
301 
302   SynchronousInputHandler* synchronous_input_handler_;
303 
304   // This should be true when a pinch is in progress. The sequence of events is
305   // as follows: GSB GPB GSU GPU ... GPE GSE.
306   bool handling_gesture_on_impl_thread_;
307 
308   bool gesture_pinch_in_progress_ = false;
309   bool in_inertial_scrolling_ = false;
310   bool scroll_sequence_ignored_;
311 
312   // Used to animate rubber-band/bounce over-scroll effect.
313   std::unique_ptr<ElasticOverscrollController> elastic_overscroll_controller_;
314 
315   // The merged result of the last touch event with previous touch events
316   // within a single touch sequence. This value will get returned for
317   // subsequent TouchMove events to allow passive events not to block
318   // scrolling.
319   base::Optional<EventDisposition> touch_result_;
320 
321   // The result of the last mouse wheel event in a wheel phase sequence. This
322   // value is used to determine whether the next wheel scroll is blocked on the
323   // Main thread or not.
324   base::Optional<EventDisposition> mouse_wheel_result_;
325 
326   // Used to record overscroll notifications while an event is being
327   // dispatched.  If the event causes overscroll, the overscroll metadata is
328   // bundled in the event ack, saving an IPC.
329   std::unique_ptr<DidOverscrollParams> current_overscroll_params_;
330 
331   std::unique_ptr<CompositorThreadEventQueue> compositor_event_queue_;
332 
333   // Set only when the compositor input handler is handling a gesture. Tells
334   // which source device is currently performing a gesture based scroll.
335   base::Optional<blink::WebGestureDevice> currently_active_gesture_device_;
336 
337   // Tracks whether the first scroll update gesture event has been seen after a
338   // scroll begin. This is set/reset when scroll gestures are processed in
339   // HandleInputEventWithLatencyInfo and shouldn't be used outside the scope
340   // of that method.
341   bool has_seen_first_gesture_scroll_update_after_begin_;
342 
343   // Whether the last injected scroll gesture was a GestureScrollBegin. Used to
344   // determine which GestureScrollUpdate is the first in a gesture sequence for
345   // latency classification. This is separate from
346   // |is_first_gesture_scroll_update_| and is used to determine which type of
347   // latency component should be added for injected GestureScrollUpdates.
348   bool last_injected_gesture_was_begin_;
349 
350   const base::TickClock* tick_clock_;
351 
352   std::unique_ptr<cc::SnapFlingController> snap_fling_controller_;
353 
354   std::unique_ptr<ScrollPredictor> scroll_predictor_;
355 
356   // These flags are set for the SkipTouchEventFilter experiment. The
357   // experiment either skips filtering discrete (touch start/end) events to the
358   // main thread, or all events (touch start/end/move).
359   bool skip_touch_filter_discrete_ = false;
360   bool skip_touch_filter_all_ = false;
361 
362   // This bit is set when the input handler proxy has requested that the client
363   // perform a hit test for a scroll begin on the main thread. During that
364   // time, scroll updates need to be queued. The reply from the main thread
365   // will come by calling ContinueScrollBeginAfterMainThreadHitTest where the
366   // queue will be flushed and this bit cleared. Used only in scroll
367   // unification.
368   bool hit_testing_scroll_begin_on_main_thread_ = false;
369 
370   // This bit can be used to disable event attribution in cases where the
371   // hit test information is unnecessary (e.g. tests).
372   bool event_attribution_enabled_ = true;
373 
374   // Helpers for the momentum scroll jank UMAs.
375   std::unique_ptr<MomentumScrollJankTracker> momentum_scroll_jank_tracker_;
376 
377   // Swipe to move cursor feature.
378   std::unique_ptr<CursorControlHandler> cursor_control_handler_;
379 
380   DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy);
381 };
382 
383 }  // namespace blink
384 
385 #endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INPUT_INPUT_HANDLER_PROXY_H_
386