| Flutter Linux Embedder |

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
5 #include "flutter/shell/platform/linux/fl_pointer_manager.h"
6
7 #include "flutter/shell/platform/linux/fl_engine_private.h"
8
9 static constexpr int kMicrosecondsPerMillisecond = 1000;
10
11 struct _FlPointerManager {
12 GObject parent_instance;
13
14 // Engine to send pointer events to.
15 GWeakRef engine;
16
17 // ID to mark events with.
18 FlutterViewId view_id;
19
20 // TRUE if the mouse pointer is inside the view, used for generating missing
21 // add events.
22 gboolean pointer_inside;
23
24 // Pointer button state recorded for sending status updates.
25 int64_t button_state;
26 };
27
28 G_DEFINE_TYPE(FlPointerManager, fl_pointer_manager, G_TYPE_OBJECT);
29
30 // 8 corresponds to mouse back button on both x11 and wayland
31 static constexpr guint kMouseButtonBack = 8;
32
33 // 9 corresponds to mouse forward button on both x11 and wayland
34 static constexpr guint kMouseButtonForward = 9;
35
36 // Convert a GDK button ID into a Flutter button ID
37 static gboolean get_mouse_button(guint gdk_button, int64_t* button) {
38 switch (gdk_button) {
39 case GDK_BUTTON_PRIMARY:
40 *button = kFlutterPointerButtonMousePrimary;
41 return TRUE;
42 case GDK_BUTTON_MIDDLE:
43 *button = kFlutterPointerButtonMouseMiddle;
44 return TRUE;
45 case GDK_BUTTON_SECONDARY:
46 *button = kFlutterPointerButtonMouseSecondary;
47 return TRUE;
48 case kMouseButtonBack:
49 *button = kFlutterPointerButtonMouseBack;
50 return TRUE;
51 case kMouseButtonForward:
52 *button = kFlutterPointerButtonMouseForward;
53 return TRUE;
54 default:
55 return FALSE;
56 }
57 }
58
59 // Generates a mouse pointer event if the pointer appears inside the window.
60 static void ensure_pointer_added(FlPointerManager* self,
61 guint event_time,
62 FlutterPointerDeviceKind device_kind,
63 gdouble x,
64 gdouble y) {
65 if (self->pointer_inside) {
66 return;
67 }
68 self->pointer_inside = TRUE;
69
70 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
71 if (engine == nullptr) {
72 return;
73 }
74
75 fl_engine_send_mouse_pointer_event(
76 engine, self->view_id, kAdd, event_time * kMicrosecondsPerMillisecond, x,
77 y, device_kind, 0, 0, self->button_state);
78 }
79
80 static void fl_pointer_manager_dispose(GObject* object) {
81 FlPointerManager* self = FL_POINTER_MANAGER(object);
82
83 g_weak_ref_clear(&self->engine);
84
85 G_OBJECT_CLASS(fl_pointer_manager_parent_class)->dispose(object);
86 }
87
88 static void fl_pointer_manager_class_init(FlPointerManagerClass* klass) {
89 G_OBJECT_CLASS(klass)->dispose = fl_pointer_manager_dispose;
90 }
91
92 static void fl_pointer_manager_init(FlPointerManager* self) {}
93
94 FlPointerManager* fl_pointer_manager_new(FlutterViewId view_id,
95 FlEngine* engine) {
96 FlPointerManager* self =
97 FL_POINTER_MANAGER(g_object_new(fl_pointer_manager_get_type(), nullptr));
98
99 self->view_id = view_id;
100 g_weak_ref_init(&self->engine, engine);
101
102 return self;
103 }
104
105 gboolean fl_pointer_manager_handle_button_press(
106 FlPointerManager* self,
107 guint event_time,
108 FlutterPointerDeviceKind device_kind,
109 gdouble x,
110 gdouble y,
111 guint gdk_button) {
112 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
113
114 int64_t button;
115 if (!get_mouse_button(gdk_button, &button)) {
116 return FALSE;
117 }
118
119 ensure_pointer_added(self, event_time, device_kind, x, y);
120
121 // Drop the event if Flutter already thinks the button is down.
122 if ((self->button_state & button) != 0) {
123 return FALSE;
124 }
125
126 int old_button_state = self->button_state;
127 FlutterPointerPhase phase = kMove;
128 self->button_state ^= button;
129 phase = old_button_state == 0 ? kDown : kMove;
130
131 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
132 if (engine == nullptr) {
133 return FALSE;
134 }
135
136 fl_engine_send_mouse_pointer_event(
137 engine, self->view_id, phase, event_time * kMicrosecondsPerMillisecond, x,
138 y, device_kind, 0, 0, self->button_state);
139
140 return TRUE;
141 }
142
143 gboolean fl_pointer_manager_handle_button_release(
144 FlPointerManager* self,
145 guint event_time,
146 FlutterPointerDeviceKind device_kind,
147 gdouble x,
148 gdouble y,
149 guint gdk_button) {
150 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
151
152 int64_t button;
153 if (!get_mouse_button(gdk_button, &button)) {
154 return FALSE;
155 }
156
157 // Drop the event if Flutter already thinks the button is up.
158 if ((self->button_state & button) == 0) {
159 return FALSE;
160 }
161
162 FlutterPointerPhase phase = kMove;
163 self->button_state ^= button;
164
165 phase = self->button_state == 0 ? kUp : kMove;
166
167 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
168 if (engine == nullptr) {
169 return FALSE;
170 }
171
172 fl_engine_send_mouse_pointer_event(
173 engine, self->view_id, phase, event_time * kMicrosecondsPerMillisecond, x,
174 y, device_kind, 0, 0, self->button_state);
175
176 return TRUE;
177 }
178
179 gboolean fl_pointer_manager_handle_motion(FlPointerManager* self,
180 guint event_time,
181 FlutterPointerDeviceKind device_kind,
182 gdouble x,
183 gdouble y) {
184 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
185
186 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
187 if (engine == nullptr) {
188 return FALSE;
189 }
190
191 ensure_pointer_added(self, event_time, device_kind, x, y);
192
193 fl_engine_send_mouse_pointer_event(
194 engine, self->view_id, self->button_state != 0 ? kMove : kHover,
195 event_time * kMicrosecondsPerMillisecond, x, y, device_kind, 0, 0,
196 self->button_state);
197
198 return TRUE;
199 }
200
201 gboolean fl_pointer_manager_handle_enter(FlPointerManager* self,
202 guint event_time,
203 FlutterPointerDeviceKind device_kind,
204 gdouble x,
205 gdouble y) {
206 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
207
208 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
209 if (engine == nullptr) {
210 return FALSE;
211 }
212
213 ensure_pointer_added(self, event_time, device_kind, x, y);
214
215 return TRUE;
216 }
217
218 gboolean fl_pointer_manager_handle_leave(FlPointerManager* self,
219 guint event_time,
220 FlutterPointerDeviceKind device_kind,
221 gdouble x,
222 gdouble y) {
223 g_return_val_if_fail(FL_IS_POINTER_MANAGER(self), FALSE);
224
225 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
226 if (engine == nullptr) {
227 return FALSE;
228 }
229
230 // Don't remove pointer while button is down; In case of dragging outside of
231 // window with mouse grab active Gtk will send another leave notify on
232 // release.
233 if (self->pointer_inside && self->button_state == 0) {
234 fl_engine_send_mouse_pointer_event(engine, self->view_id, kRemove,
235 event_time * kMicrosecondsPerMillisecond,
236 x, y, device_kind, 0, 0,
237 self->button_state);
238 self->pointer_inside = FALSE;
239 }
240
241 return TRUE;
242 }
fl_engine_send_mouse_pointer_event
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)
Definition: fl_engine.cc:989
fl_engine_private.h
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_pointer_manager_handle_button_press
gboolean fl_pointer_manager_handle_button_press(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, guint gdk_button)
Definition: fl_pointer_manager.cc:105
fl_pointer_manager_new
FlPointerManager * fl_pointer_manager_new(FlutterViewId view_id, FlEngine *engine)
Definition: fl_pointer_manager.cc:94
fl_pointer_manager_handle_motion
gboolean fl_pointer_manager_handle_motion(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y)
Definition: fl_pointer_manager.cc:179
G_DEFINE_TYPE
G_DEFINE_TYPE(FlPointerManager, fl_pointer_manager, G_TYPE_OBJECT)
get_mouse_button
static gboolean get_mouse_button(guint gdk_button, int64_t *button)
Definition: fl_pointer_manager.cc:37
fl_pointer_manager_dispose
static void fl_pointer_manager_dispose(GObject *object)
Definition: fl_pointer_manager.cc:80
ensure_pointer_added
static void ensure_pointer_added(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y)
Definition: fl_pointer_manager.cc:60
fl_pointer_manager_handle_enter
gboolean fl_pointer_manager_handle_enter(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y)
Definition: fl_pointer_manager.cc:201
kMicrosecondsPerMillisecond
static constexpr int kMicrosecondsPerMillisecond
Definition: fl_pointer_manager.cc:9
kMouseButtonForward
static constexpr guint kMouseButtonForward
Definition: fl_pointer_manager.cc:34
fl_pointer_manager_handle_leave
gboolean fl_pointer_manager_handle_leave(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y)
Definition: fl_pointer_manager.cc:218
kMouseButtonBack
static constexpr guint kMouseButtonBack
Definition: fl_pointer_manager.cc:31
fl_pointer_manager_class_init
static void fl_pointer_manager_class_init(FlPointerManagerClass *klass)
Definition: fl_pointer_manager.cc:88
fl_pointer_manager_handle_button_release
gboolean fl_pointer_manager_handle_button_release(FlPointerManager *self, guint event_time, FlutterPointerDeviceKind device_kind, gdouble x, gdouble y, guint gdk_button)
Definition: fl_pointer_manager.cc:143
fl_pointer_manager_init
static void fl_pointer_manager_init(FlPointerManager *self)
Definition: fl_pointer_manager.cc:92
fl_pointer_manager.h
view_id
G_BEGIN_DECLS FlutterViewId view_id
Definition: fl_view_accessible.h:49
_FlPointerManager
Definition: fl_pointer_manager.cc:11
_FlPointerManager::engine
GWeakRef engine
Definition: fl_pointer_manager.cc:15
_FlPointerManager::button_state
int64_t button_state
Definition: fl_pointer_manager.cc:25
_FlPointerManager::view_id
FlutterViewId view_id
Definition: fl_pointer_manager.cc:18
_FlPointerManager::parent_instance
GObject parent_instance
Definition: fl_pointer_manager.cc:12
_FlPointerManager::pointer_inside
gboolean pointer_inside
Definition: fl_pointer_manager.cc:22