Flutter Linux Embedder
fl_keyboard_handler.cc File Reference

Go to the source code of this file.

Classes

struct  _FlKeyboardHandlerUserData
 
struct  _FlKeyboardHandler
 

Macros

#define DEBUG_PRINT_LAYOUT
 
#define FL_TYPE_KEYBOARD_HANDLER_USER_DATA   fl_keyboard_handler_user_data_get_type()
 

Functions

 G_DECLARE_FINAL_TYPE (FlKeyboardHandlerUserData, fl_keyboard_handler_user_data, FL, KEYBOARD_HANDLER_USER_DATA, GObject)
 
static uint64_t get_logical_key_from_layout (FlKeyEvent *event, const DerivedLayout &layout)
 
 G_DEFINE_TYPE (FlKeyboardHandlerUserData, fl_keyboard_handler_user_data, G_TYPE_OBJECT) static void fl_keyboard_handler_user_data_dispose(GObject *object)
 
static void fl_keyboard_handler_user_data_class_init (FlKeyboardHandlerUserDataClass *klass)
 
static void fl_keyboard_handler_user_data_init (FlKeyboardHandlerUserData *self)
 
static FlKeyboardHandlerUserData * fl_keyboard_handler_user_data_new (FlKeyboardHandler *handler, uint64_t sequence_id)
 
 G_DEFINE_TYPE (FlKeyboardHandler, fl_keyboard_handler, G_TYPE_OBJECT)
 
static gboolean g_ptr_array_find_with_equal_func1 (GPtrArray *haystack, gconstpointer needle, GEqualFunc equal_func, guint *index_)
 
static gboolean compare_pending_by_sequence_id (gconstpointer a, gconstpointer b)
 
static gboolean compare_pending_by_hash (gconstpointer a, gconstpointer b)
 
static bool fl_keyboard_handler_remove_redispatched (FlKeyboardHandler *self, uint64_t hash)
 
static void responder_handle_event_callback (bool handled, gpointer user_data_ptr)
 
static uint16_t convert_key_to_char (FlKeyboardViewDelegate *view_delegate, guint keycode, gint group, gint level)
 
static void guarantee_layout (FlKeyboardHandler *self, FlKeyEvent *event)
 
static FlMethodResponse * get_keyboard_state (FlKeyboardHandler *self)
 
static void method_call_handler (FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
 
static void dispatch_to_responder (gpointer responder_data, gpointer foreach_data_ptr)
 
static void fl_keyboard_handler_dispose (GObject *object)
 
static void fl_keyboard_handler_class_init (FlKeyboardHandlerClass *klass)
 
static void fl_keyboard_handler_init (FlKeyboardHandler *self)
 
FlKeyboardHandler * fl_keyboard_handler_new (FlBinaryMessenger *messenger, FlKeyboardViewDelegate *view_delegate)
 
gboolean fl_keyboard_handler_handle_event (FlKeyboardHandler *self, FlKeyEvent *event)
 
gboolean fl_keyboard_handler_is_state_clear (FlKeyboardHandler *self)
 
void fl_keyboard_handler_sync_modifier_if_needed (FlKeyboardHandler *self, guint state, double event_time)
 
GHashTable * fl_keyboard_handler_get_pressed_state (FlKeyboardHandler *self)
 

Variables

static constexpr char kChannelName [] = "flutter/keyboard"
 
static constexpr char kGetKeyboardStateMethod [] = "getKeyboardState"
 

Macro Definition Documentation

◆ DEBUG_PRINT_LAYOUT

#define DEBUG_PRINT_LAYOUT

Definition at line 21 of file fl_keyboard_handler.cc.

◆ FL_TYPE_KEYBOARD_HANDLER_USER_DATA

#define FL_TYPE_KEYBOARD_HANDLER_USER_DATA   fl_keyboard_handler_user_data_get_type()

Definition at line 28 of file fl_keyboard_handler.cc.

Function Documentation

◆ compare_pending_by_hash()

static gboolean compare_pending_by_hash ( gconstpointer  a,
gconstpointer  b 
)
static

Definition at line 244 of file fl_keyboard_handler.cc.

244  {
245  FlKeyboardPendingEvent* pending =
246  FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
247  uint64_t hash = *reinterpret_cast<const uint64_t*>(b);
248  return fl_keyboard_pending_event_get_hash(pending) == hash;
249 }

References fl_keyboard_pending_event_get_hash().

Referenced by fl_keyboard_handler_remove_redispatched().

◆ compare_pending_by_sequence_id()

static gboolean compare_pending_by_sequence_id ( gconstpointer  a,
gconstpointer  b 
)
static

Definition at line 235 of file fl_keyboard_handler.cc.

236  {
237  FlKeyboardPendingEvent* pending =
238  FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
239  uint64_t sequence_id = *reinterpret_cast<const uint64_t*>(b);
240  return fl_keyboard_pending_event_get_sequence_id(pending) == sequence_id;
241 }

References fl_keyboard_pending_event_get_sequence_id().

Referenced by responder_handle_event_callback().

◆ convert_key_to_char()

static uint16_t convert_key_to_char ( FlKeyboardViewDelegate *  view_delegate,
guint  keycode,
gint  group,
gint  level 
)
static

Definition at line 309 of file fl_keyboard_handler.cc.

312  {
313  GdkKeymapKey key = {keycode, group, level};
314  constexpr int kBmpMax = 0xD7FF;
315  guint origin = fl_keyboard_view_delegate_lookup_key(view_delegate, &key);
316  return origin < kBmpMax ? origin : 0xFFFF;
317 }

References fl_keyboard_view_delegate_lookup_key().

Referenced by guarantee_layout().

◆ dispatch_to_responder()

static void dispatch_to_responder ( gpointer  responder_data,
gpointer  foreach_data_ptr 
)
static

Definition at line 439 of file fl_keyboard_handler.cc.

440  {
441  DispatchToResponderLoopContext* context =
442  reinterpret_cast<DispatchToResponderLoopContext*>(foreach_data_ptr);
443  FlKeyResponder* responder = FL_KEY_RESPONDER(responder_data);
445  responder, context->event, responder_handle_event_callback,
446  context->user_data, context->specified_logical_key);
447 }

References fl_key_responder_handle_event(), and responder_handle_event_callback().

Referenced by fl_keyboard_handler_handle_event().

◆ fl_keyboard_handler_class_init()

static void fl_keyboard_handler_class_init ( FlKeyboardHandlerClass *  klass)
static

Definition at line 473 of file fl_keyboard_handler.cc.

473  {
474  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_handler_dispose;
475 }

References fl_keyboard_handler_dispose().

◆ fl_keyboard_handler_dispose()

static void fl_keyboard_handler_dispose ( GObject *  object)
static

Definition at line 449 of file fl_keyboard_handler.cc.

449  {
450  FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(object);
451 
452  if (self->view_delegate != nullptr) {
454  nullptr);
455  g_object_remove_weak_pointer(
456  G_OBJECT(self->view_delegate),
457  reinterpret_cast<gpointer*>(&(self->view_delegate)));
458  self->view_delegate = nullptr;
459  }
460 
461  self->derived_layout.reset();
462  self->keycode_to_goals.reset();
463  self->logical_to_mandatory_goals.reset();
464 
465  g_ptr_array_free(self->responder_list, TRUE);
466  g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
467  g_ptr_array_free(self->pending_responds, TRUE);
468  g_ptr_array_free(self->pending_redispatches, TRUE);
469 
470  G_OBJECT_CLASS(fl_keyboard_handler_parent_class)->dispose(object);
471 }

References fl_keyboard_view_delegate_subscribe_to_layout_change(), and TRUE.

Referenced by fl_keyboard_handler_class_init().

◆ fl_keyboard_handler_get_pressed_state()

GHashTable* fl_keyboard_handler_get_pressed_state ( FlKeyboardHandler *  handler)

fl_keyboard_handler_get_pressed_state: @handler: the #FlKeyboardHandler self.

Returns the keyboard pressed state. The hash table contains one entry per pressed keys, mapping from the logical key to the physical key.*

Definition at line 590 of file fl_keyboard_handler.cc.

590  {
591  g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), nullptr);
592 
593  // The embedder responder is the first element in
594  // FlKeyboardHandler.responder_list.
595  FlKeyEmbedderResponder* responder =
596  FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(self->responder_list, 0));
598 }

References fl_key_embedder_responder_get_pressed_state().

Referenced by fl_view_get_keyboard_state().

◆ fl_keyboard_handler_handle_event()

gboolean fl_keyboard_handler_handle_event ( FlKeyboardHandler *  handler,
FlKeyEvent *  event 
)

fl_keyboard_handler_handle_event: @handler: the #FlKeyboardHandler self. @event: the event to be dispatched. It is usually a wrap of a GdkEventKey. This event will be managed and released by #FlKeyboardHandler.

Make the handler process a system key event. This might eventually send messages to the framework, trigger text input effects, or redispatch the event back to the system.

Definition at line 541 of file fl_keyboard_handler.cc.

542  {
543  g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), FALSE);
544  g_return_val_if_fail(event != nullptr, FALSE);
545  g_return_val_if_fail(self->view_delegate != nullptr, FALSE);
546 
547  guarantee_layout(self, event);
548 
549  uint64_t incoming_hash = fl_key_event_hash(event);
550  if (fl_keyboard_handler_remove_redispatched(self, incoming_hash)) {
551  return FALSE;
552  }
553 
554  FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(
555  event, ++self->last_sequence_id, self->responder_list->len);
556 
557  g_ptr_array_add(self->pending_responds, pending);
558  FlKeyboardHandlerUserData* user_data = fl_keyboard_handler_user_data_new(
560  DispatchToResponderLoopContext data{
561  .event = event,
562  .specified_logical_key =
563  get_logical_key_from_layout(event, *self->derived_layout),
564  .user_data = user_data,
565  };
566  g_ptr_array_foreach(self->responder_list, dispatch_to_responder, &data);
567 
568  return TRUE;
569 }

References dispatch_to_responder(), event, fl_key_event_hash(), fl_keyboard_handler_remove_redispatched(), fl_keyboard_handler_user_data_new(), fl_keyboard_pending_event_get_sequence_id(), fl_keyboard_pending_event_new(), get_logical_key_from_layout(), guarantee_layout(), TRUE, and user_data.

Referenced by fl_view_key_press_event(), and fl_view_key_release_event().

◆ fl_keyboard_handler_init()

static void fl_keyboard_handler_init ( FlKeyboardHandler *  self)
static

Definition at line 477 of file fl_keyboard_handler.cc.

477  {
478  self->derived_layout = std::make_unique<DerivedLayout>();
479 
480  self->keycode_to_goals =
481  std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
482  self->logical_to_mandatory_goals =
483  std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
484  for (const LayoutGoal& goal : layout_goals) {
485  (*self->keycode_to_goals)[goal.keycode] = &goal;
486  if (goal.mandatory) {
487  (*self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
488  }
489  }
490 
491  self->responder_list = g_ptr_array_new_with_free_func(g_object_unref);
492 
493  self->pending_responds = g_ptr_array_new();
494  self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
495 
496  self->last_sequence_id = 1;
497 }

References if(), and layout_goals.

◆ fl_keyboard_handler_is_state_clear()

gboolean fl_keyboard_handler_is_state_clear ( FlKeyboardHandler *  handler)

fl_keyboard_handler_is_state_clear: @handler: the #FlKeyboardHandler self.

A debug-only method that queries whether the handler's various states are cleared, i.e. no pending events for redispatching or for responding.

Returns: true if the handler's various states are cleared.

Definition at line 571 of file fl_keyboard_handler.cc.

571  {
572  g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), FALSE);
573  return self->pending_responds->len == 0 &&
574  self->pending_redispatches->len == 0;
575 }

◆ fl_keyboard_handler_new()

FlKeyboardHandler* fl_keyboard_handler_new ( FlBinaryMessenger *  messenger,
FlKeyboardViewDelegate *  view_delegate 
)

FlKeyboardHandler:

Processes keyboard events and cooperate with TextInputHandler.

A keyboard event goes through a few sections, each can choose to handle the event, and only unhandled events can move to the next section:

  • Keyboard: Dispatch to the embedder responder and the channel responder simultaneously. After both responders have responded (asynchronously), the event is considered handled if either responder handles it.
  • Text input: Events are sent to IM filter (usually owned by TextInputHandler) and are handled synchronously.
  • Redispatching: Events are inserted back to the system for redispatching. fl_keyboard_handler_new: @view_delegate: An interface that the handler requires to communicate with the platform. Usually implemented by FlView.

Create a new #FlKeyboardHandler.

Returns: a new #FlKeyboardHandler.

Definition at line 499 of file fl_keyboard_handler.cc.

501  {
502  g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(view_delegate), nullptr);
503 
504  FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(
505  g_object_new(fl_keyboard_handler_get_type(), nullptr));
506 
507  self->view_delegate = view_delegate;
508  g_object_add_weak_pointer(
509  G_OBJECT(view_delegate),
510  reinterpret_cast<gpointer*>(&(self->view_delegate)));
511 
512  // The embedder responder must be added before the channel responder.
513  g_ptr_array_add(
514  self->responder_list,
515  FL_KEY_RESPONDER(fl_key_embedder_responder_new(
516  [](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
517  void* callback_user_data, void* send_key_event_user_data) {
518  FlKeyboardHandler* self =
519  FL_KEYBOARD_HANDLER(send_key_event_user_data);
520  g_return_if_fail(self->view_delegate != nullptr);
522  self->view_delegate, event, callback, callback_user_data);
523  },
524  self)));
525  g_ptr_array_add(self->responder_list,
526  FL_KEY_RESPONDER(fl_key_channel_responder_new(
527  fl_keyboard_view_delegate_get_messenger(view_delegate))));
528 
530  self->view_delegate, [self]() { self->derived_layout->clear(); });
531 
532  // Setup the flutter/keyboard channel.
533  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
534  self->channel =
535  fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
537  self, nullptr);
538  return self;
539 }

References callback, event, fl_key_channel_responder_new(), fl_key_embedder_responder_new(), fl_keyboard_view_delegate_get_messenger(), fl_keyboard_view_delegate_send_key_event(), fl_keyboard_view_delegate_subscribe_to_layout_change(), fl_method_channel_new(), fl_method_channel_set_method_call_handler(), fl_standard_method_codec_new(), kChannelName, and method_call_handler().

Referenced by init_keyboard().

◆ fl_keyboard_handler_remove_redispatched()

static bool fl_keyboard_handler_remove_redispatched ( FlKeyboardHandler *  self,
uint64_t  hash 
)
static

Definition at line 255 of file fl_keyboard_handler.cc.

256  {
257  guint result_index;
258  gboolean found = g_ptr_array_find_with_equal_func1(
259  self->pending_redispatches, static_cast<const uint64_t*>(&hash),
260  compare_pending_by_hash, &result_index);
261  if (found) {
262  // The removed object is freed due to `pending_redispatches`'s free_func.
263  g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
264  return TRUE;
265  } else {
266  return FALSE;
267  }
268 }

References compare_pending_by_hash(), g_ptr_array_find_with_equal_func1(), and TRUE.

Referenced by fl_keyboard_handler_handle_event().

◆ fl_keyboard_handler_sync_modifier_if_needed()

void fl_keyboard_handler_sync_modifier_if_needed ( FlKeyboardHandler *  handler,
guint  state,
double  event_time 
)

fl_keyboard_handler_sync_modifier_if_needed: @handler: the #FlKeyboardHandler self. @state: the state of the modifiers mask. @event_time: the time attribute of the incoming GDK event.

If needed, synthesize modifier keys up and down event by comparing their current pressing states with the given modifiers mask.

Definition at line 577 of file fl_keyboard_handler.cc.

579  {
580  g_return_if_fail(FL_IS_KEYBOARD_HANDLER(self));
581 
582  // The embedder responder is the first element in
583  // FlKeyboardHandler.responder_list.
584  FlKeyEmbedderResponder* responder =
585  FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(self->responder_list, 0));
587  event_time);
588 }

References fl_key_embedder_responder_sync_modifiers_if_needed(), and state.

Referenced by motion_notify_event_cb(), and send_pointer_button_event().

◆ fl_keyboard_handler_user_data_class_init()

static void fl_keyboard_handler_user_data_class_init ( FlKeyboardHandlerUserDataClass *  klass)
static

Definition at line 137 of file fl_keyboard_handler.cc.

138  {
139  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_handler_user_data_dispose;
140 }

◆ fl_keyboard_handler_user_data_init()

static void fl_keyboard_handler_user_data_init ( FlKeyboardHandlerUserData *  self)
static

Definition at line 142 of file fl_keyboard_handler.cc.

143  {}

◆ fl_keyboard_handler_user_data_new()

static FlKeyboardHandlerUserData* fl_keyboard_handler_user_data_new ( FlKeyboardHandler *  handler,
uint64_t  sequence_id 
)
static

Definition at line 146 of file fl_keyboard_handler.cc.

148  {
149  FlKeyboardHandlerUserData* self = FL_KEYBOARD_HANDLER_USER_DATA(
150  g_object_new(fl_keyboard_handler_user_data_get_type(), nullptr));
151 
152  self->handler = handler;
153  // Add a weak pointer so we can know if the key event responder disappeared
154  // while the framework was responding.
155  g_object_add_weak_pointer(G_OBJECT(handler),
156  reinterpret_cast<gpointer*>(&(self->handler)));
157  self->sequence_id = sequence_id;
158  return self;
159 }

Referenced by fl_keyboard_handler_handle_event().

◆ G_DECLARE_FINAL_TYPE()

G_DECLARE_FINAL_TYPE ( FlKeyboardHandlerUserData  ,
fl_keyboard_handler_user_data  ,
FL  ,
KEYBOARD_HANDLER_USER_DATA  ,
GObject   
)

◆ G_DEFINE_TYPE() [1/2]

G_DEFINE_TYPE ( FlKeyboardHandler  ,
fl_keyboard_handler  ,
G_TYPE_OBJECT   
)

◆ G_DEFINE_TYPE() [2/2]

G_DEFINE_TYPE ( FlKeyboardHandlerUserData  ,
fl_keyboard_handler_user_data  ,
G_TYPE_OBJECT   
)

Definition at line 123 of file fl_keyboard_handler.cc.

127  {
128  g_return_if_fail(FL_IS_KEYBOARD_HANDLER_USER_DATA(object));
129  FlKeyboardHandlerUserData* self = FL_KEYBOARD_HANDLER_USER_DATA(object);
130  if (self->handler != nullptr) {
131  g_object_remove_weak_pointer(G_OBJECT(self->handler),
132  reinterpret_cast<gpointer*>(&(self->handler)));
133  self->handler = nullptr;
134  }
135 }

◆ 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_ 
)
static

Definition at line 213 of file fl_keyboard_handler.cc.

216  {
217  guint i;
218  g_return_val_if_fail(haystack != NULL, FALSE);
219  if (equal_func == NULL) {
220  equal_func = g_direct_equal;
221  }
222  for (i = 0; i < haystack->len; i++) {
223  if (equal_func(g_ptr_array_index(haystack, i), needle)) {
224  if (index_ != NULL) {
225  *index_ = i;
226  }
227  return TRUE;
228  }
229  }
230 
231  return FALSE;
232 }

References i, and TRUE.

Referenced by fl_keyboard_handler_remove_redispatched(), and responder_handle_event_callback().

◆ get_keyboard_state()

static FlMethodResponse* get_keyboard_state ( FlKeyboardHandler *  self)
static

Definition at line 397 of file fl_keyboard_handler.cc.

397  {
398  g_autoptr(FlValue) result = fl_value_new_map();
399 
400  GHashTable* pressing_records =
402 
403  g_hash_table_foreach(
404  pressing_records,
405  [](gpointer key, gpointer value, gpointer user_data) {
406  int64_t physical_key = reinterpret_cast<int64_t>(key);
407  int64_t logical_key = reinterpret_cast<int64_t>(value);
408  FlValue* fl_value_map = reinterpret_cast<FlValue*>(user_data);
409 
410  fl_value_set_take(fl_value_map, fl_value_new_int(physical_key),
411  fl_value_new_int(logical_key));
412  },
413  result);
414  return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
415 }

References fl_keyboard_view_delegate_get_keyboard_state(), fl_method_success_response_new(), fl_value_new_int(), fl_value_new_map(), fl_value_set_take(), result, user_data, and value.

Referenced by method_call_handler().

◆ get_logical_key_from_layout()

static uint64_t get_logical_key_from_layout ( FlKeyEvent *  event,
const DerivedLayout &  layout 
)
static

Definition at line 92 of file fl_keyboard_handler.cc.

93  {
94  guint8 group = fl_key_event_get_group(event);
95  guint16 keycode = fl_key_event_get_keycode(event);
96  if (keycode >= kLayoutSize) {
97  return 0;
98  }
99 
100  auto found_group_layout = layout.find(group);
101  if (found_group_layout != layout.end()) {
102  return found_group_layout->second[keycode];
103  }
104  return 0;
105 }

References event, fl_key_event_get_group(), and fl_key_event_get_keycode().

Referenced by fl_keyboard_handler_handle_event().

◆ guarantee_layout()

static void guarantee_layout ( FlKeyboardHandler *  self,
FlKeyEvent *  event 
)
static

Definition at line 321 of file fl_keyboard_handler.cc.

321  {
322  guint8 group = fl_key_event_get_group(event);
323  if (self->derived_layout->find(group) != self->derived_layout->end()) {
324  return;
325  }
326  if (self->keycode_to_goals->find(fl_key_event_get_keycode(event)) ==
327  self->keycode_to_goals->end()) {
328  return;
329  }
330 
331  DerivedGroupLayout& layout = (*self->derived_layout)[group];
332 
333  // Clone all mandatory goals. Each goal is removed from this cloned map when
334  // fulfilled, and the remaining ones will be assigned to a default position.
335  std::map<uint64_t, const LayoutGoal*> remaining_mandatory_goals =
336  *self->logical_to_mandatory_goals;
337 
338 #ifdef DEBUG_PRINT_LAYOUT
339  std::string debug_layout_data;
340  for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
341  std::vector<uint16_t> this_key_clues = {
342  convert_key_to_char(self->view_delegate, keycode, group, 0),
343  convert_key_to_char(self->view_delegate, keycode, group, 1), // Shift
344  };
345  debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
346  this_key_clues[1]);
347  }
348 #endif
349 
350  // It's important to only traverse layout goals instead of all keycodes.
351  // Some key codes outside of the standard keyboard also gives alpha-numeric
352  // letters, and will therefore take over mandatory goals from standard
353  // keyboard keys if they come first. Example: French keyboard digit 1.
354  for (const LayoutGoal& keycode_goal : layout_goals) {
355  uint16_t keycode = keycode_goal.keycode;
356  std::vector<uint16_t> this_key_clues = {
357  convert_key_to_char(self->view_delegate, keycode, group, 0),
358  convert_key_to_char(self->view_delegate, keycode, group, 1), // Shift
359  };
360 
361  // The logical key should be the first available clue from below:
362  //
363  // - Mandatory goal, if it matches any clue. This ensures that all alnum
364  // keys can be found somewhere.
365  // - US layout, if neither clue of the key is EASCII. This ensures that
366  // there are no non-latin logical keys.
367  // - A value derived on the fly from keycode & keyval.
368  for (uint16_t clue : this_key_clues) {
369  auto matching_goal = remaining_mandatory_goals.find(clue);
370  if (matching_goal != remaining_mandatory_goals.end()) {
371  // Found a key that produces a mandatory char. Use it.
372  g_return_if_fail(layout[keycode] == 0);
373  layout[keycode] = clue;
374  remaining_mandatory_goals.erase(matching_goal);
375  break;
376  }
377  }
378  bool has_any_eascii =
379  is_eascii(this_key_clues[0]) || is_eascii(this_key_clues[1]);
380  // See if any produced char meets the requirement as a logical key.
381  if (layout[keycode] == 0 && !has_any_eascii) {
382  auto found_us_layout = self->keycode_to_goals->find(keycode);
383  if (found_us_layout != self->keycode_to_goals->end()) {
384  layout[keycode] = found_us_layout->second->logical_key;
385  }
386  }
387  }
388 
389  // Ensure all mandatory goals are assigned.
390  for (const auto mandatory_goal_iter : remaining_mandatory_goals) {
391  const LayoutGoal* goal = mandatory_goal_iter.second;
392  layout[goal->keycode] = goal->logical_key;
393  }
394 }

References convert_key_to_char(), event, fl_key_event_get_group(), fl_key_event_get_keycode(), LayoutGoal::keycode, layout_goals, and LayoutGoal::logical_key.

Referenced by fl_keyboard_handler_handle_event().

◆ method_call_handler()

static void method_call_handler ( FlMethodChannel *  channel,
FlMethodCall *  method_call,
gpointer  user_data 
)
static

Definition at line 418 of file fl_keyboard_handler.cc.

420  {
421  FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(user_data);
422 
423  const gchar* method = fl_method_call_get_name(method_call);
424 
425  g_autoptr(FlMethodResponse) response = nullptr;
426  if (strcmp(method, kGetKeyboardStateMethod) == 0) {
427  response = get_keyboard_state(self);
428  } else {
429  response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
430  }
431 
432  g_autoptr(GError) error = nullptr;
433  if (!fl_method_call_respond(method_call, response, &error)) {
434  g_warning("Failed to send method call response: %s", error->message);
435  }
436 }

References error, fl_method_call_get_name(), fl_method_call_respond(), fl_method_not_implemented_response_new(), get_keyboard_state(), kGetKeyboardStateMethod, method_call, and user_data.

Referenced by fl_keyboard_handler_new().

◆ responder_handle_event_callback()

static void responder_handle_event_callback ( bool  handled,
gpointer  user_data_ptr 
)
static

Definition at line 271 of file fl_keyboard_handler.cc.

272  {
273  g_return_if_fail(FL_IS_KEYBOARD_HANDLER_USER_DATA(user_data_ptr));
274  FlKeyboardHandlerUserData* user_data =
275  FL_KEYBOARD_HANDLER_USER_DATA(user_data_ptr);
276  FlKeyboardHandler* self = user_data->handler;
277  g_return_if_fail(self->view_delegate != nullptr);
278 
279  guint result_index = -1;
280  gboolean found = g_ptr_array_find_with_equal_func1(
281  self->pending_responds, &user_data->sequence_id,
282  compare_pending_by_sequence_id, &result_index);
283  g_return_if_fail(found);
284  FlKeyboardPendingEvent* pending = FL_KEYBOARD_PENDING_EVENT(
285  g_ptr_array_index(self->pending_responds, result_index));
286  g_return_if_fail(pending != nullptr);
287  fl_keyboard_pending_event_mark_replied(pending, handled);
288  // All responders have replied.
290  g_object_unref(user_data_ptr);
291  gpointer removed =
292  g_ptr_array_remove_index_fast(self->pending_responds, result_index);
293  g_return_if_fail(removed == pending);
294  bool should_redispatch =
297  self->view_delegate, fl_keyboard_pending_event_get_event(pending));
298  if (should_redispatch) {
299  g_ptr_array_add(self->pending_redispatches, pending);
301  self->view_delegate,
302  FL_KEY_EVENT(fl_keyboard_pending_event_get_event(pending)));
303  } else {
304  g_object_unref(pending);
305  }
306  }
307 }

References compare_pending_by_sequence_id(), fl_keyboard_pending_event_get_any_handled(), fl_keyboard_pending_event_get_event(), fl_keyboard_pending_event_is_complete(), fl_keyboard_pending_event_mark_replied(), fl_keyboard_view_delegate_redispatch_event(), fl_keyboard_view_delegate_text_filter_key_press(), g_ptr_array_find_with_equal_func1(), and user_data.

Referenced by dispatch_to_responder().

Variable Documentation

◆ kChannelName

constexpr char kChannelName[] = "flutter/keyboard"
staticconstexpr

Definition at line 23 of file fl_keyboard_handler.cc.

Referenced by fl_keyboard_handler_new().

◆ kGetKeyboardStateMethod

constexpr char kGetKeyboardStateMethod[] = "getKeyboardState"
staticconstexpr

Definition at line 24 of file fl_keyboard_handler.cc.

Referenced by method_call_handler().

fl_keyboard_pending_event_get_hash
uint64_t fl_keyboard_pending_event_get_hash(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:81
if
if(end==-1)
Definition: fl_accessible_text_field.cc:42
fl_keyboard_view_delegate_redispatch_event
void fl_keyboard_view_delegate_redispatch_event(FlKeyboardViewDelegate *self, FlKeyEvent *event)
Definition: fl_keyboard_view_delegate.cc:42
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
get_keyboard_state
static FlMethodResponse * get_keyboard_state(FlKeyboardHandler *self)
Definition: fl_keyboard_handler.cc:397
fl_keyboard_pending_event_get_event
FlKeyEvent * fl_keyboard_pending_event_get_event(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:70
layout_goals
const std::vector< LayoutGoal > layout_goals
Definition: key_mapping.g.cc:462
kChannelName
static constexpr char kChannelName[]
Definition: fl_keyboard_handler.cc:23
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
fl_key_event_get_group
guint8 fl_key_event_get_group(FlKeyEvent *self)
Definition: fl_key_event.cc:104
fl_key_embedder_responder_get_pressed_state
GHashTable * fl_key_embedder_responder_get_pressed_state(FlKeyEmbedderResponder *self)
Definition: fl_key_embedder_responder.cc:896
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:51
LayoutGoal
Definition: key_mapping.h:40
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
i
int i
Definition: fl_socket_accessible.cc:18
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
fl_keyboard_handler_user_data_new
static FlKeyboardHandlerUserData * fl_keyboard_handler_user_data_new(FlKeyboardHandler *handler, uint64_t sequence_id)
Definition: fl_keyboard_handler.cc:146
LayoutGoal::keycode
uint16_t keycode
Definition: key_mapping.h:42
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_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
convert_key_to_char
static uint16_t convert_key_to_char(FlKeyboardViewDelegate *view_delegate, guint keycode, gint group, gint level)
Definition: fl_keyboard_handler.cc:309
fl_method_success_response_new
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
Definition: fl_method_response.cc:126
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
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_handler.cc:213
fl_keyboard_pending_event_get_sequence_id
uint64_t fl_keyboard_pending_event_get_sequence_id(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:75
fl_keyboard_view_delegate_lookup_key
guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate *self, const GdkKeymapKey *key)
Definition: fl_keyboard_view_delegate.cc:60
fl_keyboard_pending_event_is_complete
gboolean fl_keyboard_pending_event_is_complete(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:102
kGetKeyboardStateMethod
static constexpr char kGetKeyboardStateMethod[]
Definition: fl_keyboard_handler.cc:24
fl_keyboard_pending_event_get_any_handled
gboolean fl_keyboard_pending_event_get_any_handled(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:96
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_method_call_respond
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
Definition: fl_method_call.cc:77
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
guarantee_layout
static void guarantee_layout(FlKeyboardHandler *self, FlKeyEvent *event)
Definition: fl_keyboard_handler.cc:321
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
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
fl_keyboard_handler_remove_redispatched
static bool fl_keyboard_handler_remove_redispatched(FlKeyboardHandler *self, uint64_t hash)
Definition: fl_keyboard_handler.cc:255
fl_keyboard_pending_event_mark_replied
void fl_keyboard_pending_event_mark_replied(FlKeyboardPendingEvent *self, gboolean handled)
Definition: fl_keyboard_pending_event.cc:86
fl_method_call_get_name
const G_MODULE_EXPORT gchar * fl_method_call_get_name(FlMethodCall *self)
Definition: fl_method_call.cc:67
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
responder_handle_event_callback
static void responder_handle_event_callback(bool handled, gpointer user_data_ptr)
Definition: fl_keyboard_handler.cc:271
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:879
method_call_handler
static void method_call_handler(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
Definition: fl_keyboard_handler.cc:418
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
result
GAsyncResult * result
Definition: fl_text_input_handler.cc:106
fl_key_event_hash
uint64_t fl_key_event_hash(FlKeyEvent *self)
Definition: fl_key_event.cc:114
fl_key_event_get_keycode
guint16 fl_key_event_get_keycode(FlKeyEvent *self)
Definition: fl_key_event.cc:89
compare_pending_by_hash
static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b)
Definition: fl_keyboard_handler.cc:244
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_keyboard_view_delegate_get_messenger
FlBinaryMessenger * fl_keyboard_view_delegate_get_messenger(FlKeyboardViewDelegate *self)
Definition: fl_keyboard_view_delegate.cc:35
compare_pending_by_sequence_id
static gboolean compare_pending_by_sequence_id(gconstpointer a, gconstpointer b)
Definition: fl_keyboard_handler.cc:235
fl_keyboard_pending_event_new
FlKeyboardPendingEvent * fl_keyboard_pending_event_new(FlKeyEvent *event, uint64_t sequence_id, size_t to_reply)
Definition: fl_keyboard_pending_event.cc:55
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
dispatch_to_responder
static void dispatch_to_responder(gpointer responder_data, gpointer foreach_data_ptr)
Definition: fl_keyboard_handler.cc:439
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:67
get_logical_key_from_layout
static uint64_t get_logical_key_from_layout(FlKeyEvent *event, const DerivedLayout &layout)
Definition: fl_keyboard_handler.cc:92
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_keyboard_handler_dispose
static void fl_keyboard_handler_dispose(GObject *object)
Definition: fl_keyboard_handler.cc:449