5#include "flutter/shell/platform/linux/fl_keyboard_manager.h"
12#include "flutter/shell/platform/linux/fl_key_channel_responder.h"
13#include "flutter/shell/platform/linux/fl_key_embedder_responder.h"
14#include "flutter/shell/platform/linux/key_mapping.h"
15#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
16#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
20#define DEBUG_PRINT_LAYOUT
28 fl_keyboard_pending_event,
30 KEYBOARD_PENDING_EVENT,
33#define FL_TYPE_KEYBOARD_MANAGER_USER_DATA \
34 fl_keyboard_manager_user_data_get_type()
36 fl_keyboard_manager_user_data,
38 KEYBOARD_MANAGER_USER_DATA,
49constexpr size_t kLayoutSize = 128;
53typedef std::array<uint64_t, kLayoutSize> DerivedGroupLayout;
57typedef std::map<guint8, DerivedGroupLayout> DerivedLayout;
64} DispatchToResponderLoopContext;
70#ifdef DEBUG_PRINT_LAYOUT
72void debug_format_layout_data(std::string& debug_layout_data,
76 if (keycode % 4 == 0) {
77 debug_layout_data.append(
" ");
86 debug_layout_data.append(
buffer);
88 if (keycode % 4 == 3) {
90 debug_layout_data.append(
buffer);
98 const DerivedLayout& layout) {
99 guint8 group =
event->group;
100 guint16 keycode =
event->keycode;
101 if (keycode >= kLayoutSize) {
105 auto found_group_layout = layout.find(group);
106 if (found_group_layout != layout.end()) {
107 return found_group_layout->second[keycode];
145G_DEFINE_TYPE(FlKeyboardPendingEvent, fl_keyboard_pending_event, G_TYPE_OBJECT)
150 g_return_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(
object));
152 FlKeyboardPendingEvent*
self = FL_KEYBOARD_PENDING_EVENT(
object);
153 if (
self->event !=
nullptr) {
156 G_OBJECT_CLASS(fl_keyboard_pending_event_parent_class)->dispose(
object);
160 FlKeyboardPendingEventClass* klass) {
174 static_cast<uint64_t
>(
event->is_press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
175 guint64 keycode =
static_cast<uint64_t
>(
event->keycode);
176 return (
event->
time & 0xffffffff) | ((
type & 0xffff) << 32) |
177 ((keycode & 0xffff) << 48);
185 std::unique_ptr<FlKeyEvent>
event,
186 uint64_t sequence_id,
188 FlKeyboardPendingEvent*
self = FL_KEYBOARD_PENDING_EVENT(
189 g_object_new(fl_keyboard_pending_event_get_type(),
nullptr));
192 self->sequence_id = sequence_id;
193 self->unreplied = to_reply;
194 self->any_handled =
false;
216 fl_keyboard_manager_user_data,
219static void fl_keyboard_manager_user_data_dispose(GObject*
object) {
220 g_return_if_fail(FL_IS_KEYBOARD_MANAGER_USER_DATA(
object));
221 FlKeyboardManagerUserData*
self = FL_KEYBOARD_MANAGER_USER_DATA(
object);
222 if (
self->manager !=
nullptr) {
223 g_object_remove_weak_pointer(G_OBJECT(
self->manager),
224 reinterpret_cast<gpointer*
>(&(
self->manager)));
225 self->manager =
nullptr;
230 FlKeyboardManagerUserDataClass* klass) {
231 G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_user_data_dispose;
235 FlKeyboardManagerUserData*
self) {}
240 uint64_t sequence_id) {
241 FlKeyboardManagerUserData*
self = FL_KEYBOARD_MANAGER_USER_DATA(
242 g_object_new(fl_keyboard_manager_user_data_get_type(),
nullptr));
244 self->manager = manager;
248 reinterpret_cast<gpointer*
>(&(
self->manager)));
249 self->sequence_id = sequence_id;
293 std::unique_ptr<std::map<uint64_t, const LayoutGoal*>>
309 self->derived_layout = std::make_unique<DerivedLayout>();
311 self->keycode_to_goals =
312 std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
313 self->logical_to_mandatory_goals =
314 std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
316 (*
self->keycode_to_goals)[goal.keycode] = &goal;
317 if (goal.mandatory) {
318 (*
self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
322 self->responder_list = g_ptr_array_new_with_free_func(g_object_unref);
324 self->pending_responds = g_ptr_array_new();
325 self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
327 self->last_sequence_id = 1;
333 if (
self->view_delegate !=
nullptr) {
336 g_object_remove_weak_pointer(
337 G_OBJECT(
self->view_delegate),
338 reinterpret_cast<gpointer*
>(&(
self->view_delegate)));
339 self->view_delegate =
nullptr;
342 self->derived_layout.reset();
343 self->keycode_to_goals.reset();
344 self->logical_to_mandatory_goals.reset();
346 g_ptr_array_free(
self->responder_list,
TRUE);
347 g_ptr_array_set_free_func(
self->pending_responds, g_object_unref);
348 g_ptr_array_free(
self->pending_responds,
TRUE);
349 g_ptr_array_free(
self->pending_redispatches,
TRUE);
351 G_OBJECT_CLASS(fl_keyboard_manager_parent_class)->dispose(
object);
360 gconstpointer needle,
361 GEqualFunc equal_func,
364 g_return_val_if_fail(haystack != NULL,
FALSE);
365 if (equal_func == NULL) {
366 equal_func = g_direct_equal;
368 for (i = 0; i < haystack->len; i++) {
369 if (equal_func(g_ptr_array_index(haystack, i), needle)) {
370 if (index_ != NULL) {
383 gconstpointer pending,
384 gconstpointer needle_sequence_id) {
385 uint64_t sequence_id = *
reinterpret_cast<const uint64_t*
>(needle_sequence_id);
386 return static_cast<const FlKeyboardPendingEvent*
>(pending)->sequence_id ==
393 gconstpointer needle_hash) {
394 uint64_t
hash = *
reinterpret_cast<const uint64_t*
>(needle_hash);
395 return static_cast<const FlKeyboardPendingEvent*
>(pending)->
hash ==
hash;
406 self->pending_redispatches,
static_cast<const uint64_t*
>(&
hash),
410 g_ptr_array_remove_index_fast(
self->pending_redispatches, result_index);
419 gpointer user_data_ptr) {
420 g_return_if_fail(FL_IS_KEYBOARD_MANAGER_USER_DATA(user_data_ptr));
422 FL_KEYBOARD_MANAGER_USER_DATA(user_data_ptr);
424 g_return_if_fail(
self->view_delegate !=
nullptr);
426 guint result_index = -1;
430 g_return_if_fail(found);
431 FlKeyboardPendingEvent* pending = FL_KEYBOARD_PENDING_EVENT(
432 g_ptr_array_index(
self->pending_responds, result_index));
433 g_return_if_fail(pending !=
nullptr);
434 g_return_if_fail(pending->unreplied > 0);
435 pending->unreplied -= 1;
436 pending->any_handled = pending->any_handled || handled;
438 if (pending->unreplied == 0) {
439 g_object_unref(user_data_ptr);
441 g_ptr_array_remove_index_fast(
self->pending_responds, result_index);
442 g_return_if_fail(removed == pending);
443 bool should_redispatch = !pending->any_handled &&
445 self->view_delegate, pending->event.get());
446 if (should_redispatch) {
447 g_ptr_array_add(
self->pending_redispatches, pending);
449 std::move(pending->event));
451 g_object_unref(pending);
460 GdkKeymapKey
key = {keycode, group, level};
461 constexpr int kBmpMax = 0xD7FF;
463 return origin < kBmpMax ? origin : 0xFFFF;
469 guint8 group =
event->group;
470 if (
self->derived_layout->find(group) !=
self->derived_layout->end()) {
474 self->keycode_to_goals->end()) {
478 DerivedGroupLayout& layout = (*
self->derived_layout)[group];
482 std::map<uint64_t, const LayoutGoal*> remaining_mandatory_goals =
483 *
self->logical_to_mandatory_goals;
485#ifdef DEBUG_PRINT_LAYOUT
486 std::string debug_layout_data;
487 for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
488 std::vector<uint16_t> this_key_clues = {
492 debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
502 uint16_t keycode = keycode_goal.keycode;
503 std::vector<uint16_t> this_key_clues = {
515 for (uint16_t clue : this_key_clues) {
516 auto matching_goal = remaining_mandatory_goals.find(clue);
517 if (matching_goal != remaining_mandatory_goals.end()) {
519 g_return_if_fail(layout[keycode] == 0);
520 layout[keycode] = clue;
521 remaining_mandatory_goals.erase(matching_goal);
525 bool has_any_eascii =
526 is_eascii(this_key_clues[0]) || is_eascii(this_key_clues[1]);
528 if (layout[keycode] == 0 && !has_any_eascii) {
529 auto found_us_layout =
self->keycode_to_goals->find(keycode);
530 if (found_us_layout !=
self->keycode_to_goals->end()) {
531 layout[keycode] = found_us_layout->second->logical_key;
537 for (
const auto mandatory_goal_iter : remaining_mandatory_goals) {
538 const LayoutGoal* goal = mandatory_goal_iter.second;
547 GHashTable* pressing_records =
550 g_hash_table_foreach(
553 int64_t physical_key =
reinterpret_cast<int64_t
>(
key);
554 int64_t logical_key =
reinterpret_cast<int64_t
>(
value);
572 g_autoptr(FlMethodResponse) response =
nullptr;
579 g_autoptr(GError)
error =
nullptr;
581 g_warning(
"Failed to send method call response: %s",
error->message);
586 FlBinaryMessenger* messenger,
587 FlKeyboardViewDelegate* view_delegate) {
588 g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(view_delegate),
nullptr);
591 g_object_new(fl_keyboard_manager_get_type(),
nullptr));
593 self->view_delegate = view_delegate;
595 G_OBJECT(view_delegate),
596 reinterpret_cast<gpointer*
>(&(
self->view_delegate)));
600 self->responder_list,
603 void* callback_user_data,
void* send_key_event_user_data) {
605 FL_KEYBOARD_MANAGER(send_key_event_user_data);
606 g_return_if_fail(
self->view_delegate !=
nullptr);
611 g_ptr_array_add(
self->responder_list,
616 self->view_delegate, [
self]() { self->derived_layout->clear(); });
629 gpointer foreach_data_ptr) {
630 DispatchToResponderLoopContext* context =
631 reinterpret_cast<DispatchToResponderLoopContext*
>(foreach_data_ptr);
632 FlKeyResponder* responder = FL_KEY_RESPONDER(responder_data);
635 context->user_data, context->specified_logical_key);
640 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self),
FALSE);
641 g_return_val_if_fail(
event !=
nullptr,
FALSE);
642 g_return_val_if_fail(
self->view_delegate !=
nullptr,
FALSE);
652 std::unique_ptr<FlKeyEvent>(
event), ++
self->last_sequence_id,
653 self->responder_list->len);
655 g_ptr_array_add(
self->pending_responds, pending);
658 DispatchToResponderLoopContext data{
660 .specified_logical_key =
670 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self),
FALSE);
671 return self->pending_responds->len == 0 &&
672 self->pending_redispatches->len == 0;
678 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
682 FlKeyEmbedderResponder* responder =
683 FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(
self->responder_list, 0));
689 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self),
nullptr);
693 FlKeyEmbedderResponder* responder =
694 FL_KEY_EMBEDDER_RESPONDER(g_ptr_array_index(
self->responder_list, 0));
static uint32_t hash(const SkShaderBase::GradientInfo &v)
static const size_t kBufferSize
void(* FlutterKeyEventCallback)(bool, void *)
FlKeyEvent uint64_t specified_logical_key
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyChannelResponder * fl_key_channel_responder_new(FlBinaryMessenger *messenger, FlKeyChannelResponderMock *mock)
GHashTable * fl_key_embedder_responder_get_pressed_state(FlKeyEmbedderResponder *self)
FlKeyEmbedderResponder * fl_key_embedder_responder_new(EmbedderSendKeyEvent send_key_event, void *send_key_event_user_data)
void fl_key_embedder_responder_sync_modifiers_if_needed(FlKeyEmbedderResponder *responder, guint state, double event_time)
void fl_key_event_dispose(FlKeyEvent *event)
void fl_key_responder_handle_event(FlKeyResponder *self, FlKeyEvent *event, FlKeyResponderAsyncCallback callback, gpointer user_data, uint64_t specified_logical_key)
typedefG_BEGIN_DECLS struct _FlKeyboardManager FlKeyboardManager
gboolean fl_keyboard_manager_is_state_clear(FlKeyboardManager *self)
static void fl_keyboard_manager_class_init(FlKeyboardManagerClass *klass)
static void fl_keyboard_manager_dispose(GObject *object)
static FlKeyboardPendingEvent * fl_keyboard_pending_event_new(std::unique_ptr< FlKeyEvent > event, uint64_t sequence_id, size_t to_reply)
static void fl_keyboard_manager_user_data_init(FlKeyboardManagerUserData *self)
static uint64_t get_logical_key_from_layout(const FlKeyEvent *event, const DerivedLayout &layout)
G_DEFINE_TYPE(FlKeyboardManagerUserData, fl_keyboard_manager_user_data, G_TYPE_OBJECT) static void fl_keyboard_manager_user_data_dispose(GObject *object)
static uint64_t fl_keyboard_manager_get_event_hash(FlKeyEvent *event)
static void guarantee_layout(FlKeyboardManager *self, FlKeyEvent *event)
static FlKeyboardManagerUserData * fl_keyboard_manager_user_data_new(FlKeyboardManager *manager, uint64_t sequence_id)
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager *self, FlKeyEvent *event)
G_DECLARE_FINAL_TYPE(FlKeyboardPendingEvent, fl_keyboard_pending_event, FL, KEYBOARD_PENDING_EVENT, GObject)
GHashTable * fl_keyboard_manager_get_pressed_state(FlKeyboardManager *self)
static void fl_keyboard_manager_user_data_class_init(FlKeyboardManagerUserDataClass *klass)
static void fl_keyboard_manager_init(FlKeyboardManager *self)
static void method_call_handler(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data)
static void dispatch_to_responder(gpointer responder_data, gpointer foreach_data_ptr)
static constexpr char kChannelName[]
FlMethodResponse * get_keyboard_state(FlKeyboardManager *self)
static void fl_keyboard_pending_event_class_init(FlKeyboardPendingEventClass *klass)
static gboolean g_ptr_array_find_with_equal_func1(GPtrArray *haystack, gconstpointer needle, GEqualFunc equal_func, guint *index_)
static void responder_handle_event_callback(bool handled, gpointer user_data_ptr)
static gboolean compare_pending_by_hash(gconstpointer pending, gconstpointer needle_hash)
static constexpr char kGetKeyboardStateMethod[]
static gboolean compare_pending_by_sequence_id(gconstpointer pending, gconstpointer needle_sequence_id)
static void fl_keyboard_pending_event_dispose(GObject *object)
FlKeyboardManager * fl_keyboard_manager_new(FlBinaryMessenger *messenger, FlKeyboardViewDelegate *view_delegate)
static bool fl_keyboard_manager_remove_redispatched(FlKeyboardManager *self, uint64_t hash)
static void fl_keyboard_pending_event_init(FlKeyboardPendingEvent *self)
void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager *self, guint state, double event_time)
static uint16_t convert_key_to_char(FlKeyboardViewDelegate *view_delegate, guint keycode, gint group, gint level)
GHashTable * fl_keyboard_view_delegate_get_keyboard_state(FlKeyboardViewDelegate *self)
void fl_keyboard_view_delegate_send_key_event(FlKeyboardViewDelegate *self, const FlutterKeyEvent *event, FlutterKeyEventCallback callback, void *user_data)
FlBinaryMessenger * fl_keyboard_view_delegate_get_messenger(FlKeyboardViewDelegate *self)
void fl_keyboard_view_delegate_subscribe_to_layout_change(FlKeyboardViewDelegate *self, KeyboardLayoutNotifier notifier)
guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate *self, const GdkKeymapKey *key)
gboolean fl_keyboard_view_delegate_text_filter_key_press(FlKeyboardViewDelegate *self, FlKeyEvent *event)
void fl_keyboard_view_delegate_redispatch_event(FlKeyboardViewDelegate *self, std::unique_ptr< FlKeyEvent > event)
G_MODULE_EXPORT const gchar * fl_method_call_get_name(FlMethodCall *self)
G_MODULE_EXPORT gboolean fl_method_call_respond(FlMethodCall *self, FlMethodResponse *response, GError **error)
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
G_MODULE_EXPORT FlValue * fl_value_new_map()
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
typedefG_BEGIN_DECLS struct _FlValue FlValue
g_object_add_weak_pointer(G_OBJECT(self), reinterpret_cast< gpointer * >(&self->engine))
const std::vector< LayoutGoal > layout_goals
FlKeyboardManager * manager
GPtrArray * pending_responds
FlMethodChannel * channel
std::unique_ptr< DerivedLayout > derived_layout
FlKeyboardViewDelegate * view_delegate
GPtrArray * pending_redispatches
std::unique_ptr< std::map< uint64_t, const LayoutGoal * > > logical_to_mandatory_goals
std::unique_ptr< std::map< uint16_t, const LayoutGoal * > > keycode_to_goals
uint64_t last_sequence_id
GPtrArray * responder_list
std::unique_ptr< FlKeyEvent > event