| Flutter Linux Embedder |

Classes | Macros | Functions
fl_keyboard_manager.cc File Reference
`#include "flutter/shell/platform/linux/fl_keyboard_manager.h"`
`#include <array>`
`#include <cinttypes>`
`#include <memory>`
`#include <string>`
`#include "flutter/shell/platform/linux/fl_engine_private.h"`
`#include "flutter/shell/platform/linux/fl_key_channel_responder.h"`
`#include "flutter/shell/platform/linux/fl_key_embedder_responder.h"`
`#include "flutter/shell/platform/linux/fl_keyboard_layout.h"`
`#include "flutter/shell/platform/linux/fl_keyboard_pending_event.h"`
`#include "flutter/shell/platform/linux/key_mapping.h"`

Go to the source code of this file.

## Classes
struct | _FlKeyboardManagerData
struct | _FlKeyboardManager

## Macros
#define | DEBUG_PRINT_LAYOUT

## Functions
| G_DECLARE_FINAL_TYPE (FlKeyboardManagerData, fl_keyboard_manager_data, FL, KEYBOARD_MANAGER_DATA, GObject)
static void | fl_keyboard_manager_data_dispose (GObject *object)
static void | fl_keyboard_manager_data_class_init (FlKeyboardManagerDataClass *klass)
static void | fl_keyboard_manager_data_init (FlKeyboardManagerData *self)
static FlKeyboardManagerData * | fl_keyboard_manager_data_new (FlKeyboardManager *manager, FlKeyboardPendingEvent *pending)
| G_DEFINE_TYPE (FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT)
static void | keymap_keys_changed_cb (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_hash (gconstpointer a, gconstpointer b)
static bool | fl_keyboard_manager_remove_redispatched (FlKeyboardManager *self, uint64_t hash)
static void | responder_handle_event_callback (FlKeyboardManager *self, FlKeyboardPendingEvent *pending)
static void | responder_handle_embedder_event_callback (bool handled, gpointer user_data)
static void | responder_handle_channel_event_cb (GObject *object, GAsyncResult *result, gpointer user_data)
static uint16_t | convert_key_to_char (FlKeyboardManager *self, guint keycode, gint group, gint level)
static void | guarantee_layout (FlKeyboardManager *self, FlKeyEvent *event)
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)
FlKeyboardManager * | fl_keyboard_manager_new (FlEngine *engine, FlKeyboardViewDelegate *view_delegate)
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)
void | fl_keyboard_manager_set_send_key_event_handler (FlKeyboardManager *self, FlKeyboardManagerSendKeyEventHandler send_key_event_handler, gpointer user_data)
void | fl_keyboard_manager_set_lookup_key_handler (FlKeyboardManager *self, FlKeyboardManagerLookupKeyHandler lookup_key_handler, gpointer user_data)
void | fl_keyboard_manager_set_redispatch_handler (FlKeyboardManager *self, FlKeyboardManagerRedispatchEventHandler redispatch_handler, gpointer user_data)
void | fl_keyboard_manager_set_get_pressed_state_handler (FlKeyboardManager *self, FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler, gpointer user_data)

## Macro Definition Documentation

## ◆ DEBUG_PRINT_LAYOUT

#define DEBUG_PRINT_LAYOUT

Definition at line 21 of file fl_keyboard_manager.cc.

## Function Documentation

## ◆ compare_pending_by_hash()

static gboolean compare_pending_by_hash | ( | gconstpointer | a,
|  | gconstpointer | b
| ) |  |
| static

Definition at line 207 of file fl_keyboard_manager.cc.

207 {
208 FlKeyboardPendingEvent* pending =
209 FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
210 uint64_t hash = *reinterpret_cast<const uint64_t*>(b);
211 return fl_keyboard_pending_event_get_hash(pending) == hash;
212 }

References fl_keyboard_pending_event_get_hash().

Referenced by fl_keyboard_manager_remove_redispatched().

## ◆ convert_key_to_char()

static uint16_t convert_key_to_char | ( | FlKeyboardManager * | self,
|  | guint | keycode,
|  | gint | group,
|  | gint | level
| ) |  |
| static

Definition at line 306 of file fl_keyboard_manager.cc.

309 {
310 GdkKeymapKey key = {keycode, group, level};
311 constexpr int kBmpMax = 0xD7FF;
312 guint origin;
313 if (self->lookup_key_handler != nullptr) {
314 origin = self->lookup_key_handler(&key, self->lookup_key_handler_user_data);
315 } else {
316 origin = gdk_keymap_lookup_key(self->keymap, &key);
317 }
318 return origin < kBmpMax ? origin : 0xFFFF;
319 }

Referenced by guarantee_layout().

## ◆ fl_keyboard_manager_class_init()

static void fl_keyboard_manager_class_init | ( | FlKeyboardManagerClass * | klass | ) |
| static

Definition at line 435 of file fl_keyboard_manager.cc.

435 {
436 G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_dispose;
437 }

References fl_keyboard_manager_dispose().

## ◆ fl_keyboard_manager_data_class_init()

static void fl_keyboard_manager_data_class_init | ( | FlKeyboardManagerDataClass * | klass | ) |
| static

Definition at line 94 of file fl_keyboard_manager.cc.

95 {
96 G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_data_dispose;
97 }

References fl_keyboard_manager_data_dispose().

## ◆ fl_keyboard_manager_data_dispose()

static void fl_keyboard_manager_data_dispose | ( | GObject * | object | ) |
| static

Definition at line 85 of file fl_keyboard_manager.cc.

85 {
86 g_return_if_fail(FL_IS_KEYBOARD_MANAGER_DATA(object));
87 FlKeyboardManagerData* self = FL_KEYBOARD_MANAGER_DATA(object);
88
89 g_weak_ref_clear(&self->manager);
90
91 G_OBJECT_CLASS(fl_keyboard_manager_data_parent_class)->dispose(object);
92 }

Referenced by fl_keyboard_manager_data_class_init().

## ◆ fl_keyboard_manager_data_init()

static void fl_keyboard_manager_data_init | ( | FlKeyboardManagerData * | self | ) |
| static

Definition at line 99 of file fl_keyboard_manager.cc.

99 {}

## ◆ fl_keyboard_manager_data_new()

static FlKeyboardManagerData* fl_keyboard_manager_data_new | ( | FlKeyboardManager * | manager,
|  | FlKeyboardPendingEvent * | pending
| ) |  |
| static

Definition at line 102 of file fl_keyboard_manager.cc.

104 {
105 FlKeyboardManagerData* self = FL_KEYBOARD_MANAGER_DATA(
106 g_object_new(fl_keyboard_manager_data_get_type(), nullptr));
107
108 g_weak_ref_init(&self->manager, manager);
109 self->pending = FL_KEYBOARD_PENDING_EVENT(g_object_ref(pending));
110 return self;
111 }

Referenced by fl_keyboard_manager_handle_event().

## ◆ fl_keyboard_manager_dispose()

static void fl_keyboard_manager_dispose | ( | GObject * | object | ) |
| static

Definition at line 409 of file fl_keyboard_manager.cc.

409 {
410 FlKeyboardManager* self = FL_KEYBOARD_MANAGER(object);
411
412 g_cancellable_cancel(self->cancellable);
413
414 g_weak_ref_clear(&self->engine);
415 g_weak_ref_clear(&self->view_delegate);
416
417 self->keycode_to_goals.reset();
418 self->logical_to_mandatory_goals.reset();
419
420 g_clear_object(&self->key_embedder_responder);
421 g_clear_object(&self->key_channel_responder);
422 g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
423 g_ptr_array_free(self->pending_responds, TRUE);
424 g_ptr_array_free(self->pending_redispatches, TRUE);
425 g_clear_object(&self->derived_layout);
426 if (self->keymap_keys_changed_cb_id != 0) {
427 g_signal_handler_disconnect(self->keymap, self->keymap_keys_changed_cb_id);
428 self->keymap_keys_changed_cb_id = 0;
429 }
430 g_clear_object(&self->cancellable);
431
432 G_OBJECT_CLASS(fl_keyboard_manager_parent_class)->dispose(object);
433 }

References TRUE.

Referenced by fl_keyboard_manager_class_init().

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

566 {
567 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), nullptr);
568 if (self->get_pressed_state_handler != nullptr) {
569 return self->get_pressed_state_handler(
570 self->get_pressed_state_handler_user_data);
571 } else {
572 return fl_key_embedder_responder_get_pressed_state(
573 self->key_embedder_responder);
574 }
575 }

References fl_key_embedder_responder_get_pressed_state().

Referenced by 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 522 of file fl_keyboard_manager.cc.

523 {
524 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
525 g_return_val_if_fail(event != nullptr, FALSE);
526
527 guarantee_layout(self, event);
528
529 uint64_t incoming_hash = fl_key_event_hash(event);
530 if (fl_keyboard_manager_remove_redispatched(self, incoming_hash)) {
531 return FALSE;
532 }
533
534 FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(event);
535
536 g_ptr_array_add(self->pending_responds, pending);
537 g_autoptr(FlKeyboardManagerData) data =
538 fl_keyboard_manager_data_new(self, pending);
539 uint64_t specified_logical_key = fl_keyboard_layout_get_logical_key(
540 self->derived_layout, fl_key_event_get_group(event),
541 fl_key_event_get_keycode(event));
542 fl_key_embedder_responder_handle_event(
543 self->key_embedder_responder, event, specified_logical_key,
544 responder_handle_embedder_event_callback, g_object_ref(data));
545 fl_key_channel_responder_handle_event(
546 self->key_channel_responder, event, specified_logical_key,
547 self->cancellable, responder_handle_channel_event_cb, g_object_ref(data));
548
549 return TRUE;
550 }

References fl_key_channel_responder_handle_event(), fl_key_embedder_responder_handle_event(), fl_key_event_get_group(), fl_key_event_get_keycode(), fl_key_event_hash(), fl_keyboard_layout_get_logical_key(), fl_keyboard_manager_data_new(), fl_keyboard_manager_remove_redispatched(), fl_keyboard_pending_event_new(), guarantee_layout(), responder_handle_channel_event_cb(), responder_handle_embedder_event_callback(), and TRUE.

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

439 {
440 self->derived_layout = fl_keyboard_layout_new();
441
442 self->keycode_to_goals =
443 std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
444 self->logical_to_mandatory_goals =
445 std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
446 for (const LayoutGoal& goal : layout_goals) {
447 (*self->keycode_to_goals)[goal.keycode] = &goal;
448 if (goal.mandatory) {
449 (*self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
450 }
451 }
452
453 self->pending_responds = g_ptr_array_new();
454 self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
455
456 self->keymap = gdk_keymap_get_for_display(gdk_display_get_default());
457 self->keymap_keys_changed_cb_id = g_signal_connect_swapped(
458 self->keymap, "keys-changed", G_CALLBACK(keymap_keys_changed_cb), self);
459 self->cancellable = g_cancellable_new();
460 }

References fl_keyboard_layout_new(), if(), keymap_keys_changed_cb(), 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 552 of file fl_keyboard_manager.cc.

552 {
553 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
554 return self->pending_responds->len == 0 &&
555 self->pending_redispatches->len == 0;
556 }

## ◆ fl_keyboard_manager_new()

FlKeyboardManager* fl_keyboard_manager_new | ( | FlEngine * | engine,
|  | FlKeyboardViewDelegate * | view_delegate
| ) |  |

FlKeyboardManager:

Processes keyboard events and cooperate with `TextInputManager`.

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 `TextInputManager`) and are handled synchronously.
- Redispatching: Events are inserted back to the system for redispatching. fl_keyboard_manager_new: @engine: an #FlEngine. @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 462 of file fl_keyboard_manager.cc.

464 {
465 g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(view_delegate), nullptr);
466
467 FlKeyboardManager* self = FL_KEYBOARD_MANAGER(
468 g_object_new(fl_keyboard_manager_get_type(), nullptr));
469
470 g_weak_ref_init(&self->engine, engine);
471 g_weak_ref_init(&self->view_delegate, view_delegate);
472
473 self->key_embedder_responder = fl_key_embedder_responder_new(
474 [](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
475 void* callback_user_data, void* send_key_event_user_data) {
476 FlKeyboardManager* self = FL_KEYBOARD_MANAGER(send_key_event_user_data);
477 if (self->send_key_event_handler != nullptr) {
478 self->send_key_event_handler(event, callback, callback_user_data,
479 self->send_key_event_handler_user_data);
480 } else {
481 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
482 if (engine != nullptr) {
483 typedef struct {
484 FlutterKeyEventCallback callback;
485 void* callback_user_data;
486 } SendKeyEventData;
487 SendKeyEventData* data = g_new0(SendKeyEventData, 1);
488 data->callback = callback;
489 data->callback_user_data = callback_user_data;
490 fl_engine_send_key_event(
491 engine, event, self->cancellable,
492 [](GObject* object, GAsyncResult* result, gpointer user_data) {
493 g_autofree SendKeyEventData* data =
494 static_cast<SendKeyEventData*>(user_data);
495 gboolean handled = FALSE;
496 g_autoptr(GError) error = nullptr;
497 if (!fl_engine_send_key_event_finish(
498 FL_ENGINE(object), result, &handled, &error)) {
499 if (g_error_matches(error, G_IO_ERROR,
500 G_IO_ERROR_CANCELLED)) {
501 return;
502 }
503
504 g_warning("Failed to send key event: %s", error->message);
505 }
506
507 if (data->callback != nullptr) {
508 data->callback(handled, data->callback_user_data);
509 }
510 },
511 data);
512 }
513 }
514 },
515 self);
516 self->key_channel_responder =
517 fl_key_channel_responder_new(fl_engine_get_binary_messenger(engine));
518
519 return self;
520 }

References fl_engine_send_key_event(), fl_key_embedder_responder_new(), if(), and user_data.

Referenced by init_keyboard(), and TEST().

## ◆ fl_keyboard_manager_remove_redispatched()

static bool fl_keyboard_manager_remove_redispatched | ( | FlKeyboardManager * | self,
|  | uint64_t | hash
| ) |  |
| static

Definition at line 218 of file fl_keyboard_manager.cc.

219 {
220 guint result_index;
221 gboolean found = g_ptr_array_find_with_equal_func1(
222 self->pending_redispatches, static_cast<const uint64_t*>(&hash),
223 compare_pending_by_hash, &result_index);
224 if (found) {
225 // The removed object is freed due to `pending_redispatches`'s free_func.
226 g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
227 return TRUE;
228 } else {
229 return FALSE;
230 }
231 }

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

Referenced by fl_keyboard_manager_handle_event().

## ◆ fl_keyboard_manager_set_get_pressed_state_handler()

void fl_keyboard_manager_set_get_pressed_state_handler | ( | FlKeyboardManager * | manager,
|  | FlKeyboardManagerGetPressedStateHandler | get_pressed_state_handler,
|  | gpointer | user_data
| ) |  |

fl_keyboard_manager_set_get_pressed_state_handler: @manager: the #FlKeyboardManager self.

Set the handler for gettting the keyboard state, for testing purposes only.

Definition at line 604 of file fl_keyboard_manager.cc.

607 {
608 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
609 self->get_pressed_state_handler = get_pressed_state_handler;
610 self->get_pressed_state_handler_user_data = user_data;
611 }

References user_data.

Referenced by TEST().

## ◆ fl_keyboard_manager_set_lookup_key_handler()

void fl_keyboard_manager_set_lookup_key_handler | ( | FlKeyboardManager * | manager,
|  | FlKeyboardManagerLookupKeyHandler | lookup_key_handler,
|  | gpointer | user_data
| ) |  |

fl_keyboard_manager_set_lookup_key_handler: @manager: the #FlKeyboardManager self.

Set the handler for key lookup, for testing purposes only.

Definition at line 586 of file fl_keyboard_manager.cc.

589 {
590 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
591 self->lookup_key_handler = lookup_key_handler;
592 self->lookup_key_handler_user_data = user_data;
593 }

References user_data.

## ◆ fl_keyboard_manager_set_redispatch_handler()

void fl_keyboard_manager_set_redispatch_handler | ( | FlKeyboardManager * | manager,
|  | FlKeyboardManagerRedispatchEventHandler | redispatch_handler,
|  | gpointer | user_data
| ) |  |

fl_keyboard_manager_set_redispatch_handler: @manager: the #FlKeyboardManager self.

Set the handler for redispatches, for testing purposes only.

Definition at line 595 of file fl_keyboard_manager.cc.

598 {
599 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
600 self->redispatch_handler = redispatch_handler;
601 self->redispatch_handler_user_data = user_data;
602 }

References user_data.

## ◆ fl_keyboard_manager_set_send_key_event_handler()

void fl_keyboard_manager_set_send_key_event_handler | ( | FlKeyboardManager * | manager,
|  | FlKeyboardManagerSendKeyEventHandler | send_key_event_handler,
|  | gpointer | user_data
| ) |  |

fl_keyboard_manager_set_send_key_event_handler: @manager: the #FlKeyboardManager self.

Set the handler for sending events, for testing purposes only.

Definition at line 577 of file fl_keyboard_manager.cc.

580 {
581 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
582 self->send_key_event_handler = send_key_event_handler;
583 self->send_key_event_handler_user_data = user_data;
584 }

References user_data.

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

560 {
561 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
562 fl_key_embedder_responder_sync_modifiers_if_needed(
563 self->key_embedder_responder, state, event_time);
564 }

References fl_key_embedder_responder_sync_modifiers_if_needed(), and state.

Referenced by sync_modifier_if_needed().

## ◆ G_DECLARE_FINAL_TYPE()

G_DECLARE_FINAL_TYPE | ( | FlKeyboardManagerData | ,
|  | fl_keyboard_manager_data | ,
|  | FL | ,
|  | KEYBOARD_MANAGER_DATA | ,
|  | GObject |
| ) |  |

## ◆ G_DEFINE_TYPE()

G_DEFINE_TYPE | ( | FlKeyboardManager | ,
|  | fl_keyboard_manager | ,
|  | G_TYPE_OBJECT |
| ) |  |

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

188 {
189 guint i;
190 g_return_val_if_fail(haystack != NULL, FALSE);
191 if (equal_func == NULL) {
192 equal_func = g_direct_equal;
193 }
194 for (i = 0; i < haystack->len; i++) {
195 if (equal_func(g_ptr_array_index(haystack, i), needle)) {
196 if (index_ != NULL) {
197 *index_ = i;
198 }
199 return TRUE;
200 }
201 }
202
203 return FALSE;
204 }

References i, and TRUE.

Referenced by fl_keyboard_manager_remove_redispatched().

## ◆ guarantee_layout()

static void guarantee_layout | ( | FlKeyboardManager * | self,
|  | FlKeyEvent * | event
| ) |  |
| static

Definition at line 323 of file fl_keyboard_manager.cc.

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

References convert_key_to_char(), fl_key_event_get_group(), fl_key_event_get_keycode(), fl_keyboard_layout_get_logical_key(), fl_keyboard_layout_has_group(), fl_keyboard_layout_set_logical_key(), LayoutGoal::keycode, layout_goals, and LayoutGoal::logical_key.

Referenced by fl_keyboard_manager_handle_event().

## ◆ keymap_keys_changed_cb()

static void keymap_keys_changed_cb | ( | FlKeyboardManager * | self | ) |
| static

Definition at line 177 of file fl_keyboard_manager.cc.

177 {
178 g_clear_object(&self->derived_layout);
179 self->derived_layout = fl_keyboard_layout_new();
180 }

References fl_keyboard_layout_new().

Referenced by fl_keyboard_manager_init().

## ◆ responder_handle_channel_event_cb()

static void responder_handle_channel_event_cb | ( | GObject * | object,
|  | GAsyncResult * | result,
|  | gpointer | user_data
| ) |  |
| static

Definition at line 280 of file fl_keyboard_manager.cc.

282 {
283 g_autoptr(FlKeyboardManagerData) data = FL_KEYBOARD_MANAGER_DATA(user_data);
284
285 g_autoptr(GError) error = nullptr;
286 gboolean handled;
287 if (!fl_key_channel_responder_handle_event_finish(
288 FL_KEY_CHANNEL_RESPONDER(object), result, &handled, &error)) {
289 if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
290 g_warning("Failed to handle key event in platform: %s", error->message);
291 }
292 return;
293 }
294
295 g_autoptr(FlKeyboardManager) self =
296 FL_KEYBOARD_MANAGER(g_weak_ref_get(&data->manager));
297 if (self == nullptr) {
298 return;
299 }
300
301 fl_keyboard_pending_event_mark_channel_replied(data->pending, handled);
302
303 responder_handle_event_callback(self, data->pending);
304 }

References error, fl_key_channel_responder_handle_event_finish(), fl_keyboard_pending_event_mark_channel_replied(), responder_handle_event_callback(), and user_data.

Referenced by fl_keyboard_manager_handle_event().

## ◆ responder_handle_embedder_event_callback()

static void responder_handle_embedder_event_callback | ( | bool | handled,
|  | gpointer | user_data
| ) |  |
| static

Definition at line 265 of file fl_keyboard_manager.cc.

266 {
267 g_autoptr(FlKeyboardManagerData) data = FL_KEYBOARD_MANAGER_DATA(user_data);
268
269 fl_keyboard_pending_event_mark_embedder_replied(data->pending, handled);
270
271 g_autoptr(FlKeyboardManager) self =
272 FL_KEYBOARD_MANAGER(g_weak_ref_get(&data->manager));
273 if (self == nullptr) {
274 return;
275 }
276
277 responder_handle_event_callback(self, data->pending);
278 }

References fl_keyboard_pending_event_mark_embedder_replied(), responder_handle_event_callback(), and user_data.

Referenced by fl_keyboard_manager_handle_event().

## ◆ responder_handle_event_callback()

static void responder_handle_event_callback | ( | FlKeyboardManager * | self,
|  | FlKeyboardPendingEvent * | pending
| ) |  |
| static

Definition at line 234 of file fl_keyboard_manager.cc.

235 {
236 g_autoptr(FlKeyboardViewDelegate) view_delegate =
237 FL_KEYBOARD_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate));
238 if (view_delegate == nullptr) {
239 return;
240 }
241
242 // All responders have replied.
243 if (fl_keyboard_pending_event_is_complete(pending)) {
244 g_ptr_array_remove(self->pending_responds, pending);
245 bool should_redispatch =
246 !fl_keyboard_pending_event_get_any_handled(pending) &&
247 !fl_keyboard_view_delegate_text_filter_key_press(
248 view_delegate, fl_keyboard_pending_event_get_event(pending));
249 if (should_redispatch) {
250 g_ptr_array_add(self->pending_redispatches, g_object_ref(pending));
251 FlKeyEvent* event = fl_keyboard_pending_event_get_event(pending);
252 if (self->redispatch_handler != nullptr) {
253 self->redispatch_handler(event, self->redispatch_handler_user_data);
254 } else {
255 GdkEventType event_type =
256 gdk_event_get_event_type(fl_key_event_get_origin(event));
257 g_return_if_fail(event_type == GDK_KEY_PRESS ||
258 event_type == GDK_KEY_RELEASE);
259 gdk_event_put(fl_key_event_get_origin(event));
260 }
261 }
262 }
263 }

References fl_key_event_get_origin(), fl_keyboard_pending_event_get_any_handled(), fl_keyboard_pending_event_get_event(), fl_keyboard_pending_event_is_complete(), and fl_keyboard_view_delegate_text_filter_key_press().

Referenced by responder_handle_channel_event_cb(), and responder_handle_embedder_event_callback().

fl_keyboard_pending_event_get_hash
uint64_t fl_keyboard_pending_event_get_hash(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:73
if
if(end==-1)
Definition: fl_accessible_text_field.cc:42
responder_handle_embedder_event_callback
static void responder_handle_embedder_event_callback(bool handled, gpointer user_data)
Definition: fl_keyboard_manager.cc:265
fl_keyboard_pending_event_get_event
FlKeyEvent * fl_keyboard_pending_event_get_event(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:68
fl_key_embedder_responder_handle_event
void fl_key_embedder_responder_handle_event(FlKeyEmbedderResponder *self, FlKeyEvent *event, uint64_t specified_logical_key, FlKeyEmbedderResponderAsyncCallback callback, gpointer user_data)
Definition: fl_key_embedder_responder.cc:835
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:323
convert_key_to_char
static uint16_t convert_key_to_char(FlKeyboardManager *self, guint keycode, gint group, gint level)
Definition: fl_keyboard_manager.cc:306
responder_handle_channel_event_cb
static void responder_handle_channel_event_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_keyboard_manager.cc:280
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:867
LayoutGoal
Definition: key_mapping.h:40
responder_handle_event_callback
static void responder_handle_event_callback(FlKeyboardManager *self, FlKeyboardPendingEvent *pending)
Definition: fl_keyboard_manager.cc:234
fl_key_channel_responder_new
FlKeyChannelResponder * fl_key_channel_responder_new(FlBinaryMessenger *messenger)
Definition: fl_key_channel_responder.cc:59
fl_keyboard_pending_event_mark_channel_replied
void fl_keyboard_pending_event_mark_channel_replied(FlKeyboardPendingEvent *self, gboolean handled)
Definition: fl_keyboard_pending_event.cc:86
i
int i
Definition: fl_socket_accessible.cc:18
LayoutGoal::keycode
uint16_t keycode
Definition: key_mapping.h:42
fl_keyboard_manager_dispose
static void fl_keyboard_manager_dispose(GObject *object)
Definition: fl_keyboard_manager.cc:409
keymap_keys_changed_cb
static void keymap_keys_changed_cb(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:177
LayoutGoal::logical_key
uint64_t logical_key
Definition: key_mapping.h:45
fl_keyboard_manager_remove_redispatched
static bool fl_keyboard_manager_remove_redispatched(FlKeyboardManager *self, uint64_t hash)
Definition: fl_keyboard_manager.cc:218
fl_engine_get_binary_messenger
G_MODULE_EXPORT FlBinaryMessenger * fl_engine_get_binary_messenger(FlEngine *self)
Definition: fl_engine.cc:1203
fl_engine_send_key_event
void fl_engine_send_key_event(FlEngine *self, const FlutterKeyEvent *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:1121
fl_keyboard_layout_get_logical_key
uint64_t fl_keyboard_layout_get_logical_key(FlKeyboardLayout *self, uint8_t group, uint16_t keycode)
Definition: fl_keyboard_layout.cc:65
state
AtkStateType state
Definition: fl_accessible_node.cc:10
fl_key_event_get_origin
GdkEvent * fl_key_event_get_origin(FlKeyEvent *self)
Definition: fl_key_event.cc:109
fl_keyboard_layout_set_logical_key
void fl_keyboard_layout_set_logical_key(FlKeyboardLayout *self, uint8_t group, uint16_t keycode, uint64_t logical_key)
Definition: fl_keyboard_layout.cc:49
compare_pending_by_hash
static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b)
Definition: fl_keyboard_manager.cc:207
fl_keyboard_pending_event_is_complete
gboolean fl_keyboard_pending_event_is_complete(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:100
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
fl_keyboard_pending_event_mark_embedder_replied
void fl_keyboard_pending_event_mark_embedder_replied(FlKeyboardPendingEvent *self, gboolean handled)
Definition: fl_keyboard_pending_event.cc:78
fl_keyboard_pending_event_get_any_handled
gboolean fl_keyboard_pending_event_get_any_handled(FlKeyboardPendingEvent *self)
Definition: fl_keyboard_pending_event.cc:94
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:237
fl_keyboard_manager_data_dispose
static void fl_keyboard_manager_data_dispose(GObject *object)
Definition: fl_keyboard_manager.cc:85
fl_keyboard_layout_new
FlKeyboardLayout * fl_keyboard_layout_new()
Definition: fl_keyboard_layout.cc:40
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
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:185
fl_key_channel_responder_handle_event
void fl_key_channel_responder_handle_event(FlKeyChannelResponder *self, FlKeyEvent *event, uint64_t specified_logical_key, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_key_channel_responder.cc:71
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:14
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:850
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
fl_keyboard_pending_event_new
FlKeyboardPendingEvent * fl_keyboard_pending_event_new(FlKeyEvent *event)
Definition: fl_keyboard_pending_event.cc:58
fl_key_channel_responder_handle_event_finish
gboolean fl_key_channel_responder_handle_event_finish(FlKeyChannelResponder *self, GAsyncResult *result, gboolean *handled, GError **error)
Definition: fl_key_channel_responder.cc:139
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_keyboard_layout_has_group
gboolean fl_keyboard_layout_has_group(FlKeyboardLayout *self, uint8_t group)
Definition: fl_keyboard_layout.cc:45
fl_keyboard_manager_data_new
static FlKeyboardManagerData * fl_keyboard_manager_data_new(FlKeyboardManager *manager, FlKeyboardPendingEvent *pending)
Definition: fl_keyboard_manager.cc:102