summaryrefslogtreecommitdiff
path: root/chromium/content/browser/renderer_host/input/input_router_impl.h
blob: 9f2862155d0ea7a6e4ddc445716befcafb932c4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_
#define CONTENT_BROWSER_RENDERER_HOST_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/macros.h"
#include "base/time/time.h"
#include "cc/input/touch_action.h"
#include "content/browser/renderer_host/input/fling_scheduler.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
#include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/browser/renderer_host/input/touchpad_pinch_event_queue.h"
#include "content/common/input/input_event_stream_validator.h"
#include "content/common/input/input_handler.mojom.h"
#include "content/common/widget.mojom.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/common/input_event_ack_source.h"
#include "mojo/public/cpp/bindings/binding.h"

namespace ui {
class LatencyInfo;
struct DidOverscrollParams;
}  // namespace ui

namespace content {

class InputDispositionHandler;

class MockRenderWidgetHost;

class CONTENT_EXPORT InputRouterImplClient : public InputRouterClient {
 public:
  virtual mojom::WidgetInputHandler* GetWidgetInputHandler() = 0;
  virtual void OnImeCancelComposition() = 0;
  virtual void OnImeCompositionRangeChanged(
      const gfx::Range& range,
      const std::vector<gfx::Rect>& bounds) = 0;
};

// A default implementation for browser input event routing.
class CONTENT_EXPORT InputRouterImpl : public InputRouter,
                                       public GestureEventQueueClient,
                                       public FlingControllerEventSenderClient,
                                       public MouseWheelEventQueueClient,
                                       public PassthroughTouchEventQueueClient,
                                       public TouchpadPinchEventQueueClient,
                                       public mojom::WidgetInputHandlerHost {
 public:
  InputRouterImpl(InputRouterImplClient* client,
                  InputDispositionHandler* disposition_handler,
                  FlingControllerSchedulerClient* fling_scheduler_client,
                  const Config& config);
  ~InputRouterImpl() override;

  // InputRouter
  void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override;
  void SendWheelEvent(
      const MouseWheelEventWithLatencyInfo& wheel_event) override;
  void SendKeyboardEvent(
      const NativeWebKeyboardEventWithLatencyInfo& key_event) override;
  void SendGestureEvent(
      const GestureEventWithLatencyInfo& gesture_event) override;
  void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override;
  void NotifySiteIsMobileOptimized(bool is_mobile_optimized) override;
  bool HasPendingEvents() const override;
  void SetDeviceScaleFactor(float device_scale_factor) override;
  void SetFrameTreeNodeId(int frame_tree_node_id) override;
  void SetForceEnableZoom(bool enabled) override;
  base::Optional<cc::TouchAction> AllowedTouchAction() override;
  void BindHost(mojom::WidgetInputHandlerHostRequest request,
                bool frame_handler) override;
  void StopFling() override;
  bool FlingCancellationIsDeferred() override;
  void OnSetTouchAction(cc::TouchAction touch_action) override;
  void ForceSetTouchActionAuto() override;

  // InputHandlerHost impl
  void CancelTouchTimeout() override;
  void SetWhiteListedTouchAction(cc::TouchAction touch_action,
                                 uint32_t unique_touch_event_id,
                                 InputEventAckState state) override;
  void DidOverscroll(const ui::DidOverscrollParams& params) override;
  void ImeCancelComposition() override;
  void DidStartScrollingViewport() override;
  void ImeCompositionRangeChanged(
      const gfx::Range& range,
      const std::vector<gfx::Rect>& bounds) override;
  void SetMouseCapture(bool capture) override;

  // Exposed so that tests can swap out the implementation and intercept calls.
  mojo::Binding<mojom::WidgetInputHandlerHost>&
  frame_host_binding_for_testing() {
    return frame_host_binding_;
  }

  // IPC::Listener
  bool OnMessageReceived(const IPC::Message& message) override;

  void OnHasTouchEventHandlersForTest(bool has_handlers);

 private:
  friend class InputRouterImplTest;
  friend class MockRenderWidgetHost;
  friend class RenderWidgetHostBrowserTest;

  // Keeps track of last position of touch points and sets MovementXY for them.
  void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);

  void SendMouseEventImmediately(const MouseEventWithLatencyInfo& mouse_event);

  // PassthroughTouchEventQueueClient
  void SendTouchEventImmediately(
      const TouchEventWithLatencyInfo& touch_event) override;
  void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
                       InputEventAckSource ack_source,
                       InputEventAckState ack_result) override;
  void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override;

  // GestureEventFilterClient
  void SendGestureEventImmediately(
      const GestureEventWithLatencyInfo& gesture_event) override;
  void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
                         InputEventAckSource ack_source,
                         InputEventAckState ack_result) override;

  // FlingControllerEventSenderClient
  void SendGeneratedWheelEvent(
      const MouseWheelEventWithLatencyInfo& wheel_event) override;
  void SendGeneratedGestureScrollEvents(
      const GestureEventWithLatencyInfo& gesture_event) override;

  // MouseWheelEventQueueClient
  void SendMouseWheelEventImmediately(
      const MouseWheelEventWithLatencyInfo& touch_event) override;
  void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
                            InputEventAckSource ack_source,
                            InputEventAckState ack_result) override;
  void ForwardGestureEventWithLatencyInfo(
      const blink::WebGestureEvent& gesture_event,
      const ui::LatencyInfo& latency_info) override;
  bool IsWheelScrollInProgress() override;

  // TouchpadPinchEventQueueClient
  void SendMouseWheelEventForPinchImmediately(
      const MouseWheelEventWithLatencyInfo& event) override;
  void OnGestureEventForPinchAck(const GestureEventWithLatencyInfo& event,
                                 InputEventAckSource ack_source,
                                 InputEventAckState ack_result) override;

  void FilterAndSendWebInputEvent(
      const blink::WebInputEvent& input_event,
      const ui::LatencyInfo& latency_info,
      mojom::WidgetInputHandler::DispatchEventCallback callback);

  void KeyboardEventHandled(
      const NativeWebKeyboardEventWithLatencyInfo& event,
      InputEventAckSource source,
      const ui::LatencyInfo& latency,
      InputEventAckState state,
      const base::Optional<ui::DidOverscrollParams>& overscroll,
      const base::Optional<cc::TouchAction>& touch_action);
  void MouseEventHandled(
      const MouseEventWithLatencyInfo& event,
      InputEventAckSource source,
      const ui::LatencyInfo& latency,
      InputEventAckState state,
      const base::Optional<ui::DidOverscrollParams>& overscroll,
      const base::Optional<cc::TouchAction>& touch_action);
  void TouchEventHandled(
      const TouchEventWithLatencyInfo& touch_event,
      InputEventAckSource source,
      const ui::LatencyInfo& latency,
      InputEventAckState state,
      const base::Optional<ui::DidOverscrollParams>& overscroll,
      const base::Optional<cc::TouchAction>& touch_action);
  void GestureEventHandled(
      const GestureEventWithLatencyInfo& gesture_event,
      InputEventAckSource source,
      const ui::LatencyInfo& latency,
      InputEventAckState state,
      const base::Optional<ui::DidOverscrollParams>& overscroll,
      const base::Optional<cc::TouchAction>& touch_action);
  void MouseWheelEventHandled(
      const MouseWheelEventWithLatencyInfo& event,
      InputEventAckSource source,
      const ui::LatencyInfo& latency,
      InputEventAckState state,
      const base::Optional<ui::DidOverscrollParams>& overscroll,
      const base::Optional<cc::TouchAction>& touch_action);

  // IPC message handlers
  void OnHasTouchEventHandlers(bool has_handlers);

  // 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();

  InputRouterImplClient* client_;
  InputDispositionHandler* disposition_handler_;
  int frame_tree_node_id_;

  // Whether there are any active flings in the renderer. As the fling
  // end notification is asynchronous, we use a count rather than a boolean
  // to avoid races in bookkeeping when starting a new fling.
  int active_renderer_fling_count_;

  // Whether the TouchScrollStarted event has been sent for the current
  // gesture scroll yet.
  bool touch_scroll_started_sent_;

  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 binding associated with the widget input handler from
  // the widget.
  mojo::Binding<mojom::WidgetInputHandlerHost> host_binding_;

  // The host binding associated with the widget input handler from
  // the frame.
  mojo::Binding<mojom::WidgetInputHandlerHost> frame_host_binding_;

  base::WeakPtr<InputRouterImpl> weak_this_;
  base::WeakPtrFactory<InputRouterImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(InputRouterImpl);
};

}  // namespace content

#endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_