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;
200 FlKeyResponderInterface* iface);
203 #define FL_TYPE_EMBEDDER_RESPONDER_USER_DATA \
204 fl_key_embedder_responder_get_type()
206 FlKeyEmbedderResponder,
207 fl_key_embedder_responder,
213 FlKeyResponder* responder,
220 FlKeyResponderInterface* iface) {
226 FlKeyEmbedderResponderClass* klass) {
235 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
object);
237 g_clear_pointer(&
self->pressing_records, g_hash_table_unref);
238 g_clear_pointer(&
self->mapping_records, g_hash_table_unref);
239 g_clear_pointer(&
self->modifier_bit_to_checked_keys, g_hash_table_unref);
240 g_clear_pointer(&
self->lock_bit_to_checked_keys, g_hash_table_unref);
241 g_clear_pointer(&
self->logical_key_to_lock_bit, g_hash_table_unref);
243 G_OBJECT_CLASS(fl_key_embedder_responder_parent_class)->dispose(
object);
255 GHashTable* table =
reinterpret_cast<GHashTable*
>(
user_data);
256 g_hash_table_insert(table,
258 GUINT_TO_POINTER(lock_bit));
264 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
269 self->pressing_records = g_hash_table_new(g_direct_hash, g_direct_equal);
270 self->mapping_records = g_hash_table_new(g_direct_hash, g_direct_equal);
271 self->lock_records = 0;
272 self->caps_lock_state_logic_inferrence = kStateLogicUndecided;
274 self->modifier_bit_to_checked_keys =
275 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
278 self->lock_bit_to_checked_keys =
279 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
282 self->logical_key_to_lock_bit =
283 g_hash_table_new(g_direct_hash, g_direct_equal);
284 g_hash_table_foreach(
self->lock_bit_to_checked_keys,
286 self->logical_key_to_lock_bit);
300 return found->second;
306 guint keyval =
event->keyval;
309 return found->second;
326 gunichar unicodeChar = gdk_keyval_to_unicode(
event->
keyval);
328 gchar*
result = g_ucs4_to_utf8(&unicodeChar, 1, NULL, &items_written, NULL);
329 if (items_written == 0) {
341 g_autoptr(FlKeyEmbedderUserData) data = FL_KEY_EMBEDDER_USER_DATA(
user_data);
343 g_return_if_fail(data->callback !=
nullptr);
345 data->callback(handled, data->user_data);
350 FlutterKeyEventType type,
354 FlutterKeyEvent out_event;
355 out_event.struct_size =
sizeof(out_event);
356 out_event.timestamp = timestamp;
357 out_event.type = type;
358 out_event.physical = physical;
359 out_event.logical = logical;
360 out_event.character =
nullptr;
361 out_event.synthesized =
true;
362 self->sent_any_events =
true;
363 self->send_key_event(&out_event,
nullptr,
nullptr);
371 FlKeyEmbedderResponder*
self;
373 uint64_t event_logical_key;
376 } SyncStateLoopContext;
381 bool known_modifier_physical_key;
382 uint64_t logical_key;
383 uint64_t physical_key_from_event;
384 uint64_t corrected_physical_key;
385 } ModifierLogicalToPhysicalContext;
395 uint64_t physical_key,
396 uint64_t logical_key) {
397 if (logical_key != 0) {
400 g_hash_table_insert(
self->pressing_records,
406 g_hash_table_remove(
self->pressing_records,
416 uint64_t logical_key,
421 const guint mode_bit = GPOINTER_TO_UINT(g_hash_table_lookup(
424 self->lock_records ^= mode_bit;
429 uint64_t physical_key,
430 uint64_t logical_key) {
442 SyncStateLoopContext* context =
443 reinterpret_cast<SyncStateLoopContext*
>(
user_data);
447 const guint modifier_bit = GPOINTER_TO_INT(key);
448 FlKeyEmbedderResponder*
self = context->self;
457 const uint64_t logical_keys[] = {
463 const bool any_pressed_by_state = (context->state & modifier_bit) != 0;
465 bool any_pressed_by_record =
false;
474 for (guint logical_key_idx = 0; logical_key_idx < length; logical_key_idx++) {
475 const uint64_t logical_key = logical_keys[logical_key_idx];
476 g_return_if_fail(logical_key != 0);
477 const uint64_t pressing_physical_key =
479 const bool this_key_pressed_before_event = pressing_physical_key != 0;
481 any_pressed_by_record =
482 any_pressed_by_record || this_key_pressed_before_event;
484 if (this_key_pressed_before_event && !any_pressed_by_state) {
485 const uint64_t recorded_physical_key =
489 g_return_if_fail(recorded_physical_key != 0);
491 const uint64_t recorded_logical_key =
494 recorded_physical_key, recorded_logical_key,
501 if (any_pressed_by_state && !any_pressed_by_record) {
503 const uint64_t recorded_physical_key =
510 const uint64_t physical_key = recorded_physical_key != 0
511 ? recorded_physical_key
513 if (recorded_physical_key == 0) {
517 logical_key, context->timestamp);
525 constexpr
int stage_by_record_index[] = {
531 return stage_by_record_index[(is_down << 1) + is_enabled];
539 bool reverse_state_logic) {
541 return reverse_state_logic ? 2 : 0;
544 return reverse_state_logic ? 0 : 2;
546 return stage_by_record;
552 g_return_val_if_fail(stage_by_record >= 0 && stage_by_record < 4,
557 if (stage_by_record == 0) {
560 return stage_by_record;
579 FlKeyEmbedderResponder*
self,
581 bool enabled_by_state,
582 int stage_by_record) {
583 if (
self->caps_lock_state_logic_inferrence != kStateLogicUndecided) {
586 if (!is_down_event) {
590 stage_by_record, is_down_event, enabled_by_state,
false);
591 if ((stage_by_event == 0 && stage_by_record == 2) ||
592 (stage_by_event == 2 && stage_by_record == 0)) {
593 self->caps_lock_state_logic_inferrence = kStateLogicReversed;
595 self->caps_lock_state_logic_inferrence = kStateLogicNormal;
608 SyncStateLoopContext* context =
609 reinterpret_cast<SyncStateLoopContext*
>(
user_data);
613 guint modifier_bit = GPOINTER_TO_INT(key);
614 FlKeyEmbedderResponder*
self = context->self;
617 const uint64_t recorded_physical_key =
626 const uint64_t physical_key = recorded_physical_key != 0
627 ? recorded_physical_key
649 const uint64_t pressed_logical_key =
650 recorded_physical_key == 0
654 g_return_if_fail(pressed_logical_key == 0 ||
655 pressed_logical_key == logical_key);
657 pressed_logical_key != 0, (
self->lock_records & modifier_bit) != 0);
659 const bool enabled_by_state = (context->state & modifier_bit) != 0;
660 const bool this_key_is_event_key = logical_key == context->event_logical_key;
661 if (this_key_is_event_key && checked_key->
is_caps_lock) {
663 enabled_by_state, stage_by_record);
664 g_return_if_fail(
self->caps_lock_state_logic_inferrence !=
665 kStateLogicUndecided);
667 const bool reverse_state_logic =
669 self->caps_lock_state_logic_inferrence == kStateLogicReversed;
670 const int stage_by_event =
671 this_key_is_event_key
673 enabled_by_state, reverse_state_logic)
678 constexpr
int kNumStages = 4;
679 const int destination_stage = stage_by_event >= stage_by_record
681 : stage_by_event + kNumStages;
683 g_return_if_fail(stage_by_record <= destination_stage);
684 if (stage_by_record == destination_stage) {
687 for (
int current_stage = stage_by_record; current_stage < destination_stage;
688 current_stage += 1) {
689 if (current_stage == 9) {
693 const int standard_current_stage = current_stage % kNumStages;
694 const bool is_down_event =
695 standard_current_stage == 0 || standard_current_stage == 2;
696 if (is_down_event && recorded_physical_key == 0) {
699 FlutterKeyEventType type =
700 is_down_event ? kFlutterKeyEventTypeDown : kFlutterKeyEventTypeUp;
715 ModifierLogicalToPhysicalContext* context =
716 reinterpret_cast<ModifierLogicalToPhysicalContext*
>(
user_data);
721 context->known_modifier_physical_key =
true;
732 ModifierLogicalToPhysicalContext* context =
733 reinterpret_cast<ModifierLogicalToPhysicalContext*
>(
user_data);
744 GHashTable* modifier_bit_to_checked_keys,
745 uint64_t physical_key_from_event,
746 uint64_t logical_key) {
747 ModifierLogicalToPhysicalContext logical_to_physical_context;
748 logical_to_physical_context.known_modifier_physical_key =
false;
749 logical_to_physical_context.physical_key_from_event = physical_key_from_event;
750 logical_to_physical_context.logical_key = logical_key;
753 logical_to_physical_context.corrected_physical_key = physical_key_from_event;
756 g_hash_table_foreach(modifier_bit_to_checked_keys,
758 &logical_to_physical_context);
762 if (logical_to_physical_context.known_modifier_physical_key) {
763 g_hash_table_foreach(modifier_bit_to_checked_keys,
765 &logical_to_physical_context);
768 return logical_to_physical_context.corrected_physical_key;
772 FlKeyResponder* responder,
777 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(responder);
779 g_return_if_fail(
event !=
nullptr);
780 g_return_if_fail(
callback !=
nullptr);
787 self->modifier_bit_to_checked_keys, physical_key_from_event, logical_key);
789 const bool is_down_event =
event->is_press;
791 SyncStateLoopContext sync_state_context;
792 sync_state_context.self =
self;
793 sync_state_context.state =
event->state;
794 sync_state_context.timestamp = timestamp;
795 sync_state_context.is_down = is_down_event;
796 sync_state_context.event_logical_key = logical_key;
799 g_hash_table_foreach(
self->lock_bit_to_checked_keys,
803 g_hash_table_foreach(
self->modifier_bit_to_checked_keys,
805 &sync_state_context);
808 const uint64_t last_logical_record =
811 FlutterKeyEvent out_event;
812 out_event.struct_size =
sizeof(out_event);
813 out_event.timestamp = timestamp;
814 out_event.physical = physical_key;
816 last_logical_record != 0 ? last_logical_record : logical_key;
817 out_event.character =
nullptr;
818 out_event.synthesized =
false;
820 g_autofree
char* character_to_free =
nullptr;
822 if (last_logical_record) {
825 out_event.type = kFlutterKeyEventTypeRepeat;
827 out_event.type = kFlutterKeyEventTypeDown;
830 out_event.character = character_to_free;
832 if (!last_logical_record) {
839 out_event.type = kFlutterKeyEventTypeUp;
843 if (out_event.type != kFlutterKeyEventTypeRepeat) {
850 FlKeyEmbedderUserData* response_data =
852 self->sent_any_events =
true;
858 FlKeyResponder* responder,
863 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(responder);
864 self->sent_any_events =
false;
867 if (!
self->sent_any_events) {
868 self->send_key_event(&
kEmptyEvent,
nullptr,
nullptr);
873 FlKeyEmbedderResponder* responder,
878 SyncStateLoopContext sync_state_context;
879 sync_state_context.self = responder;
880 sync_state_context.state =
state;
881 sync_state_context.timestamp = timestamp;
884 g_hash_table_foreach(responder->modifier_bit_to_checked_keys,
886 &sync_state_context);
890 FlKeyEmbedderResponder*
self) {
891 return self->pressing_records;