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
content / browser / renderer_host / input / touch_emulator_impl.h [blame]
// Copyright 2014 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_BROWSER_RENDERER_HOST_INPUT_TOUCH_EMULATOR_IMPL_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EMULATOR_IMPL_H_
#include <memory>
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "components/input/touch_emulator.h"
#include "components/input/touch_emulator_client.h"
#include "content/common/content_export.h"
#include "ui/base/cursor/cursor.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/gfx/geometry/size_f.h"
namespace blink {
class WebKeyboardEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
} // namespace blink
namespace input {
class RenderWidgetHostViewInput;
} // namespace input
namespace content {
class CONTENT_EXPORT TouchEmulatorImpl : public input::TouchEmulator {
public:
TouchEmulatorImpl(input::TouchEmulatorClient* client,
float device_scale_factor);
TouchEmulatorImpl(const TouchEmulatorImpl&) = delete;
TouchEmulatorImpl& operator=(const TouchEmulatorImpl&) = delete;
~TouchEmulatorImpl() override;
// TouchEmulator implementation.
void SetDeviceScaleFactor(float device_scale_factor) override;
void SetDoubleTapSupportForPageEnabled(bool enabled) override;
bool IsEnabled() const override;
bool HandleTouchEvent(const blink::WebTouchEvent& event) override;
void OnGestureEventAck(
const blink::WebGestureEvent& event,
input::RenderWidgetHostViewInput* target_view) override;
void OnViewDestroyed(
input::RenderWidgetHostViewInput* destroyed_view) override;
bool HandleTouchEventAck(
const blink::WebTouchEvent& event,
blink::mojom::InputEventResultState ack_result) override;
void Enable(Mode mode, ui::GestureProviderConfigType config_type);
void Disable();
// Returns |true| if the event was consumed. Consumed event should not
// propagate any further.
// TODO(dgozman): maybe pass latency info together with events.
bool HandleMouseEvent(const blink::WebMouseEvent& event,
input::RenderWidgetHostViewInput* target_view);
bool HandleMouseWheelEvent(const blink::WebMouseWheelEvent& event);
bool HandleKeyboardEvent(const blink::WebKeyboardEvent& event);
// Injects a touch event to be processed for gestures and optionally
// forwarded to the client. Only works in kInjectingTouchEvents mode.
void InjectTouchEvent(const blink::WebTouchEvent& event,
input::RenderWidgetHostViewInput* target_view,
base::OnceClosure completion_callback);
// Cancel any touches, for example, when focus is lost.
void CancelTouch();
// This is needed because SyntheticGestureSmoothDrag doesn't support setting
// key-modifiers on the drag sequence.
// https://crbug.com/901374.
void SetPinchGestureModeForTesting(bool pinch_gesture_mode);
bool suppress_next_fling_cancel_for_testing() const {
return suppress_next_fling_cancel_;
}
private:
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
bool RequiresDoubleTapGestureEvents() const override;
ui::Cursor InitCursorFromResource(int resource_id);
void InitCursors();
void ResetState();
void UpdateCursor();
bool UpdateShiftPressed(bool shift_pressed);
// Whether we should convert scrolls into pinches.
bool InPinchGestureMode() const;
void FillTouchEventAndPoint(const blink::WebMouseEvent& mouse_event,
const gfx::PointF& pos_in_root);
blink::WebGestureEvent GetPinchGestureEvent(
blink::WebInputEvent::Type type,
const blink::WebGestureEvent& original_event);
// The following methods generate and pass gesture events to the renderer.
void PinchBegin(const blink::WebGestureEvent& event);
void PinchUpdate(const blink::WebGestureEvent& event);
void PinchEnd(const blink::WebGestureEvent& event);
void ScrollEnd(const blink::WebGestureEvent& event);
// Offers the emulated event to |gesture_provider_|, conditionally forwarding
// it to the client if appropriate. Returns whether event was handled
// synchronously, and there will be no ack.
bool HandleEmulatedTouchEvent(blink::WebTouchEvent event,
input::RenderWidgetHostViewInput* target_view);
// Called when ack for injected touch has been received.
void OnInjectedTouchCompleted();
const raw_ptr<input::TouchEmulatorClient> client_;
// Emulator is enabled iff gesture provider is created.
// Disabled emulator does only process touch acks left from previous
// emulation. It does not intercept any events.
std::unique_ptr<ui::FilteredGestureProvider> gesture_provider_;
ui::GestureProviderConfigType gesture_provider_config_type_;
Mode mode_;
bool double_tap_enabled_;
// While emulation is on, default cursor is touch. Pressing shift changes
// cursor to the pinch one.
ui::Cursor touch_cursor_;
ui::Cursor pinch_cursor_;
gfx::SizeF cursor_size_;
float cursor_scale_factor_ = 0;
// These are used to drop extra mouse move events coming too quickly, so
// we don't handle too much touches in gesture provider.
bool last_mouse_event_was_move_;
base::TimeTicks last_mouse_move_timestamp_;
bool mouse_pressed_;
bool shift_pressed_;
bool pinch_gesture_mode_for_testing_;
blink::WebTouchEvent touch_event_;
int emulated_stream_active_sequence_count_;
int native_stream_active_sequence_count_;
raw_ptr<input::RenderWidgetHostViewInput> last_emulated_start_target_;
// TODO(einbinder): this relies on synchronous tap gesture generation and does
// not work for any other gestures. We should switch to callbacks which go
// through touches and gestures once that's available.
int pending_taps_count_;
// Whether we should suppress next fling cancel. This may happen when we
// did not send fling start in pinch mode.
bool suppress_next_fling_cancel_;
// Point which does not move while pinch-zooming.
gfx::PointF pinch_anchor_;
// The cumulative scale change from the start of pinch gesture.
float pinch_scale_;
bool pinch_gesture_active_;
base::queue<base::OnceClosure> injected_touch_completion_callbacks_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EMULATOR_IMPL_H_