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;
79 STATE_LOGIC_INFERRENCE_UNDECIDED,
80 STATE_LOGIC_INFERRENCE_NORMAL,
81 STATE_LOGIC_INFERRENCE_REVERSED,
82 } StateLogicInferrence;
150 G_DEFINE_TYPE(FlKeyEmbedderResponder, fl_key_embedder_responder, G_TYPE_OBJECT)
154 FlKeyEmbedderResponderClass* klass) {
160 self->cancellable = g_cancellable_new();
165 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
object);
167 g_cancellable_cancel(self->cancellable);
169 g_weak_ref_clear(&self->engine);
170 g_clear_pointer(&self->pressing_records, g_hash_table_unref);
171 g_clear_pointer(&self->mapping_records, g_hash_table_unref);
172 g_clear_pointer(&self->modifier_bit_to_checked_keys, g_hash_table_unref);
173 g_clear_pointer(&self->lock_bit_to_checked_keys, g_hash_table_unref);
174 g_clear_pointer(&self->logical_key_to_lock_bit, g_hash_table_unref);
175 g_clear_object(&self->cancellable);
177 G_OBJECT_CLASS(fl_key_embedder_responder_parent_class)->dispose(
object);
182 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(
183 g_object_new(fl_key_embedder_responder_get_type(),
nullptr));
185 g_weak_ref_init(&self->engine, engine);
187 self->pressing_records = g_hash_table_new(g_direct_hash, g_direct_equal);
188 self->mapping_records = g_hash_table_new(g_direct_hash, g_direct_equal);
189 self->lock_records = 0;
190 self->caps_lock_state_logic_inferrence = STATE_LOGIC_INFERRENCE_UNDECIDED;
192 self->modifier_bit_to_checked_keys =
193 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
196 self->lock_bit_to_checked_keys =
197 g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
201 self->logical_key_to_lock_bit =
202 g_hash_table_new(g_direct_hash, g_direct_equal);
204 g_hash_table_iter_init(&iter, self->lock_bit_to_checked_keys);
206 while (g_hash_table_iter_next(&iter, &key, &
value)) {
207 guint lock_bit = GPOINTER_TO_UINT(key);
210 g_hash_table_insert(self->logical_key_to_lock_bit,
212 GUINT_TO_POINTER(lock_bit));
225 return found->second;
234 return found->second;
254 gchar* result = g_ucs4_to_utf8(&unicodeChar, 1, NULL, &items_written, NULL);
255 if (items_written == 0) {
256 if (result != NULL) {
266 FlutterKeyEventType
type,
270 FlutterKeyEvent out_event;
271 out_event.struct_size =
sizeof(out_event);
272 out_event.timestamp = timestamp;
273 out_event.type =
type;
274 out_event.physical = physical;
275 out_event.logical = logical;
276 out_event.character =
nullptr;
277 out_event.synthesized =
true;
278 self->sent_any_events =
true;
279 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
280 if (engine !=
nullptr) {
292 uint64_t physical_key,
293 uint64_t logical_key) {
294 if (logical_key != 0) {
297 g_hash_table_insert(self->pressing_records,
303 g_hash_table_remove(self->pressing_records,
313 uint64_t logical_key,
318 const guint mode_bit = GPOINTER_TO_UINT(g_hash_table_lookup(
321 self->lock_records ^= mode_bit;
326 uint64_t physical_key,
327 uint64_t logical_key) {
338 g_hash_table_iter_init(&iter, self->modifier_bit_to_checked_keys);
340 while (g_hash_table_iter_next(&iter, &key, &
value)) {
341 guint modifier_bit = GPOINTER_TO_UINT(key);
353 const uint64_t logical_keys[] = {
359 const bool any_pressed_by_state = (
state & modifier_bit) != 0;
361 bool any_pressed_by_record =
false;
372 for (guint logical_key_idx = 0; logical_key_idx <
length;
374 const uint64_t logical_key = logical_keys[logical_key_idx];
375 g_return_if_fail(logical_key != 0);
376 const uint64_t pressing_physical_key =
378 const bool this_key_pressed_before_event = pressing_physical_key != 0;
380 any_pressed_by_record =
381 any_pressed_by_record || this_key_pressed_before_event;
383 if (this_key_pressed_before_event && !any_pressed_by_state) {
384 const uint64_t recorded_physical_key =
388 g_return_if_fail(recorded_physical_key != 0);
390 const uint64_t recorded_logical_key =
393 recorded_physical_key, recorded_logical_key,
400 if (any_pressed_by_state && !any_pressed_by_record) {
402 const uint64_t recorded_physical_key =
409 const uint64_t physical_key = recorded_physical_key != 0
410 ? recorded_physical_key
412 if (recorded_physical_key == 0) {
416 logical_key, timestamp);
425 constexpr
int stage_by_record_index[] = {
431 return stage_by_record_index[(is_down << 1) + is_enabled];
439 bool reverse_state_logic) {
441 return reverse_state_logic ? 2 : 0;
444 return reverse_state_logic ? 0 : 2;
446 return stage_by_record;
452 g_return_val_if_fail(stage_by_record >= 0 && stage_by_record < 4,
457 if (stage_by_record == 0) {
460 return stage_by_record;
479 FlKeyEmbedderResponder*
self,
481 bool enabled_by_state,
482 int stage_by_record) {
483 if (self->caps_lock_state_logic_inferrence !=
484 STATE_LOGIC_INFERRENCE_UNDECIDED) {
487 if (!is_down_event) {
491 stage_by_record, is_down_event, enabled_by_state,
false);
492 if ((stage_by_event == 0 && stage_by_record == 2) ||
493 (stage_by_event == 2 && stage_by_record == 0)) {
494 self->caps_lock_state_logic_inferrence = STATE_LOGIC_INFERRENCE_REVERSED;
496 self->caps_lock_state_logic_inferrence = STATE_LOGIC_INFERRENCE_NORMAL;
508 uint64_t event_logical_key) {
510 g_hash_table_iter_init(&iter, self->lock_bit_to_checked_keys);
512 while (g_hash_table_iter_next(&iter, &key, &
value)) {
513 guint modifier_bit = GPOINTER_TO_UINT(key);
518 const uint64_t recorded_physical_key =
527 const uint64_t physical_key = recorded_physical_key != 0
528 ? recorded_physical_key
550 const uint64_t pressed_logical_key =
551 recorded_physical_key == 0
555 g_return_if_fail(pressed_logical_key == 0 ||
556 pressed_logical_key == logical_key);
558 pressed_logical_key != 0, (self->lock_records & modifier_bit) != 0);
560 const bool enabled_by_state = (
state & modifier_bit) != 0;
561 const bool this_key_is_event_key = logical_key == event_logical_key;
562 if (this_key_is_event_key && checked_key->
is_caps_lock) {
565 g_return_if_fail(self->caps_lock_state_logic_inferrence !=
566 STATE_LOGIC_INFERRENCE_UNDECIDED);
568 const bool reverse_state_logic =
569 checked_key->
is_caps_lock &&
self->caps_lock_state_logic_inferrence ==
570 STATE_LOGIC_INFERRENCE_REVERSED;
571 const int stage_by_event =
572 this_key_is_event_key
574 enabled_by_state, reverse_state_logic)
579 constexpr
int kNumStages = 4;
580 const int destination_stage = stage_by_event >= stage_by_record
582 : stage_by_event + kNumStages;
584 g_return_if_fail(stage_by_record <= destination_stage);
585 for (
int current_stage = stage_by_record;
586 current_stage < destination_stage && current_stage < 9;
587 current_stage += 1) {
588 const int standard_current_stage = current_stage % kNumStages;
589 const bool is_down_event =
590 standard_current_stage == 0 || standard_current_stage == 2;
591 if (is_down_event && recorded_physical_key == 0) {
594 FlutterKeyEventType
type =
595 is_down_event ? kFlutterKeyEventTypeDown : kFlutterKeyEventTypeUp;
597 is_down_event ? logical_key : 0);
605 GHashTable* modifier_bit_to_checked_keys,
606 uint64_t physical_key_from_event,
607 uint64_t logical_key) {
610 uint64_t corrected_physical_key = physical_key_from_event;
613 bool known_modifier_physical_key =
false;
615 g_hash_table_iter_init(&iter, modifier_bit_to_checked_keys);
617 while (g_hash_table_iter_next(&iter,
nullptr, &
value)) {
621 known_modifier_physical_key =
true;
627 if (known_modifier_physical_key) {
628 g_hash_table_iter_init(&iter, modifier_bit_to_checked_keys);
629 while (g_hash_table_iter_next(&iter,
nullptr, &
value)) {
639 return corrected_physical_key;
643 FlKeyEmbedderResponder* responder,
645 uint64_t specified_logical_key,
647 FlKeyEmbedderResponder*
self = FL_KEY_EMBEDDER_RESPONDER(responder);
649 const uint64_t logical_key = specified_logical_key != 0
650 ? specified_logical_key
654 self->modifier_bit_to_checked_keys, physical_key_from_event, logical_key);
666 const uint64_t last_logical_record =
669 FlutterKeyEvent out_event;
670 out_event.struct_size =
sizeof(out_event);
671 out_event.timestamp = timestamp;
672 out_event.physical = physical_key;
674 last_logical_record != 0 ? last_logical_record : logical_key;
675 out_event.character =
nullptr;
676 out_event.synthesized =
false;
678 g_autofree
char* character_to_free =
nullptr;
680 if (last_logical_record) {
683 out_event.type = kFlutterKeyEventTypeRepeat;
685 out_event.type = kFlutterKeyEventTypeDown;
688 out_event.character = character_to_free;
690 if (!last_logical_record) {
694 gboolean* return_value = g_new0(gboolean, 1);
695 *return_value =
TRUE;
696 g_task_return_pointer(task, return_value, g_free);
699 out_event.type = kFlutterKeyEventTypeUp;
703 if (out_event.type != kFlutterKeyEventTypeRepeat) {
710 self->sent_any_events =
true;
711 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
712 if (engine !=
nullptr) {
714 engine, &out_event, self->cancellable,
715 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
716 g_autoptr(GTask) task = G_TASK(user_data);
719 g_autoptr(GError) error = nullptr;
720 if (!fl_engine_send_key_event_finish(FL_ENGINE(object), result,
722 if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
725 g_warning(
"Failed to handle key event: %s", error->message);
729 gboolean* return_value = g_new0(gboolean, 1);
730 *return_value = handled;
731 g_task_return_pointer(task, return_value, g_free);
739 uint64_t specified_logical_key,
740 GCancellable* cancellable,
741 GAsyncReadyCallback callback,
743 g_autoptr(GTask) task = g_task_new(
self, cancellable, callback,
user_data);
745 self->sent_any_events =
false;
747 specified_logical_key, task);
748 if (!self->sent_any_events) {
749 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
750 if (engine !=
nullptr) {
758 FlKeyEmbedderResponder*
self,
759 GAsyncResult* result,
762 g_return_val_if_fail(g_task_is_valid(result,
self), FALSE);
764 g_autofree gboolean* return_value =
765 static_cast<gboolean*
>(g_task_propagate_pointer(G_TASK(result),
error));
766 if (return_value ==
nullptr) {
770 *handled = *return_value;
775 FlKeyEmbedderResponder*
self,
778 g_return_if_fail(FL_IS_KEY_EMBEDDER_RESPONDER(
self));
784 FlKeyEmbedderResponder*
self) {
785 return self->pressing_records;