Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_pointer_manager.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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
6
8
9static constexpr int kMicrosecondsPerMillisecond = 1000;
10
13
14 // Engine to send pointer events to.
15 GWeakRef engine;
16
17 // ID to mark events with.
19
20 // TRUE if the mouse pointer is inside the view, used for generating missing
21 // add events.
23
24 // Pointer button state recorded for sending status updates.
25 int64_t button_state;
26};
27
28G_DEFINE_TYPE(FlPointerManager, fl_pointer_manager, G_TYPE_OBJECT);
29
30// 8 corresponds to mouse back button on both x11 and wayland
31static constexpr guint kMouseButtonBack = 8;
32
33// 9 corresponds to mouse forward button on both x11 and wayland
34static constexpr guint kMouseButtonForward = 9;
35
36// Convert a GDK button ID into a Flutter button ID
37static gboolean get_mouse_button(guint gdk_button, int64_t* button) {
38 switch (gdk_button) {
39 case GDK_BUTTON_PRIMARY:
41 return TRUE;
42 case GDK_BUTTON_MIDDLE:
44 return TRUE;
45 case GDK_BUTTON_SECONDARY:
47 return TRUE;
50 return TRUE;
53 return TRUE;
54 default:
55 return FALSE;
56 }
57}
58
59static gboolean get_button(FlutterPointerDeviceKind device_kind,
60 guint gdk_button,
61 int64_t* button) {
62 if (device_kind == kFlutterPointerDeviceKindStylus ||
64 // GDK button names describe the physical button action, where "primary"
65 // is the stylus tip contact. Flutter stylus button names reserve "primary"
66 // for the first barrel button, so the GDK secondary button maps there.
67 switch (gdk_button) {
68 case GDK_BUTTON_PRIMARY:
70 return TRUE;
71 case GDK_BUTTON_SECONDARY:
73 return TRUE;
74 case GDK_BUTTON_MIDDLE:
76 return TRUE;
77 default:
78 return FALSE;
79 }
80 }
81
82 return get_mouse_button(gdk_button, button);
83}
84
85// Generates a mouse pointer event if the pointer appears inside the window.
86static void ensure_pointer_added(FlPointerManager* self,
87 guint event_time,
88 FlutterPointerDeviceKind device_kind,
89 gdouble x,
90 gdouble y,
91 gdouble rotation,
92 gdouble pressure) {
93 if (self->pointer_inside) {
94 return;
95 }
96 self->pointer_inside = TRUE;
97
98 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
99 if (engine == nullptr) {
100 return;
101 }
102
104 engine, self->view_id, kAdd, event_time * kMicrosecondsPerMillisecond, x,
105 y, device_kind, 0, 0, self->button_state, rotation, pressure);
106}
107
108static void fl_pointer_manager_dispose(GObject* object) {
109 FlPointerManager* self = FL_POINTER_MANAGER(object);
110
111 g_weak_ref_clear(&self->engine);
112
113 G_OBJECT_CLASS(fl_pointer_manager_parent_class)->dispose(object);
114}
115
116static void fl_pointer_manager_class_init(FlPointerManagerClass* klass) {
117 G_OBJECT_CLASS(klass)->dispose = fl_pointer_manager_dispose;
118}
119
120static void fl_pointer_manager_init(FlPointerManager* self) {}
121
123 FlEngine* engine) {
124 FlPointerManager* self =
125 FL_POINTER_MANAGER(g_object_new(fl_pointer_manager_get_type(), nullptr));
126
127 self->view_id = view_id;
128 g_weak_ref_init(&self->engine, engine);
129
130 return self;
131}
132
134 FlPointerManager* self,
135 guint event_time,
136 FlutterPointerDeviceKind device_kind,
137 gdouble x,
138 gdouble y,
139 guint gdk_button,
140 gdouble rotation,
141 gdouble pressure) {
142 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
143
144 int64_t button;
145 if (!get_button(device_kind, gdk_button, &button)) {
146 return FALSE;
147 }
148
149 ensure_pointer_added(self, event_time, device_kind, x, y, rotation, pressure);
150
151 // Drop the event if Flutter already thinks the button is down.
152 if ((self->button_state & button) != 0) {
153 return FALSE;
154 }
155
156 int old_button_state = self->button_state;
158 self->button_state ^= button;
159 phase = old_button_state == 0 ? kDown : kMove;
160
161 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
162 if (engine == nullptr) {
163 return FALSE;
164 }
165
167 engine, self->view_id, phase, event_time * kMicrosecondsPerMillisecond, x,
168 y, device_kind, 0, 0, self->button_state, rotation, pressure);
169
170 return TRUE;
171}
172
174 FlPointerManager* self,
175 guint event_time,
176 FlutterPointerDeviceKind device_kind,
177 gdouble x,
178 gdouble y,
179 guint gdk_button,
180 gdouble rotation,
181 gdouble pressure) {
182 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
183
184 int64_t button;
185 if (!get_button(device_kind, gdk_button, &button)) {
186 return FALSE;
187 }
188
189 // Drop the event if Flutter already thinks the button is up.
190 if ((self->button_state & button) == 0) {
191 return FALSE;
192 }
193
195 self->button_state ^= button;
196
197 phase = self->button_state == 0 ? kUp : kMove;
198
199 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
200 if (engine == nullptr) {
201 return FALSE;
202 }
203
205 engine, self->view_id, phase, event_time * kMicrosecondsPerMillisecond, x,
206 y, device_kind, 0, 0, self->button_state, rotation, pressure);
207
208 return TRUE;
209}
210
211gboolean fl_pointer_manager_handle_motion(FlPointerManager* self,
212 guint event_time,
213 FlutterPointerDeviceKind device_kind,
214 gdouble x,
215 gdouble y,
216 gdouble rotation,
217 gdouble pressure) {
218 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
219
220 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
221 if (engine == nullptr) {
222 return FALSE;
223 }
224
225 ensure_pointer_added(self, event_time, device_kind, x, y, rotation, pressure);
226
228 engine, self->view_id, self->button_state != 0 ? kMove : kHover,
229 event_time * kMicrosecondsPerMillisecond, x, y, device_kind, 0, 0,
230 self->button_state, rotation, pressure);
231
232 return TRUE;
233}
234
235gboolean fl_pointer_manager_handle_enter(FlPointerManager* self,
236 guint event_time,
237 FlutterPointerDeviceKind device_kind,
238 gdouble x,
239 gdouble y,
240 gdouble rotation,
241 gdouble pressure) {
242 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
243
244 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
245 if (engine == nullptr) {
246 return FALSE;
247 }
248
249 ensure_pointer_added(self, event_time, device_kind, x, y, rotation, pressure);
250
251 return TRUE;
252}
253
254gboolean fl_pointer_manager_handle_leave(FlPointerManager* self,
255 guint event_time,
256 FlutterPointerDeviceKind device_kind,
257 gdouble x,
258 gdouble y,
259 gdouble rotation,
260 gdouble pressure) {
261 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
262
263 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
264 if (engine == nullptr) {
265 return FALSE;
266 }
267
268 // Don't remove pointer while button is down; In case of dragging outside of
269 // window with mouse grab active Gtk will send another leave notify on
270 // release.
271 if (self->pointer_inside && self->button_state == 0) {
273 event_time * kMicrosecondsPerMillisecond,
274 x, y, device_kind, 0, 0,
275 self->button_state, rotation, pressure);
276 self->pointer_inside = FALSE;
277 }
278
279 return TRUE;
280}
int32_t x
FlutterPointerPhase
The phase of the pointer event.
Definition embedder.h:1267
@ kHover
The pointer moved while up.
Definition embedder.h:1299
@ kUp
Definition embedder.h:1275
@ kRemove
Definition embedder.h:1297
@ kDown
Definition embedder.h:1282
@ kAdd
Definition embedder.h:1292
@ kMove
Definition embedder.h:1287
@ kFlutterPointerButtonMousePrimary
Definition embedder.h:1320
@ kFlutterPointerButtonMouseMiddle
Definition embedder.h:1322
@ kFlutterPointerButtonMouseForward
Definition embedder.h:1324
@ kFlutterPointerButtonMouseBack
Definition embedder.h:1323
@ kFlutterPointerButtonMouseSecondary
Definition embedder.h:1321
int64_t FlutterViewId
Definition embedder.h:393
@ kFlutterPointerButtonStylusSecondary
Definition embedder.h:1341
@ kFlutterPointerButtonStylusPrimary
Definition embedder.h:1338
@ kFlutterPointerButtonStylusContact
Definition embedder.h:1335
FlutterPointerDeviceKind
The device type that created a pointer event.
Definition embedder.h:1309
@ kFlutterPointerDeviceKindInvertedStylus
Definition embedder.h:1314
@ kFlutterPointerDeviceKindStylus
Definition embedder.h:1312
FlutterEngine engine
Definition main.cc:84
g_autoptr(FlEngine) engine
return TRUE
void fl_engine_send_mouse_pointer_event(FlEngine *self, FlutterViewId view_id, FlutterPointerPhase phase, size_t timestamp, double x, double y, FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons, double rotation, double pressure)
static gboolean get_button(FlutterPointerDeviceKind device_kind, guint gdk_button, int64_t *button)
gboolean fl_pointer_manager_handle_enter(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, gdouble rotation, gdouble pressure)
FlPointerManager * fl_pointer_manager_new(FlutterViewId view_id, FlEngine *engine)
G_DEFINE_TYPE(FlPointerManager, fl_pointer_manager, G_TYPE_OBJECT)
static void ensure_pointer_added(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, gdouble rotation, gdouble pressure)
static gboolean get_mouse_button(guint gdk_button, int64_t *button)
static void fl_pointer_manager_dispose(GObject *object)
static constexpr int kMicrosecondsPerMillisecond
gboolean fl_pointer_manager_handle_button_press(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, guint gdk_button, gdouble rotation, gdouble pressure)
static constexpr guint kMouseButtonForward
static constexpr guint kMouseButtonBack
static void fl_pointer_manager_class_init(FlPointerManagerClass *klass)
static void fl_pointer_manager_init(FlPointerManager *self)
gboolean fl_pointer_manager_handle_motion(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, gdouble rotation, gdouble pressure)
gboolean fl_pointer_manager_handle_button_release(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, guint gdk_button, gdouble rotation, gdouble pressure)
gboolean fl_pointer_manager_handle_leave(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, gdouble rotation, gdouble pressure)
G_BEGIN_DECLS FlutterViewId view_id
double y