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