10 #include "flutter/shell/platform/embedder/embedder.h"
17 .struct_size =
sizeof(FlutterKeyEvent),
19 .
type = kFlutterKeyEventTypeDown,
54 constexpr uint64_t lower_a = 0x61;
55 constexpr uint64_t upper_a = 0x41;
56 constexpr uint64_t upper_z = 0x5a;
58 constexpr uint64_t lower_a_grave = 0xe0;
59 constexpr uint64_t upper_a_grave = 0xc0;
60 constexpr uint64_t upper_thorn = 0xde;
61 constexpr uint64_t division = 0xf7;
64 if (n >= upper_a && n <= upper_z) {
65 return n - upper_a + lower_a;
69 if (n >= upper_a_grave && n <= upper_thorn && n != division) {
70 return n - upper_a_grave + lower_a_grave;
83 #define FL_TYPE_EMBEDDER_USER_DATA fl_key_embedder_user_data_get_type()
85 fl_key_embedder_user_data,
87 KEY_EMBEDDER_USER_DATA,
97 G_DEFINE_TYPE(FlKeyEmbedderUserData, fl_key_embedder_user_data, G_TYPE_OBJECT)
102 FlKeyEmbedderUserDataClass* klass) {
111 g_return_if_fail(FL_IS_KEY_EMBEDDER_USER_DATA(
object));
120 FlKeyEmbedderUserData*
self = FL_KEY_EMBEDDER_USER_DATA(
133 kStateLogicUndecided,
136 } StateLogicInferrence;
201 FlKeyResponderInterface* iface);
204 #define FL_TYPE_EMBEDDER_RESPONDER_USER_DATA \
205 fl_key_embedder_responder_get_type()
207 FlKeyEmbedderResponder,
208 fl_key_embedder_responder,
214 FlKeyResponder* responder,
221 FlKeyResponderInterface* iface) {
227 FlKeyEmbedderResponderClass* klass) {
236 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
object);
238 g_clear_pointer(&self->pressing_records, g_hash_table_unref);
239 g_clear_pointer(&self->mapping_records, g_hash_table_unref);
240 g_clear_pointer(&self->modifier_bit_to_checked_keys, g_hash_table_unref);
241 g_clear_pointer(&self->lock_bit_to_checked_keys, g_hash_table_unref);
242 g_clear_pointer(&self->logical_key_to_lock_bit, g_hash_table_unref);
244 G_OBJECT_CLASS(fl_key_embedder_responder_parent_class)->dispose(
object);
256 GHashTable* table =
reinterpret_cast<GHashTable*
>(
user_data);
257 g_hash_table_insert(table,
259 GUINT_TO_POINTER(lock_bit));
265 void* send_key_event_user_data) {
266 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
270 self->send_key_event_user_data = send_key_event_user_data;
272 self->pressing_records = g_hash_table_new(g_direct_hash, g_direct_equal);
273 self->mapping_records = g_hash_table_new(g_direct_hash, g_direct_equal);
274 self->lock_records = 0;
275 self->caps_lock_state_logic_inferrence = kStateLogicUndecided;
277 self->modifier_bit_to_checked_keys =
278 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
281 self->lock_bit_to_checked_keys =
282 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
285 self->logical_key_to_lock_bit =
286 g_hash_table_new(g_direct_hash, g_direct_equal);
287 g_hash_table_foreach(self->lock_bit_to_checked_keys,
289 self->logical_key_to_lock_bit);
303 return found->second;
309 guint keyval =
event->keyval;
312 return found->second;
329 gunichar unicodeChar = gdk_keyval_to_unicode(
event->
keyval);
331 gchar*
result = g_ucs4_to_utf8(&unicodeChar, 1, NULL, &items_written, NULL);
332 if (items_written == 0) {
344 g_autoptr(FlKeyEmbedderUserData) data = FL_KEY_EMBEDDER_USER_DATA(
user_data);
346 g_return_if_fail(data->callback !=
nullptr);
348 data->callback(handled, data->user_data);
353 FlutterKeyEventType
type,
357 FlutterKeyEvent out_event;
358 out_event.struct_size =
sizeof(out_event);
359 out_event.timestamp = timestamp;
360 out_event.type =
type;
361 out_event.physical = physical;
362 out_event.logical = logical;
363 out_event.character =
nullptr;
364 out_event.synthesized =
true;
365 self->sent_any_events =
true;
366 self->send_key_event(&out_event,
nullptr,
nullptr,
367 self->send_key_event_user_data);
375 FlKeyEmbedderResponder*
self;
377 uint64_t event_logical_key;
380 } SyncStateLoopContext;
385 bool known_modifier_physical_key;
386 uint64_t logical_key;
387 uint64_t physical_key_from_event;
388 uint64_t corrected_physical_key;
389 } ModifierLogicalToPhysicalContext;
399 uint64_t physical_key,
400 uint64_t logical_key) {
401 if (logical_key != 0) {
404 g_hash_table_insert(self->pressing_records,
410 g_hash_table_remove(self->pressing_records,
420 uint64_t logical_key,
425 const guint mode_bit = GPOINTER_TO_UINT(g_hash_table_lookup(
428 self->lock_records ^= mode_bit;
433 uint64_t physical_key,
434 uint64_t logical_key) {
446 SyncStateLoopContext* context =
447 reinterpret_cast<SyncStateLoopContext*
>(
user_data);
451 const guint modifier_bit = GPOINTER_TO_INT(key);
452 FlKeyEmbedderResponder*
self = context->self;
461 const uint64_t logical_keys[] = {
467 const bool any_pressed_by_state = (context->state & modifier_bit) != 0;
469 bool any_pressed_by_record =
false;
478 for (guint logical_key_idx = 0; logical_key_idx <
length; logical_key_idx++) {
479 const uint64_t logical_key = logical_keys[logical_key_idx];
480 g_return_if_fail(logical_key != 0);
481 const uint64_t pressing_physical_key =
483 const bool this_key_pressed_before_event = pressing_physical_key != 0;
485 any_pressed_by_record =
486 any_pressed_by_record || this_key_pressed_before_event;
488 if (this_key_pressed_before_event && !any_pressed_by_state) {
489 const uint64_t recorded_physical_key =
493 g_return_if_fail(recorded_physical_key != 0);
495 const uint64_t recorded_logical_key =
498 recorded_physical_key, recorded_logical_key,
505 if (any_pressed_by_state && !any_pressed_by_record) {
507 const uint64_t recorded_physical_key =
514 const uint64_t physical_key = recorded_physical_key != 0
515 ? recorded_physical_key
517 if (recorded_physical_key == 0) {
521 logical_key, context->timestamp);
529 constexpr
int stage_by_record_index[] = {
535 return stage_by_record_index[(is_down << 1) + is_enabled];
543 bool reverse_state_logic) {
545 return reverse_state_logic ? 2 : 0;
548 return reverse_state_logic ? 0 : 2;
550 return stage_by_record;
556 g_return_val_if_fail(stage_by_record >= 0 && stage_by_record < 4,
561 if (stage_by_record == 0) {
564 return stage_by_record;
583 FlKeyEmbedderResponder*
self,
585 bool enabled_by_state,
586 int stage_by_record) {
587 if (self->caps_lock_state_logic_inferrence != kStateLogicUndecided) {
590 if (!is_down_event) {
594 stage_by_record, is_down_event, enabled_by_state,
false);
595 if ((stage_by_event == 0 && stage_by_record == 2) ||
596 (stage_by_event == 2 && stage_by_record == 0)) {
597 self->caps_lock_state_logic_inferrence = kStateLogicReversed;
599 self->caps_lock_state_logic_inferrence = kStateLogicNormal;
612 SyncStateLoopContext* context =
613 reinterpret_cast<SyncStateLoopContext*
>(
user_data);
617 guint modifier_bit = GPOINTER_TO_INT(key);
618 FlKeyEmbedderResponder*
self = context->self;
621 const uint64_t recorded_physical_key =
630 const uint64_t physical_key = recorded_physical_key != 0
631 ? recorded_physical_key
653 const uint64_t pressed_logical_key =
654 recorded_physical_key == 0
658 g_return_if_fail(pressed_logical_key == 0 ||
659 pressed_logical_key == logical_key);
661 pressed_logical_key != 0, (self->lock_records & modifier_bit) != 0);
663 const bool enabled_by_state = (context->state & modifier_bit) != 0;
664 const bool this_key_is_event_key = logical_key == context->event_logical_key;
665 if (this_key_is_event_key && checked_key->
is_caps_lock) {
667 enabled_by_state, stage_by_record);
668 g_return_if_fail(self->caps_lock_state_logic_inferrence !=
669 kStateLogicUndecided);
671 const bool reverse_state_logic =
673 self->caps_lock_state_logic_inferrence == kStateLogicReversed;
674 const int stage_by_event =
675 this_key_is_event_key
677 enabled_by_state, reverse_state_logic)
682 constexpr
int kNumStages = 4;
683 const int destination_stage = stage_by_event >= stage_by_record
685 : stage_by_event + kNumStages;
687 g_return_if_fail(stage_by_record <= destination_stage);
688 if (stage_by_record == destination_stage) {
691 for (
int current_stage = stage_by_record; current_stage < destination_stage;
692 current_stage += 1) {
693 if (current_stage == 9) {
697 const int standard_current_stage = current_stage % kNumStages;
698 const bool is_down_event =
699 standard_current_stage == 0 || standard_current_stage == 2;
700 if (is_down_event && recorded_physical_key == 0) {
703 FlutterKeyEventType
type =
704 is_down_event ? kFlutterKeyEventTypeDown : kFlutterKeyEventTypeUp;
719 ModifierLogicalToPhysicalContext* context =
720 reinterpret_cast<ModifierLogicalToPhysicalContext*
>(
user_data);
725 context->known_modifier_physical_key =
true;
736 ModifierLogicalToPhysicalContext* context =
737 reinterpret_cast<ModifierLogicalToPhysicalContext*
>(
user_data);
748 GHashTable* modifier_bit_to_checked_keys,
749 uint64_t physical_key_from_event,
750 uint64_t logical_key) {
751 ModifierLogicalToPhysicalContext logical_to_physical_context;
752 logical_to_physical_context.known_modifier_physical_key =
false;
753 logical_to_physical_context.physical_key_from_event = physical_key_from_event;
754 logical_to_physical_context.logical_key = logical_key;
757 logical_to_physical_context.corrected_physical_key = physical_key_from_event;
760 g_hash_table_foreach(modifier_bit_to_checked_keys,
762 &logical_to_physical_context);
766 if (logical_to_physical_context.known_modifier_physical_key) {
767 g_hash_table_foreach(modifier_bit_to_checked_keys,
769 &logical_to_physical_context);
772 return logical_to_physical_context.corrected_physical_key;
776 FlKeyResponder* responder,
781 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(responder);
783 g_return_if_fail(
event !=
nullptr);
784 g_return_if_fail(
callback !=
nullptr);
791 self->modifier_bit_to_checked_keys, physical_key_from_event, logical_key);
793 const bool is_down_event =
event->is_press;
795 SyncStateLoopContext sync_state_context;
796 sync_state_context.self =
self;
797 sync_state_context.state =
event->state;
798 sync_state_context.timestamp = timestamp;
799 sync_state_context.is_down = is_down_event;
800 sync_state_context.event_logical_key = logical_key;
803 g_hash_table_foreach(self->lock_bit_to_checked_keys,
807 g_hash_table_foreach(self->modifier_bit_to_checked_keys,
809 &sync_state_context);
812 const uint64_t last_logical_record =
815 FlutterKeyEvent out_event;
816 out_event.struct_size =
sizeof(out_event);
817 out_event.timestamp = timestamp;
818 out_event.physical = physical_key;
820 last_logical_record != 0 ? last_logical_record : logical_key;
821 out_event.character =
nullptr;
822 out_event.synthesized =
false;
824 g_autofree
char* character_to_free =
nullptr;
826 if (last_logical_record) {
829 out_event.type = kFlutterKeyEventTypeRepeat;
831 out_event.type = kFlutterKeyEventTypeDown;
834 out_event.character = character_to_free;
836 if (!last_logical_record) {
843 out_event.type = kFlutterKeyEventTypeUp;
847 if (out_event.type != kFlutterKeyEventTypeRepeat) {
854 FlKeyEmbedderUserData* response_data =
856 self->sent_any_events =
true;
858 self->send_key_event_user_data);
863 FlKeyResponder* responder,
868 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(responder);
869 self->sent_any_events =
false;
872 if (!self->sent_any_events) {
873 self->send_key_event(&
kEmptyEvent,
nullptr,
nullptr,
874 self->send_key_event_user_data);
879 FlKeyEmbedderResponder* responder,
884 SyncStateLoopContext sync_state_context;
885 sync_state_context.self = responder;
886 sync_state_context.state =
state;
887 sync_state_context.timestamp = timestamp;
890 g_hash_table_foreach(responder->modifier_bit_to_checked_keys,
892 &sync_state_context);
896 FlKeyEmbedderResponder*
self) {
897 return self->pressing_records;