19#define DEBUG_PRINT_LAYOUT
23static bool is_eascii(uint16_t
character) {
27#ifdef DEBUG_PRINT_LAYOUT
29void debug_format_layout_data(std::string& debug_layout_data,
33 if (keycode % 4 == 0) {
34 debug_layout_data.append(
" ");
37 constexpr int kBufferSize = 30;
38 char buffer[kBufferSize];
40 buffer[kBufferSize - 1] = 0;
42 snprintf(buffer, kBufferSize,
"0x%04x, 0x%04x, ", clue1, clue2);
43 debug_layout_data.append(buffer);
45 if (keycode % 4 == 3) {
46 snprintf(buffer, kBufferSize,
" // 0x%02x", keycode);
47 debug_layout_data.append(buffer);
74 data->event = FL_KEY_EVENT(g_object_ref(event));
79 g_object_unref(data->event);
111 std::unique_ptr<std::map<uint64_t, const LayoutGoal*>>
126 for (guint
i = 0;
i <
self->redispatched_key_events->len;
i++) {
128 FL_KEY_EVENT(g_ptr_array_index(
self->redispatched_key_events,
i));
132 g_ptr_array_remove_index(
self->redispatched_key_events,
i);
141 g_clear_object(&
self->derived_layout);
150 if (!data->embedder_responded || !data->channel_responded) {
154 data->redispatch = !data->handled;
155 g_task_return_boolean(task,
TRUE);
159 GAsyncResult* result,
162 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
166 data->embedder_responded =
TRUE;
171 FL_KEY_EMBEDDER_RESPONDER(
object), result, &handled, &
error)) {
172 if (!g_error_matches(
error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
173 g_warning(
"Failed to handle key event in embedder: %s",
error->message);
178 data->handled =
TRUE;
185 GAsyncResult* result,
188 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
192 data->channel_responded =
TRUE;
197 FL_KEY_CHANNEL_RESPONDER(
object), result, &handled, &
error)) {
198 if (!g_error_matches(
error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
199 g_warning(
"Failed to handle key event in platform: %s",
error->message);
204 data->handled =
TRUE;
214 GdkKeymapKey
key = {keycode, group, level};
215 constexpr int kBmpMax = 0xD7FF;
217 if (
self->lookup_key_handler !=
nullptr) {
218 origin =
self->lookup_key_handler(&
key,
self->lookup_key_handler_user_data);
222 return origin < kBmpMax ? origin : 0xFFFF;
233 self->keycode_to_goals->end()) {
239 std::map<uint64_t, const LayoutGoal*> remaining_mandatory_goals =
240 *
self->logical_to_mandatory_goals;
242#ifdef DEBUG_PRINT_LAYOUT
243 std::string debug_layout_data;
244 for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
245 std::vector<uint16_t> this_key_clues = {
249 debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
259 uint16_t keycode = keycode_goal.keycode;
260 std::vector<uint16_t> this_key_clues = {
272 for (uint16_t clue : this_key_clues) {
273 auto matching_goal = remaining_mandatory_goals.find(clue);
274 if (matching_goal != remaining_mandatory_goals.end()) {
277 self->derived_layout, group, keycode) == 0);
280 remaining_mandatory_goals.erase(matching_goal);
284 bool has_any_eascii =
285 is_eascii(this_key_clues[0]) || is_eascii(this_key_clues[1]);
290 auto found_us_layout =
self->keycode_to_goals->find(keycode);
291 if (found_us_layout !=
self->keycode_to_goals->end()) {
293 self->derived_layout, group, keycode,
294 found_us_layout->second->logical_key);
300 for (
const auto mandatory_goal_iter : remaining_mandatory_goals) {
301 const LayoutGoal* goal = mandatory_goal_iter.second;
308 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(
object);
310 g_cancellable_cancel(
self->cancellable);
312 self->keycode_to_goals.reset();
313 self->logical_to_mandatory_goals.reset();
315 g_clear_pointer(&
self->redispatched_key_events, g_ptr_array_unref);
316 g_clear_object(&
self->key_embedder_responder);
317 g_clear_object(&
self->key_channel_responder);
318 g_clear_object(&
self->derived_layout);
319 g_clear_object(&
self->cancellable);
321 G_OBJECT_CLASS(fl_keyboard_manager_parent_class)->dispose(
object);
329 self->redispatched_key_events =
330 g_ptr_array_new_with_free_func(g_object_unref);
333 self->keycode_to_goals =
334 std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
335 self->logical_to_mandatory_goals =
336 std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
338 (*
self->keycode_to_goals)[goal.keycode] = &goal;
339 if (goal.mandatory) {
340 (*
self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
345 g_signal_connect_object(
self->keymap,
"keys-changed",
348 self->cancellable = g_cancellable_new();
352 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(
353 g_object_new(fl_keyboard_manager_get_type(),
nullptr));
356 self->key_channel_responder =
364 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
366 g_ptr_array_add(
self->redispatched_key_events, g_object_ref(event));
371 GCancellable* cancellable,
374 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
375 g_return_if_fail(event !=
nullptr);
381 g_task_set_task_data(
388 data->handled =
TRUE;
389 g_task_return_boolean(task,
TRUE);
397 self->key_embedder_responder, event, specified_logical_key,
401 self->key_channel_responder, event, specified_logical_key,
406 FlKeyboardManager*
self,
407 GAsyncResult* result,
408 FlKeyEvent** redispatched_event,
410 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self), FALSE);
411 g_return_val_if_fail(g_task_is_valid(result,
self), FALSE);
415 if (redispatched_event !=
nullptr && data->redispatch) {
416 *redispatched_event = FL_KEY_EVENT(g_object_ref(data->event));
419 return g_task_propagate_boolean(G_TASK(result),
error);
425 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
427 self->key_embedder_responder, state, event_time);
431 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self),
nullptr);
433 self->key_embedder_responder);
437 FlKeyboardManager*
self,
440 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
441 self->lookup_key_handler = lookup_key_handler;
g_autoptr(FlEngine) engine
G_MODULE_EXPORT FlBinaryMessenger * fl_engine_get_binary_messenger(FlEngine *self)
void fl_key_channel_responder_handle_event(FlKeyChannelResponder *self, FlKeyEvent *event, uint64_t specified_logical_key, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
gboolean fl_key_channel_responder_handle_event_finish(FlKeyChannelResponder *self, GAsyncResult *result, gboolean *handled, GError **error)
FlKeyChannelResponder * fl_key_channel_responder_new(FlBinaryMessenger *messenger)
FlKeyEmbedderResponder * fl_key_embedder_responder_new(FlEngine *engine)
GHashTable * fl_key_embedder_responder_get_pressed_state(FlKeyEmbedderResponder *self)
void fl_key_embedder_responder_sync_modifiers_if_needed(FlKeyEmbedderResponder *self, guint state, double event_time)
void fl_key_embedder_responder_handle_event(FlKeyEmbedderResponder *self, FlKeyEvent *event, uint64_t specified_logical_key, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
gboolean fl_key_embedder_responder_handle_event_finish(FlKeyEmbedderResponder *self, GAsyncResult *result, gboolean *handled, GError **error)
guint16 fl_key_event_get_keycode(FlKeyEvent *self)
gboolean fl_key_event_get_is_press(FlKeyEvent *self)
guint8 fl_key_event_get_group(FlKeyEvent *self)
guint32 fl_key_event_get_time(FlKeyEvent *self)
const std::vector< LayoutGoal > layout_goals
FlKeyboardLayout * fl_keyboard_layout_new()
uint64_t fl_keyboard_layout_get_logical_key(FlKeyboardLayout *self, uint8_t group, uint16_t keycode)
void fl_keyboard_layout_set_logical_key(FlKeyboardLayout *self, uint8_t group, uint16_t keycode, uint64_t logical_key)
gboolean fl_keyboard_layout_has_group(FlKeyboardLayout *self, uint8_t group)
static void fl_keyboard_manager_class_init(FlKeyboardManagerClass *klass)
static void fl_keyboard_manager_dispose(GObject *object)
static void guarantee_layout(FlKeyboardManager *self, FlKeyEvent *event)
static void responder_handle_channel_event_cb(GObject *object, GAsyncResult *result, gpointer user_data)
G_DEFINE_TYPE(FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT)
void fl_keyboard_manager_handle_event(FlKeyboardManager *self, FlKeyEvent *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
static void handle_event_data_free(HandleEventData *data)
static uint16_t convert_key_to_char(FlKeyboardManager *self, guint keycode, gint group, gint level)
GHashTable * fl_keyboard_manager_get_pressed_state(FlKeyboardManager *self)
static void fl_keyboard_manager_init(FlKeyboardManager *self)
static void responder_handle_embedder_event_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static gboolean event_is_redispatched(FlKeyboardManager *self, FlKeyEvent *event)
static void keymap_keys_changed_cb(FlKeyboardManager *self)
static HandleEventData * handle_event_data_new(FlKeyEvent *event)
gboolean fl_keyboard_manager_handle_event_finish(FlKeyboardManager *self, GAsyncResult *result, FlKeyEvent **redispatched_event, GError **error)
void fl_keyboard_manager_set_lookup_key_handler(FlKeyboardManager *self, FlKeyboardManagerLookupKeyHandler lookup_key_handler, gpointer user_data)
static void complete_handle_event(FlKeyboardManager *self, GTask *task)
FlKeyboardManager * fl_keyboard_manager_new(FlEngine *engine)
void fl_keyboard_manager_add_redispatched_event(FlKeyboardManager *self, FlKeyEvent *event)
void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager *self, guint state, double event_time)
guint(* FlKeyboardManagerLookupKeyHandler)(const GdkKeymapKey *key, gpointer user_data)
const uint8_t uint32_t uint32_t GError ** error
FlutterDesktopBinaryReply callback
GdkDisplay * gdk_display_get_default()
guint gdk_keymap_lookup_key(GdkKeymap *keymap, const GdkKeymapKey *key)
GdkKeymap * gdk_keymap_get_for_display(GdkDisplay *display)
gpointer lookup_key_handler_user_data
FlKeyboardManagerLookupKeyHandler lookup_key_handler
FlKeyChannelResponder * key_channel_responder
std::unique_ptr< std::map< uint64_t, const LayoutGoal * > > logical_to_mandatory_goals
FlKeyEmbedderResponder * key_embedder_responder
GPtrArray * redispatched_key_events
std::unique_ptr< std::map< uint16_t, const LayoutGoal * > > keycode_to_goals
GCancellable * cancellable
FlKeyboardLayout * derived_layout
gboolean embedder_responded
gboolean channel_responded