19 #define DEBUG_PRINT_LAYOUT
23 static bool is_eascii(uint16_t character) {
24 return character < 256;
27 #ifdef DEBUG_PRINT_LAYOUT
29 void debug_format_layout_data(std::string& debug_layout_data,
33 if (keycode % 4 == 0) {
34 debug_layout_data.append(
" ");
37 constexpr
int kBufferSize = 30;
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*>>
121 G_DEFINE_TYPE(FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT);
128 for (guint
i = 0;
i <
self->redispatched_key_events->len;
i++) {
130 FL_KEY_EVENT(g_ptr_array_index(self->redispatched_key_events,
i));
134 g_ptr_array_remove_index(self->redispatched_key_events,
i);
143 g_clear_object(&self->derived_layout);
157 g_task_return_boolean(task,
TRUE);
161 GAsyncResult* result,
163 g_autoptr(GTask) task = G_TASK(
user_data);
164 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
170 g_autoptr(GError)
error =
nullptr;
173 FL_KEY_EMBEDDER_RESPONDER(
object), result, &handled, &
error)) {
174 if (!g_error_matches(
error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
175 g_warning(
"Failed to handle key event in embedder: %s",
error->message);
187 GAsyncResult* result,
189 g_autoptr(GTask) task = G_TASK(
user_data);
190 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
196 g_autoptr(GError)
error =
nullptr;
199 FL_KEY_CHANNEL_RESPONDER(
object), result, &handled, &
error)) {
200 if (!g_error_matches(
error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
201 g_warning(
"Failed to handle key event in platform: %s",
error->message);
216 GdkKeymapKey key = {keycode, group, level};
217 constexpr
int kBmpMax = 0xD7FF;
219 if (self->lookup_key_handler !=
nullptr) {
220 origin =
self->lookup_key_handler(&key, self->lookup_key_handler_user_data);
222 origin = gdk_keymap_lookup_key(self->keymap, &key);
224 return origin < kBmpMax ? origin : 0xFFFF;
235 self->keycode_to_goals->end()) {
241 std::map<uint64_t, const LayoutGoal*> remaining_mandatory_goals =
242 *
self->logical_to_mandatory_goals;
244 #ifdef DEBUG_PRINT_LAYOUT
245 std::string debug_layout_data;
246 for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
247 std::vector<uint16_t> this_key_clues = {
251 debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
261 uint16_t keycode = keycode_goal.keycode;
262 std::vector<uint16_t> this_key_clues = {
274 for (uint16_t clue : this_key_clues) {
275 auto matching_goal = remaining_mandatory_goals.find(clue);
276 if (matching_goal != remaining_mandatory_goals.end()) {
279 self->derived_layout, group, keycode) == 0);
282 remaining_mandatory_goals.erase(matching_goal);
286 bool has_any_eascii =
287 is_eascii(this_key_clues[0]) || is_eascii(this_key_clues[1]);
292 auto found_us_layout =
self->keycode_to_goals->find(keycode);
293 if (found_us_layout != self->keycode_to_goals->end()) {
295 self->derived_layout, group, keycode,
296 found_us_layout->second->logical_key);
302 for (
const auto mandatory_goal_iter : remaining_mandatory_goals) {
303 const LayoutGoal* goal = mandatory_goal_iter.second;
310 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(
object);
312 g_cancellable_cancel(self->cancellable);
314 self->keycode_to_goals.reset();
315 self->logical_to_mandatory_goals.reset();
317 g_clear_pointer(&self->redispatched_key_events, g_ptr_array_unref);
318 g_clear_object(&self->key_embedder_responder);
319 g_clear_object(&self->key_channel_responder);
320 g_clear_object(&self->derived_layout);
321 if (self->keymap_keys_changed_cb_id != 0) {
322 g_signal_handler_disconnect(self->keymap, self->keymap_keys_changed_cb_id);
323 self->keymap_keys_changed_cb_id = 0;
325 g_clear_object(&self->cancellable);
327 G_OBJECT_CLASS(fl_keyboard_manager_parent_class)->dispose(
object);
335 self->redispatched_key_events =
336 g_ptr_array_new_with_free_func(g_object_unref);
339 self->keycode_to_goals =
340 std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
341 self->logical_to_mandatory_goals =
342 std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
344 (*
self->keycode_to_goals)[goal.keycode] = &goal;
345 if (goal.mandatory) {
346 (*
self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
350 self->keymap = gdk_keymap_get_for_display(gdk_display_get_default());
351 self->keymap_keys_changed_cb_id = g_signal_connect_swapped(
353 self->cancellable = g_cancellable_new();
357 FlKeyboardManager*
self = FL_KEYBOARD_MANAGER(
358 g_object_new(fl_keyboard_manager_get_type(),
nullptr));
361 self->key_channel_responder =
369 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
371 g_ptr_array_add(self->redispatched_key_events, g_object_ref(event));
376 GCancellable* cancellable,
377 GAsyncReadyCallback callback,
379 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
380 g_return_if_fail(event !=
nullptr);
382 g_autoptr(GTask) task = g_task_new(
self, cancellable, callback,
user_data);
386 g_task_set_task_data(
394 g_task_return_boolean(task,
TRUE);
402 self->key_embedder_responder, event, specified_logical_key,
406 self->key_channel_responder, event, specified_logical_key,
411 FlKeyboardManager*
self,
412 GAsyncResult* result,
413 FlKeyEvent** redispatched_event,
415 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self), FALSE);
416 g_return_val_if_fail(g_task_is_valid(result,
self), FALSE);
420 if (redispatched_event !=
nullptr && data->
redispatch) {
421 *redispatched_event = FL_KEY_EVENT(g_object_ref(data->
event));
424 return g_task_propagate_boolean(G_TASK(result),
error);
430 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
432 self->key_embedder_responder,
state, event_time);
436 g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(
self),
nullptr);
438 self->key_embedder_responder);
442 FlKeyboardManager*
self,
445 g_return_if_fail(FL_IS_KEYBOARD_MANAGER(
self));
446 self->lookup_key_handler = lookup_key_handler;
447 self->lookup_key_handler_user_data =
user_data;