Flutter Linux Embedder
fl_touch_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 
7 
8 static constexpr int kMicrosecondsPerMillisecond = 1000;
9 static const int kMinTouchDeviceId = 0;
10 static const int kMaxTouchDeviceId = 128;
11 
13  GObject parent_instance;
14 
15  GWeakRef engine;
16 
17  FlutterViewId view_id;
18 
19  // List of touch device IDs that have been added to the engine.
21 
22  GHashTable* number_to_id;
23 
24  // Minimum touch device ID that can be used.
26 };
27 
28 G_DEFINE_TYPE(FlTouchManager, fl_touch_manager, G_TYPE_OBJECT);
29 
30 static void fl_touch_manager_dispose(GObject* object) {
31  FlTouchManager* self = FL_TOUCH_MANAGER(object);
32 
33  g_weak_ref_clear(&self->engine);
34 
35  g_list_free(self->added_touch_devices);
36 
37  g_clear_pointer(&self->number_to_id, g_hash_table_unref);
38 
39  G_OBJECT_CLASS(fl_touch_manager_parent_class)->dispose(object);
40 }
41 
42 static void fl_touch_manager_class_init(FlTouchManagerClass* klass) {
43  G_OBJECT_CLASS(klass)->dispose = fl_touch_manager_dispose;
44 }
45 
46 static void fl_touch_manager_init(FlTouchManager* self) {}
47 
48 FlTouchManager* fl_touch_manager_new(FlEngine* engine, FlutterViewId view_id) {
49  g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);
50 
51  FlTouchManager* self =
52  FL_TOUCH_MANAGER(g_object_new(fl_touch_manager_get_type(), nullptr));
53 
54  g_weak_ref_init(&self->engine, engine);
55  self->view_id = view_id;
56 
57  self->number_to_id =
58  g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr, nullptr);
59 
60  self->min_touch_device_id = kMinTouchDeviceId;
61 
62  return self;
63 }
64 
65 // Ensures that a touch add event is sent for the given device.
67  guint event_time,
68  gdouble x,
69  gdouble y,
70  int32_t touch_id,
71  int32_t device_id) {
72  // Check if we need to send a touch add event.
73  if (g_list_find(self->added_touch_devices, GINT_TO_POINTER(touch_id)) !=
74  nullptr) {
75  return;
76  }
77 
78  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
79  if (engine == nullptr) {
80  return;
81  }
82 
83  fl_engine_send_touch_add_event(engine, self->view_id,
84  event_time * kMicrosecondsPerMillisecond, x, y,
85  device_id);
86 
87  self->added_touch_devices =
88  g_list_append(self->added_touch_devices, GINT_TO_POINTER(touch_id));
89 }
90 
91 // Generates a unique ID to represent |number|. The generated ID is the
92 // smallest available ID greater than or equal to the minimum touch device ID.
93 static uint32_t get_generated_id(_FlTouchManager* self, uint32_t number) {
94  gpointer value;
95  if (g_hash_table_lookup_extended(self->number_to_id, GUINT_TO_POINTER(number),
96  nullptr, &value)) {
97  uint32_t id;
98  if (value == nullptr) {
99  id = 0;
100  } else {
101  id = GPOINTER_TO_UINT(value);
102  }
103  return id;
104  }
105  auto values = g_hash_table_get_values(self->number_to_id);
106  while (values != nullptr &&
107  g_list_find(values, GUINT_TO_POINTER(self->min_touch_device_id)) !=
108  nullptr &&
109  self->min_touch_device_id < kMaxTouchDeviceId) {
110  ++self->min_touch_device_id;
111  }
112  if (self->min_touch_device_id >= kMaxTouchDeviceId) {
113  self->min_touch_device_id = kMinTouchDeviceId;
114  }
115 
116  g_hash_table_insert(self->number_to_id, GUINT_TO_POINTER(number),
117  GUINT_TO_POINTER(self->min_touch_device_id));
118  return self->min_touch_device_id;
119 }
120 
121 static void release_number(_FlTouchManager* self, uint32_t number) {
122  if (g_hash_table_contains(self->number_to_id, GINT_TO_POINTER(number))) {
123  auto id = g_hash_table_lookup(self->number_to_id, GINT_TO_POINTER(number));
124  if (GPOINTER_TO_UINT(id) < self->min_touch_device_id) {
125  self->min_touch_device_id = GPOINTER_TO_UINT(id);
126  }
127  g_hash_table_remove(self->number_to_id, GINT_TO_POINTER(number));
128  }
129 }
130 
131 void fl_touch_manager_handle_touch_event(FlTouchManager* self,
132  GdkEventTouch* touch_event,
133  gint scale_factor) {
134  g_return_if_fail(FL_IS_TOUCH_MANAGER(self));
135 
136  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
137  if (engine == nullptr) {
138  return;
139  }
140 
141  GdkEvent* event = reinterpret_cast<GdkEvent*>(touch_event);
142  // get sequence id from GdkEvent
143  GdkEventSequence* seq = gdk_event_get_event_sequence(event);
144  // cast pointer to int to get unique id
145  uint32_t id = reinterpret_cast<uint64_t>(seq);
146  // generate touch id from unique id
147  auto touch_id = get_generated_id(self, id);
148  // get device id
149  auto device_id =
150  static_cast<int32_t>(kFlutterPointerDeviceKindTouch) << 28 | touch_id;
151 
152  gdouble event_x = 0.0, event_y = 0.0;
153  gdk_event_get_coords(event, &event_x, &event_y);
154 
155  double x = event_x * scale_factor;
156  double y = event_y * scale_factor;
157 
158  guint event_time = gdk_event_get_time(event);
159 
160  ensure_touch_added(self, event_time, x, y, touch_id, device_id);
161 
162  GdkEventType touch_event_type = gdk_event_get_event_type(event);
163 
164  switch (touch_event_type) {
165  case GDK_TOUCH_BEGIN:
166  fl_engine_send_touch_down_event(engine, self->view_id,
167  event_time * kMicrosecondsPerMillisecond,
168  x, y, device_id);
169  break;
170  case GDK_TOUCH_UPDATE:
171  fl_engine_send_touch_move_event(engine, self->view_id,
172  event_time * kMicrosecondsPerMillisecond,
173  x, y, device_id);
174  break;
175  case GDK_TOUCH_END:
176  fl_engine_send_touch_up_event(engine, self->view_id,
177  event_time * kMicrosecondsPerMillisecond, x,
178  y, device_id);
179 
181  engine, self->view_id, event_time * kMicrosecondsPerMillisecond, x, y,
182  device_id);
183  release_number(self, id);
184  self->added_touch_devices =
185  g_list_remove(self->added_touch_devices, GINT_TO_POINTER(touch_id));
186  break;
187  default:
188  break;
189  }
190 }
_FlTouchManager::min_touch_device_id
guint min_touch_device_id
Definition: fl_touch_manager.cc:25
fl_engine_send_touch_move_event
void fl_engine_send_touch_move_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, int32_t device)
Definition: fl_engine.cc:1004
get_generated_id
static uint32_t get_generated_id(_FlTouchManager *self, uint32_t number)
Definition: fl_touch_manager.cc:93
fl_touch_manager_class_init
static void fl_touch_manager_class_init(FlTouchManagerClass *klass)
Definition: fl_touch_manager.cc:42
fl_touch_manager.h
kMaxTouchDeviceId
static const int kMaxTouchDeviceId
Definition: fl_touch_manager.cc:10
fl_engine_send_touch_remove_event
void fl_engine_send_touch_remove_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, int32_t device)
Definition: fl_engine.cc:1056
release_number
static void release_number(_FlTouchManager *self, uint32_t number)
Definition: fl_touch_manager.cc:121
fl_touch_manager_dispose
static void fl_touch_manager_dispose(GObject *object)
Definition: fl_touch_manager.cc:30
id
int64_t id
Definition: fl_pixel_buffer_texture.cc:28
_FlTouchManager::parent_instance
GObject parent_instance
Definition: fl_touch_manager.cc:13
_FlTouchManager::added_touch_devices
GList * added_touch_devices
Definition: fl_touch_manager.cc:20
fl_touch_manager_handle_touch_event
void fl_touch_manager_handle_touch_event(FlTouchManager *self, GdkEventTouch *touch_event, gint scale_factor)
Definition: fl_touch_manager.cc:131
fl_engine_private.h
kMinTouchDeviceId
static const int kMinTouchDeviceId
Definition: fl_touch_manager.cc:9
_FlTouchManager::view_id
FlutterViewId view_id
Definition: fl_touch_manager.cc:17
fl_touch_manager_new
FlTouchManager * fl_touch_manager_new(FlEngine *engine, FlutterViewId view_id)
Definition: fl_touch_manager.cc:48
G_DEFINE_TYPE
G_DEFINE_TYPE(FlTouchManager, fl_touch_manager, G_TYPE_OBJECT)
_FlTouchManager::engine
GWeakRef engine
Definition: fl_touch_manager.cc:15
fl_engine_send_touch_down_event
void fl_engine_send_touch_down_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, int32_t device)
Definition: fl_engine.cc:978
fl_touch_manager_init
static void fl_touch_manager_init(FlTouchManager *self)
Definition: fl_touch_manager.cc:46
_FlTouchManager
Definition: fl_touch_manager.cc:12
fl_engine_send_touch_add_event
void fl_engine_send_touch_add_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, int32_t device)
Definition: fl_engine.cc:1030
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_engine_send_touch_up_event
void fl_engine_send_touch_up_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, int32_t device)
Definition: fl_engine.cc:952
kMicrosecondsPerMillisecond
static constexpr int kMicrosecondsPerMillisecond
Definition: fl_touch_manager.cc:8
ensure_touch_added
static void ensure_touch_added(_FlTouchManager *self, guint event_time, gdouble x, gdouble y, int32_t touch_id, int32_t device_id)
Definition: fl_touch_manager.cc:66
_FlTouchManager::number_to_id
GHashTable * number_to_id
Definition: fl_touch_manager.cc:22