53 constexpr uint64_t lower_a = 0x61;
54 constexpr uint64_t upper_a = 0x41;
55 constexpr uint64_t upper_z = 0x5a;
57 constexpr uint64_t lower_a_grave = 0xe0;
58 constexpr uint64_t upper_a_grave = 0xc0;
59 constexpr uint64_t upper_thorn = 0xde;
60 constexpr uint64_t division = 0xf7;
63 if (n >= upper_a && n <= upper_z) {
64 return n - upper_a + lower_a;
68 if (n >= upper_a_grave && n <= upper_thorn && n != division) {
69 return n - upper_a_grave + lower_a_grave;
78 STATE_LOGIC_INFERRENCE_UNDECIDED,
79 STATE_LOGIC_INFERRENCE_NORMAL,
80 STATE_LOGIC_INFERRENCE_REVERSED,
81} StateLogicInferrence;
149G_DEFINE_TYPE(FlKeyEmbedderResponder, fl_key_embedder_responder, G_TYPE_OBJECT)
153 FlKeyEmbedderResponderClass* klass) {
159 self->cancellable = g_cancellable_new();
164 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
object);
166 g_cancellable_cancel(
self->cancellable);
168 g_weak_ref_clear(&
self->engine);
169 g_clear_pointer(&
self->pressing_records, g_hash_table_unref);
170 g_clear_pointer(&
self->mapping_records, g_hash_table_unref);
171 g_clear_pointer(&
self->modifier_bit_to_checked_keys, g_hash_table_unref);
172 g_clear_pointer(&
self->lock_bit_to_checked_keys, g_hash_table_unref);
173 g_clear_pointer(&
self->logical_key_to_lock_bit, g_hash_table_unref);
174 g_clear_object(&
self->cancellable);
176 G_OBJECT_CLASS(fl_key_embedder_responder_parent_class)->dispose(
object);
181 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
182 g_object_new(fl_key_embedder_responder_get_type(),
nullptr));
186 self->pressing_records = g_hash_table_new(g_direct_hash, g_direct_equal);
187 self->mapping_records = g_hash_table_new(g_direct_hash, g_direct_equal);
188 self->lock_records = 0;
189 self->caps_lock_state_logic_inferrence = STATE_LOGIC_INFERRENCE_UNDECIDED;
191 self->modifier_bit_to_checked_keys =
192 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
195 self->lock_bit_to_checked_keys =
196 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
200 self->logical_key_to_lock_bit =
201 g_hash_table_new(g_direct_hash, g_direct_equal);
203 g_hash_table_iter_init(&iter,
self->lock_bit_to_checked_keys);
205 while (g_hash_table_iter_next(&iter, &
key, &
value)) {
206 guint lock_bit = GPOINTER_TO_UINT(
key);
211 GUINT_TO_POINTER(lock_bit));
224 return found->second;
233 return found->second;
253 gchar* result = g_ucs4_to_utf8(&unicodeChar, 1, NULL, &items_written, NULL);
254 if (items_written == 0) {
255 if (result != NULL) {
277 self->sent_any_events =
true;
291 uint64_t physical_key,
292 uint64_t logical_key) {
293 if (logical_key != 0) {
302 g_hash_table_remove(
self->pressing_records,
312 uint64_t logical_key,
317 const guint mode_bit = GPOINTER_TO_UINT(g_hash_table_lookup(
320 self->lock_records ^= mode_bit;
325 uint64_t physical_key,
326 uint64_t logical_key) {
337 g_hash_table_iter_init(&iter,
self->modifier_bit_to_checked_keys);
339 while (g_hash_table_iter_next(&iter, &
key, &
value)) {
340 guint modifier_bit = GPOINTER_TO_UINT(
key);
352 const uint64_t logical_keys[] = {
358 const bool any_pressed_by_state = (state & modifier_bit) != 0;
360 bool any_pressed_by_record =
false;
371 for (guint logical_key_idx = 0; logical_key_idx <
length;
373 const uint64_t logical_key = logical_keys[logical_key_idx];
374 g_return_if_fail(logical_key != 0);
375 const uint64_t pressing_physical_key =
377 const bool this_key_pressed_before_event = pressing_physical_key != 0;
379 any_pressed_by_record =
380 any_pressed_by_record || this_key_pressed_before_event;
382 if (this_key_pressed_before_event && !any_pressed_by_state) {
383 const uint64_t recorded_physical_key =
387 g_return_if_fail(recorded_physical_key != 0);
389 const uint64_t recorded_logical_key =
392 recorded_physical_key, recorded_logical_key,
399 if (any_pressed_by_state && !any_pressed_by_record) {
401 const uint64_t recorded_physical_key =
408 const uint64_t physical_key = recorded_physical_key != 0
409 ? recorded_physical_key
411 if (recorded_physical_key == 0) {
415 logical_key, timestamp);
424 constexpr int stage_by_record_index[] = {
430 return stage_by_record_index[(is_down << 1) +
is_enabled];
438 bool reverse_state_logic) {
440 return reverse_state_logic ? 2 : 0;
443 return reverse_state_logic ? 0 : 2;
445 return stage_by_record;
451 g_return_val_if_fail(stage_by_record >= 0 && stage_by_record < 4,
456 if (stage_by_record == 0) {
459 return stage_by_record;
478 FlKeyEmbedderResponder*
self,
480 bool enabled_by_state,
481 int stage_by_record) {
482 if (
self->caps_lock_state_logic_inferrence !=
483 STATE_LOGIC_INFERRENCE_UNDECIDED) {
486 if (!is_down_event) {
490 stage_by_record, is_down_event, enabled_by_state,
false);
491 if ((stage_by_event == 0 && stage_by_record == 2) ||
492 (stage_by_event == 2 && stage_by_record == 0)) {
493 self->caps_lock_state_logic_inferrence = STATE_LOGIC_INFERRENCE_REVERSED;
495 self->caps_lock_state_logic_inferrence = STATE_LOGIC_INFERRENCE_NORMAL;
507 uint64_t event_logical_key) {
509 g_hash_table_iter_init(&iter,
self->lock_bit_to_checked_keys);
511 while (g_hash_table_iter_next(&iter, &
key, &
value)) {
512 guint modifier_bit = GPOINTER_TO_UINT(
key);
517 const uint64_t recorded_physical_key =
526 const uint64_t physical_key = recorded_physical_key != 0
527 ? recorded_physical_key
549 const uint64_t pressed_logical_key =
550 recorded_physical_key == 0
554 g_return_if_fail(pressed_logical_key == 0 ||
555 pressed_logical_key == logical_key);
557 pressed_logical_key != 0, (
self->lock_records & modifier_bit) != 0);
559 const bool enabled_by_state = (state & modifier_bit) != 0;
560 const bool this_key_is_event_key = logical_key == event_logical_key;
561 if (this_key_is_event_key && checked_key->
is_caps_lock) {
564 g_return_if_fail(
self->caps_lock_state_logic_inferrence !=
565 STATE_LOGIC_INFERRENCE_UNDECIDED);
567 const bool reverse_state_logic =
569 STATE_LOGIC_INFERRENCE_REVERSED;
570 const int stage_by_event =
571 this_key_is_event_key
573 enabled_by_state, reverse_state_logic)
578 constexpr int kNumStages = 4;
579 const int destination_stage = stage_by_event >= stage_by_record
581 : stage_by_event + kNumStages;
583 g_return_if_fail(stage_by_record <= destination_stage);
584 for (
int current_stage = stage_by_record;
585 current_stage < destination_stage && current_stage < 9;
586 current_stage += 1) {
587 const int standard_current_stage = current_stage % kNumStages;
588 const bool is_down_event =
589 standard_current_stage == 0 || standard_current_stage == 2;
590 if (is_down_event && recorded_physical_key == 0) {
596 is_down_event ? logical_key : 0);
604 GHashTable* modifier_bit_to_checked_keys,
605 uint64_t physical_key_from_event,
606 uint64_t logical_key) {
609 uint64_t corrected_physical_key = physical_key_from_event;
612 bool known_modifier_physical_key =
false;
614 g_hash_table_iter_init(&iter, modifier_bit_to_checked_keys);
616 while (g_hash_table_iter_next(&iter,
nullptr, &
value)) {
620 known_modifier_physical_key =
true;
626 if (known_modifier_physical_key) {
627 g_hash_table_iter_init(&iter, modifier_bit_to_checked_keys);
628 while (g_hash_table_iter_next(&iter,
nullptr, &
value)) {
638 return corrected_physical_key;
642 FlKeyEmbedderResponder* responder,
644 uint64_t specified_logical_key,
646 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(responder);
648 const uint64_t logical_key = specified_logical_key != 0
649 ? specified_logical_key
653 self->modifier_bit_to_checked_keys, physical_key_from_event, logical_key);
665 const uint64_t last_logical_record =
673 last_logical_record != 0 ? last_logical_record : logical_key;
677 g_autofree
char* character_to_free =
nullptr;
679 if (last_logical_record) {
689 if (!last_logical_record) {
693 gboolean* return_value = g_new0(gboolean, 1);
694 *return_value =
TRUE;
695 g_task_return_pointer(task, return_value, g_free);
709 self->sent_any_events =
true;
714 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
715 g_autoptr(GTask) task = G_TASK(user_data);
718 g_autoptr(GError) error = nullptr;
719 if (!fl_engine_send_key_event_finish(FL_ENGINE(object), result,
721 if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
724 g_warning(
"Failed to handle key event: %s", error->message);
728 gboolean* return_value = g_new0(gboolean, 1);
729 *return_value = handled;
730 g_task_return_pointer(task, return_value, g_free);
738 uint64_t specified_logical_key,
739 GCancellable* cancellable,
744 self->sent_any_events =
false;
746 specified_logical_key, task);
747 if (!
self->sent_any_events) {
757 FlKeyEmbedderResponder*
self,
758 GAsyncResult* result,
761 g_return_val_if_fail(g_task_is_valid(result,
self), FALSE);
763 g_autofree gboolean* return_value =
764 static_cast<gboolean*
>(g_task_propagate_pointer(G_TASK(result),
error));
765 if (return_value ==
nullptr) {
769 *handled = *return_value;
774 FlKeyEmbedderResponder*
self,
777 g_return_if_fail(FL_IS_KEY_EMBEDDER_RESPONDER(
self));
783 FlKeyEmbedderResponder*
self) {
784 return self->pressing_records;
@ kFlutterKeyEventTypeDown
@ kFlutterKeyEventTypeRepeat
g_autoptr(FlEngine) engine
static gboolean is_enabled(FlutterSemanticsFlags flags)
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
void fl_engine_send_key_event(FlEngine *self, const FlutterKeyEvent *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
static const FlutterKeyEvent kEmptyEvent
static uint64_t event_to_logical_key(FlKeyEvent *event)
static void synchronize_pressed_states(FlKeyEmbedderResponder *self, guint state, double timestamp)
static gboolean hash_table_find_equal_value(gpointer key, gpointer value, gpointer user_data)
FlKeyEmbedderResponder * fl_key_embedder_responder_new(FlEngine *engine)
GHashTable * fl_key_embedder_responder_get_pressed_state(FlKeyEmbedderResponder *self)
static void fl_key_embedder_responder_dispose(GObject *object)
static void update_caps_lock_state_logic_inferrence(FlKeyEmbedderResponder *self, bool is_down_event, bool enabled_by_state, int stage_by_record)
static uint64_t apply_id_plane(uint64_t logical_id, uint64_t plane)
static uint64_t event_to_physical_key(FlKeyEvent *event)
static uint64_t corrected_modifier_physical_key(GHashTable *modifier_bit_to_checked_keys, uint64_t physical_key_from_event, uint64_t logical_key)
static void fl_key_embedder_responder_init(FlKeyEmbedderResponder *self)
static void synthesize_simple_event(FlKeyEmbedderResponder *self, FlutterKeyEventType type, uint64_t physical, uint64_t logical, double timestamp)
void fl_key_embedder_responder_sync_modifiers_if_needed(FlKeyEmbedderResponder *self, guint state, double event_time)
static void update_mapping_record(FlKeyEmbedderResponder *self, uint64_t physical_key, uint64_t logical_key)
static void fl_key_embedder_responder_handle_event_impl(FlKeyEmbedderResponder *responder, FlKeyEvent *event, uint64_t specified_logical_key, GTask *task)
static uint64_t lookup_hash_table(GHashTable *table, uint64_t key)
static void possibly_update_lock_bit(FlKeyEmbedderResponder *self, uint64_t logical_key, bool is_down)
static uint64_t event_to_timestamp(FlKeyEvent *event)
static void update_pressing_state(FlKeyEmbedderResponder *self, uint64_t physical_key, uint64_t logical_key)
void fl_key_embedder_responder_handle_event(FlKeyEmbedderResponder *self, FlKeyEvent *event, uint64_t specified_logical_key, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
static int find_stage_by_others_event(int stage_by_record, bool is_state_on)
gboolean fl_key_embedder_responder_handle_event_finish(FlKeyEmbedderResponder *self, GAsyncResult *result, gboolean *handled, GError **error)
static uint64_t to_lower(uint64_t n)
static int find_stage_by_self_event(int stage_by_record, bool is_down_event, bool is_state_on, bool reverse_state_logic)
constexpr uint64_t kMicrosecondsPerMillisecond
static char * event_to_character(FlKeyEvent *event)
static void fl_key_embedder_responder_class_init(FlKeyEmbedderResponderClass *klass)
static uint64_t reverse_lookup_hash_table(GHashTable *table, uint64_t value)
static int find_stage_by_record(bool is_down, bool is_enabled)
static void synchronize_lock_states(FlKeyEmbedderResponder *self, guint state, double timestamp, bool is_down, uint64_t event_logical_key)
guint16 fl_key_event_get_keycode(FlKeyEvent *self)
gboolean fl_key_event_get_is_press(FlKeyEvent *self)
GdkModifierType fl_key_event_get_state(FlKeyEvent *self)
guint fl_key_event_get_keyval(FlKeyEvent *self)
guint32 fl_key_event_get_time(FlKeyEvent *self)
std::map< uint64_t, uint64_t > xkb_to_physical_key_map
void initialize_modifier_bit_to_checked_keys(GHashTable *table)
void initialize_lock_bit_to_checked_keys(GHashTable *table)
std::map< uint64_t, uint64_t > gtk_keyval_to_logical_key_map
gpointer uint64_to_gpointer(uint64_t number)
uint64_t gpointer_to_uint64(gpointer pointer)
g_hash_table_insert(self->handlers, g_strdup(channel), handler_new(handler, user_data, destroy_notify))
const uint8_t uint32_t uint32_t GError ** error
FlutterDesktopBinaryReply callback
const uint64_t kValueMask
const uint64_t kUnicodePlane
impeller::ShaderType type
GCancellable * cancellable
GHashTable * logical_key_to_lock_bit
GHashTable * mapping_records
GHashTable * modifier_bit_to_checked_keys
GHashTable * pressing_records
GHashTable * lock_bit_to_checked_keys
StateLogicInferrence caps_lock_state_logic_inferrence
uint64_t primary_physical_key
uint64_t primary_logical_key
uint64_t secondary_logical_key
size_t struct_size
The size of this struct. Must be sizeof(FlutterKeyEvent).
FlutterKeyEventType type
The event kind.