Flutter Linux Embedder
fl_keyboard_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 
7 #include <array>
8 #include <cinttypes>
9 #include <memory>
10 #include <string>
11 
17 
18 // Turn on this flag to print complete layout data when switching IMEs. The data
19 // is used in unit tests.
20 #define DEBUG_PRINT_LAYOUT
21 
22 static constexpr char kChannelName[] = "flutter/keyboard";
23 static constexpr char kGetKeyboardStateMethod[] = "getKeyboardState";
24 
25 /* Declarations of private classes */
26 
27 G_DECLARE_FINAL_TYPE(FlKeyboardPendingEvent,
28  fl_keyboard_pending_event,
29  FL,
30  KEYBOARD_PENDING_EVENT,
31  GObject);
32 
33 #define FL_TYPE_KEYBOARD_MANAGER_USER_DATA \
34  fl_keyboard_manager_user_data_get_type()
35 G_DECLARE_FINAL_TYPE(FlKeyboardManagerUserData,
36  fl_keyboard_manager_user_data,
37  FL,
38  KEYBOARD_MANAGER_USER_DATA,
39  GObject);
40 
41 /* End declarations */
42 
43 namespace {
44 
45 // The maxiumum keycode in a derived layout.
46 //
47 // Although X supports higher keycodes, Flutter only cares about standard keys,
48 // which are below this.
49 constexpr size_t kLayoutSize = 128;
50 // Describes the derived layout of a keyboard group.
51 //
52 // Maps from keycode to logical key. Value being 0 stands for empty.
53 typedef std::array<uint64_t, kLayoutSize> DerivedGroupLayout;
54 // Describes the derived layout of the entire keyboard.
55 //
56 // Maps from group ID to group layout.
57 typedef std::map<guint8, DerivedGroupLayout> DerivedLayout;
58 
59 // Context variables for the foreach call used to dispatch events to responders.
60 typedef struct {
62  uint64_t specified_logical_key;
63  FlKeyboardManagerUserData* user_data;
64 } DispatchToResponderLoopContext;
65 
66 bool is_eascii(uint16_t character) {
67  return character < 256;
68 }
69 
70 #ifdef DEBUG_PRINT_LAYOUT
71 // Prints layout entries that will be parsed by `MockLayoutData`.
72 void debug_format_layout_data(std::string& debug_layout_data,
73  uint16_t keycode,
74  uint16_t clue1,
75  uint16_t clue2) {
76  if (keycode % 4 == 0) {
77  debug_layout_data.append(" ");
78  }
79 
80  constexpr int kBufferSize = 30;
81  char buffer[kBufferSize];
82  buffer[0] = 0;
83  buffer[kBufferSize - 1] = 0;
84 
85  snprintf(buffer, kBufferSize, "0x%04x, 0x%04x, ", clue1, clue2);
86  debug_layout_data.append(buffer);
87 
88  if (keycode % 4 == 3) {
89  snprintf(buffer, kBufferSize, " // 0x%02x", keycode);
90  debug_layout_data.append(buffer);
91  }
92 }
93 #endif
94 
95 } // namespace
96 
98  const DerivedLayout& layout) {
99  guint8 group = event->group;
100  guint16 keycode = event->keycode;
101  if (keycode >= kLayoutSize) {
102  return 0;
103  }
104 
105  auto found_group_layout = layout.find(group);
106  if (found_group_layout != layout.end()) {
107  return found_group_layout->second[keycode];
108  }
109  return 0;
110 }
111 
112 /* Define FlKeyboardPendingEvent */
113 
114 /**
115  * FlKeyboardPendingEvent:
116  * A record for events that have been received by the manager, but
117  * dispatched to other objects, whose results have yet to return.
118  *
119  * This object is used by both the "pending_responds" list and the
120  * "pending_redispatches" list.
121  */
122 
125 
126  // The target event.
127  //
128  // This is freed by #FlKeyboardPendingEvent if not null.
129  std::unique_ptr<FlKeyEvent> event;
130 
131  // Self-incrementing ID attached to an event sent to the framework.
132  //
133  // Used to identify pending responds.
134  uint64_t sequence_id;
135  // The number of responders that haven't replied.
136  size_t unreplied;
137  // Whether any replied responders reported true (handled).
139 
140  // A value calculated out of critical event information that can be used
141  // to identify redispatched events.
142  uint64_t hash;
143 };
144 
145 G_DEFINE_TYPE(FlKeyboardPendingEvent, fl_keyboard_pending_event, G_TYPE_OBJECT)
146 
147 static void fl_keyboard_pending_event_dispose(GObject* object) {
148  // Redundant, but added so that we don't get a warning about unused function
149  // for FL_IS_KEYBOARD_PENDING_EVENT.
150  g_return_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(object));
151 
152  FlKeyboardPendingEvent* self = FL_KEYBOARD_PENDING_EVENT(object);
153  if (self->event != nullptr) {
154  fl_key_event_dispose(self->event.release());
155  }
156  G_OBJECT_CLASS(fl_keyboard_pending_event_parent_class)->dispose(object);
157 }
158 
160  FlKeyboardPendingEventClass* klass) {
161  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_pending_event_dispose;
162 }
163 
164 static void fl_keyboard_pending_event_init(FlKeyboardPendingEvent* self) {}
165 
166 // Calculates a unique ID for a given FlKeyEvent object to use for
167 // identification of responses from the framework.
169  // Combine the event timestamp, the type of event, and the hardware keycode
170  // (scan code) of the event to come up with a unique id for this event that
171  // can be derived solely from the event data itself, so that we can identify
172  // whether or not we have seen this event already.
173  guint64 type =
174  static_cast<uint64_t>(event->is_press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
175  guint64 keycode = static_cast<uint64_t>(event->keycode);
176  return (event->time & 0xffffffff) | ((type & 0xffff) << 32) |
177  ((keycode & 0xffff) << 48);
178 }
179 
180 // Create a new FlKeyboardPendingEvent by providing the target event,
181 // the sequence ID, and the number of responders that will reply.
182 //
183 // This will acquire the ownership of the event.
184 static FlKeyboardPendingEvent* fl_keyboard_pending_event_new(
185  std::unique_ptr<FlKeyEvent> event,
186  uint64_t sequence_id,
187  size_t to_reply) {
188  FlKeyboardPendingEvent* self = FL_KEYBOARD_PENDING_EVENT(
189  g_object_new(fl_keyboard_pending_event_get_type(), nullptr));
190 
191  self->event = std::move(event);
192  self->sequence_id = sequence_id;
193  self->unreplied = to_reply;
194  self->any_handled = false;
195  self->hash = fl_keyboard_manager_get_event_hash(self->event.get());
196  return self;
197 }
198 
199 /* Define FlKeyboardManagerUserData */
200 
201 /**
202  * FlKeyboardManagerUserData:
203  * The user_data used when #FlKeyboardManager sends event to
204  * responders.
205  */
206 
209 
210  // A weak reference to the owner manager.
212  uint64_t sequence_id;
213 };
214 
215 G_DEFINE_TYPE(FlKeyboardManagerUserData,
216  fl_keyboard_manager_user_data,
217  G_TYPE_OBJECT)
218 
219 static void fl_keyboard_manager_user_data_dispose(GObject* object) {
220  g_return_if_fail(FL_IS_KEYBOARD_MANAGER_USER_DATA(object));
221  FlKeyboardManagerUserData* self = FL_KEYBOARD_MANAGER_USER_DATA(object);
222  if (self->manager != nullptr) {
223  g_object_remove_weak_pointer(G_OBJECT(self->manager),
224  reinterpret_cast<gpointer*>(&(self->manager)));
225  self->manager = nullptr;
226  }
227 }
228 
230  FlKeyboardManagerUserDataClass* klass) {
231  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_user_data_dispose;
232 }
233 
235  FlKeyboardManagerUserData* self) {}
236 
237 // Creates a new FlKeyboardManagerUserData private class with all information.
238 static FlKeyboardManagerUserData* fl_keyboard_manager_user_data_new(
239  FlKeyboardManager* manager,
240  uint64_t sequence_id) {
241  FlKeyboardManagerUserData* self = FL_KEYBOARD_MANAGER_USER_DATA(
242  g_object_new(fl_keyboard_manager_user_data_get_type(), nullptr));
243 
244  self->manager = manager;
245  // Add a weak pointer so we can know if the key event responder disappeared
246  // while the framework was responding.
247  g_object_add_weak_pointer(G_OBJECT(manager),
248  reinterpret_cast<gpointer*>(&(self->manager)));
249  self->sequence_id = sequence_id;
250  return self;
251 }
252 
253 /* Define FlKeyboardManager */
254 
257 
258  FlKeyboardViewDelegate* view_delegate;
259 
260  // An array of #FlKeyResponder. Elements are added with
261  // #fl_keyboard_manager_add_responder immediately after initialization and are
262  // automatically released on dispose.
263  GPtrArray* responder_list;
264 
265  // An array of #FlKeyboardPendingEvent.
266  //
267  // Its elements are *not* unreferenced when removed. When FlKeyboardManager is
268  // disposed, this array will be set with a free_func so that the elements are
269  // unreferenced when removed.
270  GPtrArray* pending_responds;
271 
272  // An array of #FlKeyboardPendingEvent.
273  //
274  // Its elements are unreferenced when removed.
276 
277  // The last sequence ID used. Increased by 1 by every use.
279 
280  // Record the derived layout.
281  //
282  // It is cleared when the platform reports a layout switch. Each entry,
283  // which corresponds to a group, is only initialized on the arrival of the
284  // first event for that group that has a goal keycode.
285  std::unique_ptr<DerivedLayout> derived_layout;
286  // A static map from keycodes to all layout goals.
287  //
288  // It is set up when the manager is initialized and is not changed ever after.
289  std::unique_ptr<std::map<uint16_t, const LayoutGoal*>> keycode_to_goals;
290  // A static map from logical keys to all mandatory layout goals.
291  //
292  // It is set up when the manager is initialized and is not changed ever after.
293  std::unique_ptr<std::map<uint64_t, const LayoutGoal*>>
295 
296  // The channel used by the framework to query the keyboard pressed state.
297  FlMethodChannel* channel;
298 };
299 
300 G_DEFINE_TYPE(FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT);
301 
302 static void fl_keyboard_manager_dispose(GObject* object);
303 
304 static void fl_keyboard_manager_class_init(FlKeyboardManagerClass* klass) {
305  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_dispose;
306 }
307 
309  self->derived_layout = std::make_unique<DerivedLayout>();
310 
311  self->keycode_to_goals =
312  std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
313  self->logical_to_mandatory_goals =
314  std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
315  for (const LayoutGoal& goal : layout_goals) {
316  (*self->keycode_to_goals)[goal.keycode] = &goal;
317  if (goal.mandatory) {
318  (*self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
319  }
320  }
321 
322  self->responder_list = g_ptr_array_new_with_free_func(g_object_unref);
323 
324  self->pending_responds = g_ptr_array_new();
325  self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
326 
327  self->last_sequence_id = 1;
328 }
329 
330 static void fl_keyboard_manager_dispose(GObject* object) {
331  FlKeyboardManager* self = FL_KEYBOARD_MANAGER(object);
332 
333  if (self->view_delegate != nullptr) {
335  nullptr);
336  g_object_remove_weak_pointer(
337  G_OBJECT(self->view_delegate),
338  reinterpret_cast<gpointer*>(&(self->view_delegate)));
339  self->view_delegate = nullptr;
340  }
341 
342  self->derived_layout.reset();
343  self->keycode_to_goals.reset();
344  self->logical_to_mandatory_goals.reset();
345 
346  g_ptr_array_free(self->responder_list, TRUE);
347  g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
348  g_ptr_array_free(self->pending_responds, TRUE);
349  g_ptr_array_free(self->pending_redispatches, TRUE);
350 
351  G_OBJECT_CLASS(fl_keyboard_manager_parent_class)->dispose(object);
352 }
353 
354 /* Implement FlKeyboardManager */
355 
356 // This is an exact copy of g_ptr_array_find_with_equal_func. Somehow CI
357 // reports that can not find symbol g_ptr_array_find_with_equal_func, despite
358 // the fact that it runs well locally.
359 static gboolean g_ptr_array_find_with_equal_func1(GPtrArray* haystack,
360  gconstpointer needle,
361  GEqualFunc equal_func,
362  guint* index_) {
363  guint i;
364  g_return_val_if_fail(haystack != NULL, FALSE);
365  if (equal_func == NULL) {
366  equal_func = g_direct_equal;
367  }
368  for (i = 0; i < haystack->len; i++) {
369  if (equal_func(g_ptr_array_index(haystack, i), needle)) {
370  if (index_ != NULL) {
371  *index_ = i;
372  }
373  return TRUE;
374  }
375  }
376 
377  return FALSE;
378 }
379 
380 // Compare a #FlKeyboardPendingEvent with the given sequence_id. The needle
381 // should be a pointer to uint64_t sequence_id.
383  gconstpointer pending,
384  gconstpointer needle_sequence_id) {
385  uint64_t sequence_id = *reinterpret_cast<const uint64_t*>(needle_sequence_id);
386  return static_cast<const FlKeyboardPendingEvent*>(pending)->sequence_id ==
387  sequence_id;
388 }
389 
390 // Compare a #FlKeyboardPendingEvent with the given hash. The #needle should be
391 // a pointer to uint64_t hash.
392 static gboolean compare_pending_by_hash(gconstpointer pending,
393  gconstpointer needle_hash) {
394  uint64_t hash = *reinterpret_cast<const uint64_t*>(needle_hash);
395  return static_cast<const FlKeyboardPendingEvent*>(pending)->hash == hash;
396 }
397 
398 // Try to remove a pending event from `pending_redispatches` with the target
399 // hash.
400 //
401 // Returns true if the event is found and removed.
403  uint64_t hash) {
404  guint result_index;
405  gboolean found = g_ptr_array_find_with_equal_func1(
406  self->pending_redispatches, static_cast<const uint64_t*>(&hash),
407  compare_pending_by_hash, &result_index);
408  if (found) {
409  // The removed object is freed due to `pending_redispatches`'s free_func.
410  g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
411  return TRUE;
412  } else {
413  return FALSE;
414  }
415 }
416 
417 // The callback used by a responder after the event was dispatched.
418 static void responder_handle_event_callback(bool handled,
419  gpointer user_data_ptr) {
420  g_return_if_fail(FL_IS_KEYBOARD_MANAGER_USER_DATA(user_data_ptr));
421  FlKeyboardManagerUserData* user_data =
422  FL_KEYBOARD_MANAGER_USER_DATA(user_data_ptr);
423  FlKeyboardManager* self = user_data->manager;
424  g_return_if_fail(self->view_delegate != nullptr);
425 
426  guint result_index = -1;
427  gboolean found = g_ptr_array_find_with_equal_func1(
428  self->pending_responds, &user_data->sequence_id,
429  compare_pending_by_sequence_id, &result_index);
430  g_return_if_fail(found);
431  FlKeyboardPendingEvent* pending = FL_KEYBOARD_PENDING_EVENT(
432  g_ptr_array_index(self->pending_responds, result_index));
433  g_return_if_fail(pending != nullptr);
434  g_return_if_fail(pending->unreplied > 0);
435  pending->unreplied -= 1;
436  pending->any_handled = pending->any_handled || handled;
437  // All responders have replied.
438  if (pending->unreplied == 0) {
439  g_object_unref(user_data_ptr);
440  gpointer removed =
441  g_ptr_array_remove_index_fast(self->pending_responds, result_index);
442  g_return_if_fail(removed == pending);
443  bool should_redispatch = !pending->any_handled &&
445  self->view_delegate, pending->event.get());
446  if (should_redispatch) {
447  g_ptr_array_add(self->pending_redispatches, pending);
448  fl_keyboard_view_delegate_redispatch_event(self->view_delegate,
449  std::move(pending->event));
450  } else {
451  g_object_unref(pending);
452  }
453  }
454 }
455 
456 static uint16_t convert_key_to_char(FlKeyboardViewDelegate* view_delegate,
457  guint keycode,
458  gint group,
459  gint level) {
460  GdkKeymapKey key = {keycode, group, level};
461  constexpr int kBmpMax = 0xD7FF;
462  guint origin = fl_keyboard_view_delegate_lookup_key(view_delegate, &key);
463  return origin < kBmpMax ? origin : 0xFFFF;
464 }
465 
466 // Make sure that Flutter has derived the layout for the group of the event,
467 // if the event contains a goal keycode.
469  guint8 group = event->group;
470  if (self->derived_layout->find(group) != self->derived_layout->end()) {
471  return;
472  }
473  if (self->keycode_to_goals->find(event->keycode) ==
474  self->keycode_to_goals->end()) {
475  return;
476  }
477 
478  DerivedGroupLayout& layout = (*self->derived_layout)[group];
479 
480  // Clone all mandatory goals. Each goal is removed from this cloned map when
481  // fulfilled, and the remaining ones will be assigned to a default position.
482  std::map<uint64_t, const LayoutGoal*> remaining_mandatory_goals =
483  *self->logical_to_mandatory_goals;
484 
485 #ifdef DEBUG_PRINT_LAYOUT
486  std::string debug_layout_data;
487  for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
488  std::vector<uint16_t> this_key_clues = {
489  convert_key_to_char(self->view_delegate, keycode, group, 0),
490  convert_key_to_char(self->view_delegate, keycode, group, 1), // Shift
491  };
492  debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
493  this_key_clues[1]);
494  }
495 #endif
496 
497  // It's important to only traverse layout goals instead of all keycodes.
498  // Some key codes outside of the standard keyboard also gives alpha-numeric
499  // letters, and will therefore take over mandatory goals from standard
500  // keyboard keys if they come first. Example: French keyboard digit 1.
501  for (const LayoutGoal& keycode_goal : layout_goals) {
502  uint16_t keycode = keycode_goal.keycode;
503  std::vector<uint16_t> this_key_clues = {
504  convert_key_to_char(self->view_delegate, keycode, group, 0),
505  convert_key_to_char(self->view_delegate, keycode, group, 1), // Shift
506  };
507 
508  // The logical key should be the first available clue from below:
509  //
510  // - Mandatory goal, if it matches any clue. This ensures that all alnum
511  // keys can be found somewhere.
512  // - US layout, if neither clue of the key is EASCII. This ensures that
513  // there are no non-latin logical keys.
514  // - A value derived on the fly from keycode & keyval.
515  for (uint16_t clue : this_key_clues) {
516  auto matching_goal = remaining_mandatory_goals.find(clue);
517  if (matching_goal != remaining_mandatory_goals.end()) {
518  // Found a key that produces a mandatory char. Use it.
519  g_return_if_fail(layout[keycode] == 0);
520  layout[keycode] = clue;
521  remaining_mandatory_goals.erase(matching_goal);
522  break;
523  }
524  }
525  bool has_any_eascii =
526  is_eascii(this_key_clues[0]) || is_eascii(this_key_clues[1]);
527  // See if any produced char meets the requirement as a logical key.
528  if (layout[keycode] == 0 && !has_any_eascii) {
529  auto found_us_layout = self->keycode_to_goals->find(keycode);
530  if (found_us_layout != self->keycode_to_goals->end()) {
531  layout[keycode] = found_us_layout->second->logical_key;
532  }
533  }
534  }
535 
536  // Ensure all mandatory goals are assigned.
537  for (const auto mandatory_goal_iter : remaining_mandatory_goals) {
538  const LayoutGoal* goal = mandatory_goal_iter.second;
539  layout[goal->keycode] = goal->logical_key;
540  }
541 }
542 
543 // Returns the keyboard pressed state.
544 FlMethodResponse* get_keyboard_state(FlKeyboardManager* self) {
545  g_autoptr(FlValue) result = fl_value_new_map();
546 
547  GHashTable* pressing_records =
549 
550  g_hash_table_foreach(
551  pressing_records,
552  [](gpointer key, gpointer value, gpointer user_data) {
553  int64_t physical_key = reinterpret_cast<int64_t>(key);
554  int64_t logical_key = reinterpret_cast<int64_t>(value);
555  FlValue* fl_value_map = reinterpret_cast<FlValue*>(user_data);
556 
557  fl_value_set_take(fl_value_map, fl_value_new_int(physical_key),
558  fl_value_new_int(logical_key));
559  },
560  result);
561  return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
562 }
563 
564 // Called when a method call on flutter/keyboard is received from Flutter.
565 static void method_call_handler(FlMethodChannel* channel,
566  FlMethodCall* method_call,
567  gpointer user_data) {
568  FlKeyboardManager* self = FL_KEYBOARD_MANAGER(user_data);
569 
570  const gchar* method = fl_method_call_get_name(method_call);
571 
572  g_autoptr(FlMethodResponse) response = nullptr;
573  if (strcmp(method, kGetKeyboardStateMethod) == 0) {
574  response = get_keyboard_state(self);
575  } else {
576  response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
577  }
578 
579  g_autoptr(GError) error = nullptr;
580  if (!fl_method_call_respond(method_call, response, &error)) {
581  g_warning("Failed to send method call response: %s", error->message);
582  }
583 }
584 
586  FlBinaryMessenger* messenger,
587  FlKeyboardViewDelegate* view_delegate) {
588  g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(view_delegate), nullptr);
589 
590  FlKeyboardManager* self = FL_KEYBOARD_MANAGER(
591  g_object_new(fl_keyboard_manager_get_type(), nullptr));
592 
593  self->view_delegate = view_delegate;
595  G_OBJECT(view_delegate),
596  reinterpret_cast<gpointer*>(&(self->view_delegate)));
597 
598  // The embedder responder must be added before the channel responder.
599  g_ptr_array_add(
600  self->responder_list,
601  FL_KEY_RESPONDER(fl_key_embedder_responder_new(
602  [](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
603  void* callback_user_data, void* send_key_event_user_data) {
604  FlKeyboardManager* self =
605  FL_KEYBOARD_MANAGER(send_key_event_user_data);
606  g_return_if_fail(self->view_delegate != nullptr);
608  self->view_delegate, event, callback, callback_user_data);
609  },
610  self)));
611  g_ptr_array_add(self->responder_list,
612  FL_KEY_RESPONDER(fl_key_channel_responder_new(
613  fl_keyboard_view_delegate_get_messenger(view_delegate))));
614 
616  self->view_delegate, [self]() { self->derived_layout->clear(); });
617 
618  // Setup the flutter/keyboard channel.
619  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
620  self->channel =
621  fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
623  self, nullptr);
624  return self;
625 }
626 
627 // The loop body to dispatch an event to a responder.
628 static void dispatch_to_responder(gpointer responder_data,
629  gpointer foreach_data_ptr) {
630  DispatchToResponderLoopContext* context =
631  reinterpret_cast<DispatchToResponderLoopContext*>(foreach_data_ptr);
632  FlKeyResponder* responder = FL_KEY_RESPONDER(responder_data);
634  responder, context->event, responder_handle_event_callback,
635  context->user_data, context->specified_logical_key);
636 }
637 
639  FlKeyEvent* event) {
640  g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
641  g_return_val_if_fail(event != nullptr, FALSE);
642  g_return_val_if_fail(self->view_delegate != nullptr, FALSE);
643 
644  guarantee_layout(self, event);
645 
646  uint64_t incoming_hash = fl_keyboard_manager_get_event_hash(event);
647  if (fl_keyboard_manager_remove_redispatched(self, incoming_hash)) {
648  return FALSE;
649  }
650 
651  FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(
652  std::unique_ptr<FlKeyEvent>(event), ++self->last_sequence_id,
653  self->responder_list->len);
654 
655  g_ptr_array_add(self->pending_responds, pending);
656  FlKeyboardManagerUserData* user_data =
657  fl_keyboard_manager_user_data_new(self, pending->sequence_id);
658  DispatchToResponderLoopContext data{
659  .event = event,
660  .specified_logical_key =
661  get_logical_key_from_layout(event, *self->derived_layout),
662  .user_data = user_data,
663  };
664  g_ptr_array_foreach(self->responder_list, dispatch_to_responder, &data);
665 
666  return TRUE;
667 }
668 
670  g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
671  return self->pending_responds->len == 0 &&
672  self->pending_redispatches->len == 0;
673 }
674 
676  guint state,
677  double event_time) {
678  g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
679 
680  // The embedder responder is the first element in
681  // FlKeyboardManager.responder_list.
682  FlKeyEmbedderResponder* responder =
683  FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(self->responder_list, 0));
685  event_time);
686 }
687 
689  g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), nullptr);
690 
691  // The embedder responder is the first element in
692  // FlKeyboardManager.responder_list.
693  FlKeyEmbedderResponder* responder =
694  FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(self->responder_list, 0));
696 }
_FlKeyEvent::time
guint32 time
Definition: fl_key_event.h:24
_FlKeyboardPendingEvent::any_handled
bool any_handled
Definition: fl_keyboard_manager.cc:138
if
if(end==-1)
Definition: fl_accessible_text_field.cc:42
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
_FlKeyboardManager::channel
FlMethodChannel * channel
Definition: fl_keyboard_manager.cc:297
fl_keyboard_pending_event_class_init
static void fl_keyboard_pending_event_class_init(FlKeyboardPendingEventClass *klass)
Definition: fl_keyboard_manager.cc:159
layout_goals
const std::vector< LayoutGoal > layout_goals
Definition: key_mapping.g.cc:462
_FlKeyboardManager::pending_redispatches
GPtrArray * pending_redispatches
Definition: fl_keyboard_manager.cc:275
guarantee_layout
static void guarantee_layout(FlKeyboardManager *self, FlKeyEvent *event)
Definition: fl_keyboard_manager.cc:468
fl_method_channel_new
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
Definition: fl_method_channel.cc:112
compare_pending_by_sequence_id
static gboolean compare_pending_by_sequence_id(gconstpointer pending, gconstpointer needle_sequence_id)
Definition: fl_keyboard_manager.cc:382
fl_keyboard_pending_event_init
static void fl_keyboard_pending_event_init(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_manager.cc:164
fl_key_embedder_responder_get_pressed_state
GHashTable * fl_key_embedder_responder_get_pressed_state(FlKeyEmbedderResponder *self)
Definition: fl_key_embedder_responder.cc:895
fl_keyboard_pending_event_new
static FlKeyboardPendingEvent * fl_keyboard_pending_event_new(std::unique_ptr< FlKeyEvent > event, uint64_t sequence_id, size_t to_reply)
Definition: fl_keyboard_manager.cc:184
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlKeyboardPendingEvent, fl_keyboard_pending_event, FL, KEYBOARD_PENDING_EVENT, GObject)
type
uint8_t type
Definition: fl_standard_message_codec_test.cc:1115
fl_keyboard_view_delegate_subscribe_to_layout_change
void fl_keyboard_view_delegate_subscribe_to_layout_change(FlKeyboardViewDelegate *self, KeyboardLayoutNotifier notifier)
Definition: fl_keyboard_view_delegate.cc:52
LayoutGoal
Definition: key_mapping.h:40
_FlKeyboardManagerUserData::parent_instance
GObject parent_instance
Definition: fl_keyboard_manager.cc:208
fl_method_not_implemented_response_new
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
Definition: fl_method_response.cc:179
fl_standard_method_codec_new
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
Definition: fl_standard_method_codec.cc:291
_FlKeyboardManager::pending_responds
GPtrArray * pending_responds
Definition: fl_keyboard_manager.cc:270
fl_keyboard_manager.h
fl_key_embedder_responder.h
fl_method_channel.h
kGetKeyboardStateMethod
static constexpr char kGetKeyboardStateMethod[]
Definition: fl_keyboard_manager.cc:23
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
LayoutGoal::keycode
uint16_t keycode
Definition: key_mapping.h:42
get_keyboard_state
FlMethodResponse * get_keyboard_state(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:544
_FlKeyboardManager::last_sequence_id
uint64_t last_sequence_id
Definition: fl_keyboard_manager.cc:278
_FlKeyboardPendingEvent::hash
uint64_t hash
Definition: fl_keyboard_manager.cc:142
fl_keyboard_manager_dispose
static void fl_keyboard_manager_dispose(GObject *object)
Definition: fl_keyboard_manager.cc:330
responder_handle_event_callback
static void responder_handle_event_callback(bool handled, gpointer user_data_ptr)
Definition: fl_keyboard_manager.cc:418
LayoutGoal::logical_key
uint64_t logical_key
Definition: key_mapping.h:45
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
fl_value_set_take
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
Definition: fl_value.cc:618
fl_keyboard_manager_remove_redispatched
static bool fl_keyboard_manager_remove_redispatched(FlKeyboardManager *self, uint64_t hash)
Definition: fl_keyboard_manager.cc:402
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
fl_keyboard_manager_is_state_clear
gboolean fl_keyboard_manager_is_state_clear(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:669
_FlKeyboardManager::responder_list
GPtrArray * responder_list
Definition: fl_keyboard_manager.cc:263
_FlKeyboardManagerUserData
Definition: fl_keyboard_manager.cc:207
fl_method_success_response_new
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
Definition: fl_method_response.cc:126
_FlKeyEvent
Definition: fl_key_event.h:22
G_DEFINE_TYPE
G_DEFINE_TYPE(FlKeyboardManagerUserData, fl_keyboard_manager_user_data, G_TYPE_OBJECT) static void fl_keyboard_manager_user_data_dispose(GObject *object)
Definition: fl_keyboard_manager.cc:215
state
AtkStateType state
Definition: fl_accessible_node.cc:10
fl_key_channel_responder_new
FlKeyChannelResponder * fl_key_channel_responder_new(FlBinaryMessenger *messenger, FlKeyChannelResponderMock *mock)
Definition: fl_key_channel_responder.cc:186
_FlKeyboardManager::parent_instance
GObject parent_instance
Definition: fl_keyboard_manager.cc:256
_FlKeyboardPendingEvent::sequence_id
uint64_t sequence_id
Definition: fl_keyboard_manager.cc:134
_FlKeyboardManagerUserData::sequence_id
uint64_t sequence_id
Definition: fl_keyboard_manager.cc:212
fl_keyboard_view_delegate_lookup_key
guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate *self, const GdkKeymapKey *key)
Definition: fl_keyboard_view_delegate.cc:61
fl_keyboard_manager_handle_event
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager *self, FlKeyEvent *event)
Definition: fl_keyboard_manager.cc:638
dispatch_to_responder
static void dispatch_to_responder(gpointer responder_data, gpointer foreach_data_ptr)
Definition: fl_keyboard_manager.cc:628
_FlKeyboardPendingEvent::parent_instance
GObject parent_instance
Definition: fl_keyboard_manager.cc:124
fl_key_embedder_responder_new
FlKeyEmbedderResponder * fl_key_embedder_responder_new(EmbedderSendKeyEvent send_key_event, void *send_key_event_user_data)
Definition: fl_key_embedder_responder.cc:263
fl_keyboard_manager_get_event_hash
static uint64_t fl_keyboard_manager_get_event_hash(FlKeyEvent *event)
Definition: fl_keyboard_manager.cc:168
fl_method_call_respond
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
Definition: fl_method_call.cc:77
get_logical_key_from_layout
static uint64_t get_logical_key_from_layout(const FlKeyEvent *event, const DerivedLayout &layout)
Definition: fl_keyboard_manager.cc:97
fl_keyboard_view_delegate_redispatch_event
void fl_keyboard_view_delegate_redispatch_event(FlKeyboardViewDelegate *self, std::unique_ptr< FlKeyEvent > event)
Definition: fl_keyboard_view_delegate.cc:42
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
fl_keyboard_manager_init
static void fl_keyboard_manager_init(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:308
_FlKeyEvent::keycode
guint16 keycode
Definition: fl_key_event.h:28
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
fl_keyboard_manager_user_data_init
static void fl_keyboard_manager_user_data_init(FlKeyboardManagerUserData *self)
Definition: fl_keyboard_manager.cc:234
fl_key_responder_handle_event
void fl_key_responder_handle_event(FlKeyResponder *self, FlKeyEvent *event, FlKeyResponderAsyncCallback callback, gpointer user_data, uint64_t specified_logical_key)
Definition: fl_key_responder.cc:11
convert_key_to_char
static uint16_t convert_key_to_char(FlKeyboardViewDelegate *view_delegate, guint keycode, gint group, gint level)
Definition: fl_keyboard_manager.cc:456
fl_method_call_get_name
const G_MODULE_EXPORT gchar * fl_method_call_get_name(FlMethodCall *self)
Definition: fl_method_call.cc:67
key_mapping.h
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_keyboard_pending_event_dispose
static void fl_keyboard_pending_event_dispose(GObject *object)
Definition: fl_keyboard_manager.cc:147
_FlKeyboardManager::derived_layout
std::unique_ptr< DerivedLayout > derived_layout
Definition: fl_keyboard_manager.cc:285
g_object_add_weak_pointer
g_object_add_weak_pointer(G_OBJECT(self), reinterpret_cast< gpointer * >(&self->engine))
g_ptr_array_find_with_equal_func1
static gboolean g_ptr_array_find_with_equal_func1(GPtrArray *haystack, gconstpointer needle, GEqualFunc equal_func, guint *index_)
Definition: fl_keyboard_manager.cc:359
fl_keyboard_view_delegate_text_filter_key_press
gboolean fl_keyboard_view_delegate_text_filter_key_press(FlKeyboardViewDelegate *self, FlKeyEvent *event)
Definition: fl_keyboard_view_delegate.cc:25
fl_key_embedder_responder_sync_modifiers_if_needed
void fl_key_embedder_responder_sync_modifiers_if_needed(FlKeyEmbedderResponder *responder, guint state, double event_time)
Definition: fl_key_embedder_responder.cc:878
kChannelName
static constexpr char kChannelName[]
Definition: fl_keyboard_manager.cc:22
FL
FL
Definition: fl_binary_messenger.cc:27
_FlKeyboardPendingEvent::event
std::unique_ptr< FlKeyEvent > event
Definition: fl_keyboard_manager.cc:129
fl_standard_method_codec.h
fl_keyboard_manager_new
FlKeyboardManager * fl_keyboard_manager_new(FlBinaryMessenger *messenger, FlKeyboardViewDelegate *view_delegate)
Definition: fl_keyboard_manager.cc:585
fl_key_event_dispose
void fl_key_event_dispose(FlKeyEvent *event)
Definition: fl_key_event.cc:32
fl_keyboard_manager_user_data_class_init
static void fl_keyboard_manager_user_data_class_init(FlKeyboardManagerUserDataClass *klass)
Definition: fl_keyboard_manager.cc:229
fl_keyboard_manager_sync_modifier_if_needed
void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager *self, guint state, double event_time)
Definition: fl_keyboard_manager.cc:675
fl_keyboard_manager_class_init
static void fl_keyboard_manager_class_init(FlKeyboardManagerClass *klass)
Definition: fl_keyboard_manager.cc:304
fl_method_channel_set_method_call_handler
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
Definition: fl_method_channel.cc:134
fl_keyboard_manager_get_pressed_state
GHashTable * fl_keyboard_manager_get_pressed_state(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:688
_FlKeyboardManager::view_delegate
FlKeyboardViewDelegate * view_delegate
Definition: fl_keyboard_manager.cc:258
result
GAsyncResult * result
Definition: fl_text_input_plugin.cc:106
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
_FlKeyboardManagerUserData::manager
FlKeyboardManager * manager
Definition: fl_keyboard_manager.cc:211
fl_keyboard_manager_user_data_new
static FlKeyboardManagerUserData * fl_keyboard_manager_user_data_new(FlKeyboardManager *manager, uint64_t sequence_id)
Definition: fl_keyboard_manager.cc:238
fl_keyboard_view_delegate_get_messenger
FlBinaryMessenger * fl_keyboard_view_delegate_get_messenger(FlKeyboardViewDelegate *self)
Definition: fl_keyboard_view_delegate.cc:35
buffer
static const uint8_t buffer[]
Definition: fl_pixel_buffer_texture_test.cc:44
specified_logical_key
FlKeyEvent uint64_t specified_logical_key
Definition: fl_key_channel_responder.cc:119
_FlKeyboardPendingEvent
Definition: fl_keyboard_manager.cc:123
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
fl_key_channel_responder.h
_FlKeyboardManager
Definition: fl_keyboard_manager.cc:255
_FlKeyboardManager::keycode_to_goals
std::unique_ptr< std::map< uint16_t, const LayoutGoal * > > keycode_to_goals
Definition: fl_keyboard_manager.cc:289
method_call_handler
static void method_call_handler(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
Definition: fl_keyboard_manager.cc:565
fl_keyboard_view_delegate_send_key_event
void fl_keyboard_view_delegate_send_key_event(FlKeyboardViewDelegate *self, const FlutterKeyEvent *event, FlutterKeyEventCallback callback, void *user_data)
Definition: fl_keyboard_view_delegate.cc:14
fl_keyboard_view_delegate_get_keyboard_state
GHashTable * fl_keyboard_view_delegate_get_keyboard_state(FlKeyboardViewDelegate *self)
Definition: fl_keyboard_view_delegate.cc:68
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
compare_pending_by_hash
static gboolean compare_pending_by_hash(gconstpointer pending, gconstpointer needle_hash)
Definition: fl_keyboard_manager.cc:392
_FlKeyboardManager::logical_to_mandatory_goals
std::unique_ptr< std::map< uint64_t, const LayoutGoal * > > logical_to_mandatory_goals
Definition: fl_keyboard_manager.cc:294
_FlKeyboardPendingEvent::unreplied
size_t unreplied
Definition: fl_keyboard_manager.cc:136
FlKeyboardManager
typedefG_BEGIN_DECLS struct _FlKeyboardManager FlKeyboardManager
Definition: fl_key_responder.h:17