Flutter Linux Embedder
fl_keyboard_manager.cc File Reference

Go to the source code of this file.

Classes

struct  _FlKeyboardPendingEvent
 
struct  _FlKeyboardManagerUserData
 
struct  _FlKeyboardManager
 

Macros

#define DEBUG_PRINT_LAYOUT
 
#define FL_TYPE_KEYBOARD_MANAGER_USER_DATA   fl_keyboard_manager_user_data_get_type()
 

Functions

 G_DECLARE_FINAL_TYPE (FlKeyboardPendingEvent, fl_keyboard_pending_event, FL, KEYBOARD_PENDING_EVENT, GObject)
 
 G_DECLARE_FINAL_TYPE (FlKeyboardManagerUserData, fl_keyboard_manager_user_data, FL, KEYBOARD_MANAGER_USER_DATA, GObject)
 
static uint64_t get_logical_key_from_layout (const FlKeyEvent *event, const DerivedLayout &layout)
 
static void fl_keyboard_pending_event_dispose (GObject *object)
 
static void fl_keyboard_pending_event_class_init (FlKeyboardPendingEventClass *klass)
 
static void fl_keyboard_pending_event_init (FlKeyboardPendingEvent *self)
 
static uint64_t fl_keyboard_manager_get_event_hash (FlKeyEvent *event)
 
static FlKeyboardPendingEvent * fl_keyboard_pending_event_new (std::unique_ptr< FlKeyEvent > event, uint64_t sequence_id, size_t to_reply)
 
 G_DEFINE_TYPE (FlKeyboardManagerUserData, fl_keyboard_manager_user_data, G_TYPE_OBJECT) static void fl_keyboard_manager_user_data_dispose(GObject *object)
 
static void fl_keyboard_manager_user_data_class_init (FlKeyboardManagerUserDataClass *klass)
 
static void fl_keyboard_manager_user_data_init (FlKeyboardManagerUserData *self)
 
static FlKeyboardManagerUserData * fl_keyboard_manager_user_data_new (FlKeyboardManager *manager, uint64_t sequence_id)
 
 G_DEFINE_TYPE (FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT)
 
static void fl_keyboard_manager_dispose (GObject *object)
 
static void fl_keyboard_manager_class_init (FlKeyboardManagerClass *klass)
 
static void fl_keyboard_manager_init (FlKeyboardManager *self)
 
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 pending, gconstpointer needle_sequence_id)
 
static gboolean compare_pending_by_hash (gconstpointer pending, gconstpointer needle_hash)
 
static bool fl_keyboard_manager_remove_redispatched (FlKeyboardManager *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 (FlKeyboardManager *self, FlKeyEvent *event)
 
FlMethodResponse * get_keyboard_state (FlKeyboardManager *self)
 
static void method_call_handler (FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
 
FlKeyboardManagerfl_keyboard_manager_new (FlBinaryMessenger *messenger, FlKeyboardViewDelegate *view_delegate)
 
static void dispatch_to_responder (gpointer responder_data, gpointer foreach_data_ptr)
 
gboolean fl_keyboard_manager_handle_event (FlKeyboardManager *self, FlKeyEvent *event)
 
gboolean fl_keyboard_manager_is_state_clear (FlKeyboardManager *self)
 
void fl_keyboard_manager_sync_modifier_if_needed (FlKeyboardManager *self, guint state, double event_time)
 
GHashTable * fl_keyboard_manager_get_pressed_state (FlKeyboardManager *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 20 of file fl_keyboard_manager.cc.

◆ FL_TYPE_KEYBOARD_MANAGER_USER_DATA

#define FL_TYPE_KEYBOARD_MANAGER_USER_DATA   fl_keyboard_manager_user_data_get_type()

Definition at line 33 of file fl_keyboard_manager.cc.

Function Documentation

◆ compare_pending_by_hash()

static gboolean compare_pending_by_hash ( gconstpointer  pending,
gconstpointer  needle_hash 
)
static

Definition at line 392 of file fl_keyboard_manager.cc.

393  {
394  uint64_t hash = *reinterpret_cast<const uint64_t*>(needle_hash);
395  return static_cast<const FlKeyboardPendingEvent*>(pending)->hash == hash;
396 }

Referenced by fl_keyboard_manager_remove_redispatched().

◆ compare_pending_by_sequence_id()

static gboolean compare_pending_by_sequence_id ( gconstpointer  pending,
gconstpointer  needle_sequence_id 
)
static

Definition at line 382 of file fl_keyboard_manager.cc.

384  {
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 }

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 456 of file fl_keyboard_manager.cc.

459  {
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 }

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 628 of file fl_keyboard_manager.cc.

629  {
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 }

References fl_key_responder_handle_event(), and responder_handle_event_callback().

Referenced by fl_keyboard_manager_handle_event().

◆ fl_keyboard_manager_class_init()

static void fl_keyboard_manager_class_init ( FlKeyboardManagerClass *  klass)
static

Definition at line 304 of file fl_keyboard_manager.cc.

304  {
305  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_dispose;
306 }

References fl_keyboard_manager_dispose().

◆ fl_keyboard_manager_dispose()

static void fl_keyboard_manager_dispose ( GObject *  object)
static

Definition at line 330 of file fl_keyboard_manager.cc.

330  {
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 }

References fl_keyboard_view_delegate_subscribe_to_layout_change(), and TRUE.

Referenced by fl_keyboard_manager_class_init().

◆ fl_keyboard_manager_get_event_hash()

static uint64_t fl_keyboard_manager_get_event_hash ( FlKeyEvent event)
static

Definition at line 168 of file fl_keyboard_manager.cc.

168  {
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 }

References event, _FlKeyEvent::time, and type.

Referenced by fl_keyboard_manager_handle_event(), and fl_keyboard_pending_event_new().

◆ fl_keyboard_manager_get_pressed_state()

GHashTable* fl_keyboard_manager_get_pressed_state ( FlKeyboardManager manager)

fl_keyboard_manager_get_pressed_state: @manager: the FlKeyboardManager 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 688 of file fl_keyboard_manager.cc.

688  {
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 }

References fl_key_embedder_responder_get_pressed_state().

Referenced by fl_view_get_keyboard_state().

◆ fl_keyboard_manager_handle_event()

gboolean fl_keyboard_manager_handle_event ( FlKeyboardManager manager,
FlKeyEvent event 
)

fl_keyboard_manager_handle_event: @manager: the FlKeyboardManager self. @event: the event to be dispatched. It is usually a wrap of a GdkEventKey. This event will be managed and released by FlKeyboardManager.

Make the manager 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 638 of file fl_keyboard_manager.cc.

639  {
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 }

References dispatch_to_responder(), event, fl_keyboard_manager_get_event_hash(), fl_keyboard_manager_remove_redispatched(), fl_keyboard_manager_user_data_new(), 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_manager_init()

static void fl_keyboard_manager_init ( FlKeyboardManager self)
static

Definition at line 308 of file fl_keyboard_manager.cc.

308  {
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 }

References if(), and layout_goals.

◆ fl_keyboard_manager_is_state_clear()

gboolean fl_keyboard_manager_is_state_clear ( FlKeyboardManager manager)

fl_keyboard_manager_is_state_clear: @manager: the FlKeyboardManager self.

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

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

Definition at line 669 of file fl_keyboard_manager.cc.

669  {
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 }

◆ fl_keyboard_manager_new()

FlKeyboardManager* fl_keyboard_manager_new ( FlBinaryMessenger *  messenger,
FlKeyboardViewDelegate *  view_delegate 
)

FlKeyboardManager:

Processes keyboard events and cooperate with TextInputPlugin.

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 TextInputPlugin) and are handled synchronously.
  • Redispatching: Events are inserted back to the system for redispatching. fl_keyboard_manager_new: @view_delegate: An interface that the manager requires to communicate with the platform. Usually implemented by FlView.

Create a new FlKeyboardManager.

Returns: a new FlKeyboardManager.

Definition at line 585 of file fl_keyboard_manager.cc.

587  {
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;
594  g_object_add_weak_pointer(
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 }

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_manager_remove_redispatched()

static bool fl_keyboard_manager_remove_redispatched ( FlKeyboardManager self,
uint64_t  hash 
)
static

Definition at line 402 of file fl_keyboard_manager.cc.

403  {
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 }

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

Referenced by fl_keyboard_manager_handle_event().

◆ fl_keyboard_manager_sync_modifier_if_needed()

void fl_keyboard_manager_sync_modifier_if_needed ( FlKeyboardManager manager,
guint  state,
double  event_time 
)

fl_keyboard_manager_sync_modifier_if_needed: @manager: the FlKeyboardManager 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 675 of file fl_keyboard_manager.cc.

677  {
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 }

References fl_key_embedder_responder_sync_modifiers_if_needed(), and state.

Referenced by motion_notify_event_cb(), and send_pointer_button_event().

◆ fl_keyboard_manager_user_data_class_init()

static void fl_keyboard_manager_user_data_class_init ( FlKeyboardManagerUserDataClass *  klass)
static

Definition at line 229 of file fl_keyboard_manager.cc.

230  {
231  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_user_data_dispose;
232 }

◆ fl_keyboard_manager_user_data_init()

static void fl_keyboard_manager_user_data_init ( FlKeyboardManagerUserData *  self)
static

Definition at line 234 of file fl_keyboard_manager.cc.

235  {}

◆ fl_keyboard_manager_user_data_new()

static FlKeyboardManagerUserData* fl_keyboard_manager_user_data_new ( FlKeyboardManager manager,
uint64_t  sequence_id 
)
static

Definition at line 238 of file fl_keyboard_manager.cc.

240  {
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 }

Referenced by fl_keyboard_manager_handle_event().

◆ fl_keyboard_pending_event_class_init()

static void fl_keyboard_pending_event_class_init ( FlKeyboardPendingEventClass *  klass)
static

Definition at line 159 of file fl_keyboard_manager.cc.

160  {
161  G_OBJECT_CLASS(klass)->dispose = fl_keyboard_pending_event_dispose;
162 }

References fl_keyboard_pending_event_dispose().

◆ fl_keyboard_pending_event_dispose()

static void fl_keyboard_pending_event_dispose ( GObject *  object)
static

Definition at line 147 of file fl_keyboard_manager.cc.

147  {
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 }

References fl_key_event_dispose().

Referenced by fl_keyboard_pending_event_class_init().

◆ fl_keyboard_pending_event_init()

static void fl_keyboard_pending_event_init ( FlKeyboardPendingEvent *  self)
static

Definition at line 164 of file fl_keyboard_manager.cc.

164 {}

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

Definition at line 184 of file fl_keyboard_manager.cc.

187  {
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 }

References event, and fl_keyboard_manager_get_event_hash().

Referenced by fl_keyboard_manager_handle_event().

◆ G_DECLARE_FINAL_TYPE() [1/2]

G_DECLARE_FINAL_TYPE ( FlKeyboardManagerUserData  ,
fl_keyboard_manager_user_data  ,
FL  ,
KEYBOARD_MANAGER_USER_DATA  ,
GObject   
)

◆ G_DECLARE_FINAL_TYPE() [2/2]

G_DECLARE_FINAL_TYPE ( FlKeyboardPendingEvent  ,
fl_keyboard_pending_event  ,
FL  ,
KEYBOARD_PENDING_EVENT  ,
GObject   
)

◆ G_DEFINE_TYPE() [1/2]

G_DEFINE_TYPE ( FlKeyboardManager  ,
fl_keyboard_manager  ,
G_TYPE_OBJECT   
)

◆ G_DEFINE_TYPE() [2/2]

G_DEFINE_TYPE ( FlKeyboardManagerUserData  ,
fl_keyboard_manager_user_data  ,
G_TYPE_OBJECT   
)

Definition at line 215 of file fl_keyboard_manager.cc.

219  {
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 }

◆ 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 359 of file fl_keyboard_manager.cc.

362  {
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 }

References i, and TRUE.

Referenced by fl_keyboard_manager_remove_redispatched(), and responder_handle_event_callback().

◆ get_keyboard_state()

FlMethodResponse* get_keyboard_state ( FlKeyboardManager self)

Definition at line 544 of file fl_keyboard_manager.cc.

544  {
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 }

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 ( const FlKeyEvent event,
const DerivedLayout &  layout 
)
static

Definition at line 97 of file fl_keyboard_manager.cc.

98  {
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 }

Referenced by fl_keyboard_manager_handle_event().

◆ guarantee_layout()

static void guarantee_layout ( FlKeyboardManager self,
FlKeyEvent event 
)
static

Definition at line 468 of file fl_keyboard_manager.cc.

468  {
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 }

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

Referenced by fl_keyboard_manager_handle_event().

◆ method_call_handler()

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

Definition at line 565 of file fl_keyboard_manager.cc.

567  {
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 }

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_manager_new().

◆ responder_handle_event_callback()

static void responder_handle_event_callback ( bool  handled,
gpointer  user_data_ptr 
)
static

Definition at line 418 of file fl_keyboard_manager.cc.

419  {
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 }

References compare_pending_by_sequence_id(), 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 22 of file fl_keyboard_manager.cc.

Referenced by fl_keyboard_manager_new().

◆ kGetKeyboardStateMethod

constexpr char kGetKeyboardStateMethod[] = "getKeyboardState"
staticconstexpr

Definition at line 23 of file fl_keyboard_manager.cc.

Referenced by method_call_handler().

_FlKeyEvent::time
guint32 time
Definition: fl_key_event.h:24
if
if(end==-1)
Definition: fl_accessible_text_field.cc:42
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
layout_goals
const std::vector< LayoutGoal > layout_goals
Definition: key_mapping.g.cc:462
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_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
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
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
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
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_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
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
dispatch_to_responder
static void dispatch_to_responder(gpointer responder_data, gpointer foreach_data_ptr)
Definition: fl_keyboard_manager.cc:628
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
_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_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
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
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_key_event_dispose
void fl_key_event_dispose(FlKeyEvent *event)
Definition: fl_key_event.cc:32
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_plugin.cc:106
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
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
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
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
typedefG_BEGIN_DECLS struct _FlKeyboardManager FlKeyboardManager
Definition: fl_key_responder.h:17