Skip to content

Commit

Permalink
Move keymap from FlKeyboardViewDelegate to FlKeyboardManager
Browse files Browse the repository at this point in the history
Ideally the tests would mock gdk_keymap_lookup_key, but I wasn't able to get it
working so I've added fl_keyboard_manager_set_lookup_key_handler for now.
  • Loading branch information
robert-ancell committed Oct 18, 2024
1 parent 0bb6b1f commit cbaaeac
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 68 deletions.
50 changes: 42 additions & 8 deletions shell/platform/linux/fl_keyboard_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ struct _FlKeyboardManager {

GWeakRef view_delegate;

FlKeyboardManagerLookupKeyHandler lookup_key_handler;
gpointer lookup_key_handler_user_data;

FlKeyboardManagerRedispatchEventHandler redispatch_handler;
gpointer redispatch_handler_user_data;

Expand Down Expand Up @@ -157,10 +160,19 @@ struct _FlKeyboardManager {
// It is set up when the manager is initialized and is not changed ever after.
std::unique_ptr<std::map<uint64_t, const LayoutGoal*>>
logical_to_mandatory_goals;

GdkKeymap* keymap;
gulong keymap_keys_changed_cb_id; // Signal connection ID for
// keymap-keys-changed
};

G_DEFINE_TYPE(FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT);

static void keymap_keys_changed_cb(FlKeyboardManager* self) {
g_clear_object(&self->derived_layout);
self->derived_layout = fl_keyboard_layout_new();
}

// This is an exact copy of g_ptr_array_find_with_equal_func. Somehow CI
// reports that can not find symbol g_ptr_array_find_with_equal_func, despite
// the fact that it runs well locally.
Expand Down Expand Up @@ -292,13 +304,18 @@ static void responder_handle_channel_event_callback(bool handled,
responder_handle_event_callback(handled, user_data_ptr, FALSE);
}

static uint16_t convert_key_to_char(FlKeyboardViewDelegate* view_delegate,
static uint16_t convert_key_to_char(FlKeyboardManager* self,
guint keycode,
gint group,
gint level) {
GdkKeymapKey key = {keycode, group, level};
constexpr int kBmpMax = 0xD7FF;
guint origin = fl_keyboard_view_delegate_lookup_key(view_delegate, &key);
guint origin;
if (self->lookup_key_handler != nullptr) {
origin = self->lookup_key_handler(&key, self->lookup_key_handler_user_data);
} else {
origin = gdk_keymap_lookup_key(self->keymap, &key);
}
return origin < kBmpMax ? origin : 0xFFFF;
}

Expand Down Expand Up @@ -329,8 +346,8 @@ static void guarantee_layout(FlKeyboardManager* self, FlKeyEvent* event) {
std::string debug_layout_data;
for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
std::vector<uint16_t> this_key_clues = {
convert_key_to_char(view_delegate, keycode, group, 0),
convert_key_to_char(view_delegate, keycode, group, 1), // Shift
convert_key_to_char(self, keycode, group, 0),
convert_key_to_char(self, keycode, group, 1), // Shift
};
debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
this_key_clues[1]);
Expand All @@ -344,8 +361,8 @@ static void guarantee_layout(FlKeyboardManager* self, FlKeyEvent* event) {
for (const LayoutGoal& keycode_goal : layout_goals) {
uint16_t keycode = keycode_goal.keycode;
std::vector<uint16_t> this_key_clues = {
convert_key_to_char(view_delegate, keycode, group, 0),
convert_key_to_char(view_delegate, keycode, group, 1), // Shift
convert_key_to_char(self, keycode, group, 0),
convert_key_to_char(self, keycode, group, 1), // Shift
};

// The logical key should be the first available clue from below:
Expand Down Expand Up @@ -404,6 +421,10 @@ static void fl_keyboard_manager_dispose(GObject* object) {
g_ptr_array_free(self->pending_responds, TRUE);
g_ptr_array_free(self->pending_redispatches, TRUE);
g_clear_object(&self->derived_layout);
if (self->keymap_keys_changed_cb_id != 0) {
g_signal_handler_disconnect(self->keymap, self->keymap_keys_changed_cb_id);
self->keymap_keys_changed_cb_id = 0;
}

G_OBJECT_CLASS(fl_keyboard_manager_parent_class)->dispose(object);
}
Expand All @@ -430,6 +451,10 @@ static void fl_keyboard_manager_init(FlKeyboardManager* self) {
self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);

self->last_sequence_id = 1;

self->keymap = gdk_keymap_get_for_display(gdk_display_get_default());
self->keymap_keys_changed_cb_id = g_signal_connect_swapped(
self->keymap, "keys-changed", G_CALLBACK(keymap_keys_changed_cb), self);
}

FlKeyboardManager* fl_keyboard_manager_new(
Expand Down Expand Up @@ -511,16 +536,25 @@ GHashTable* fl_keyboard_manager_get_pressed_state(FlKeyboardManager* self) {
self->key_embedder_responder);
}

void fl_keyboard_manager_set_lookup_key_handler(
FlKeyboardManager* self,
FlKeyboardManagerLookupKeyHandler lookup_key_handler,
gpointer user_data) {
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
self->lookup_key_handler = lookup_key_handler;
self->lookup_key_handler_user_data = user_data;
}

void fl_keyboard_manager_notify_layout_changed(FlKeyboardManager* self) {
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
g_clear_object(&self->derived_layout);
self->derived_layout = fl_keyboard_layout_new();
keymap_keys_changed_cb(self);
}

void fl_keyboard_manager_set_redispatch_handler(
FlKeyboardManager* self,
FlKeyboardManagerRedispatchEventHandler redispatch_handler,
gpointer user_data) {
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
self->redispatch_handler = redispatch_handler;
self->redispatch_handler_user_data = user_data;
}
17 changes: 16 additions & 1 deletion shell/platform/linux/fl_keyboard_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,26 @@ void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager* manager,
*/
GHashTable* fl_keyboard_manager_get_pressed_state(FlKeyboardManager* manager);

typedef guint (*FlKeyboardManagerLookupKeyHandler)(const GdkKeymapKey* key,
gpointer user_data);

/**
* fl_keyboard_manager_set_lookup_key_handler:
* @manager: the #FlKeyboardManager self.
*
* Set the handler for key lookup, for testing purposes only.
*/
void fl_keyboard_manager_set_lookup_key_handler(
FlKeyboardManager* manager,
FlKeyboardManagerLookupKeyHandler lookup_key_handler,
gpointer user_data);

/**
* fl_keyboard_manager_notify_layout_changed:
* @manager: the #FlKeyboardManager self.
*
* Notify the manager the keyboard layout has changed.
* Notify the manager the keyboard layout has changed, for testing purposes
* only.
*/
void fl_keyboard_manager_notify_layout_changed(FlKeyboardManager* manager);

Expand Down
37 changes: 16 additions & 21 deletions shell/platform/linux/fl_keyboard_manager_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ struct _FlMockViewDelegate {
FlMockKeyBinaryMessenger* messenger;
EmbedderCallHandler embedder_handler;
bool text_filter_result;
const MockLayoutData* layout_data;
};

static void fl_mock_view_keyboard_delegate_iface_init(
Expand Down Expand Up @@ -329,24 +328,10 @@ static gboolean fl_mock_view_keyboard_text_filter_key_press(
return self->text_filter_result;
}

static guint fl_mock_view_keyboard_lookup_key(
FlKeyboardViewDelegate* view_delegate,
const GdkKeymapKey* key) {
FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate);
guint8 group = static_cast<guint8>(key->group);
EXPECT_LT(group, self->layout_data->size());
const MockGroupLayoutData* group_layout = (*self->layout_data)[group];
EXPECT_TRUE(group_layout != nullptr);
EXPECT_TRUE(key->level == 0 || key->level == 1);
bool shift = key->level == 1;
return (*group_layout)[key->keycode * 2 + shift];
}

static void fl_mock_view_keyboard_delegate_iface_init(
FlKeyboardViewDelegateInterface* iface) {
iface->send_key_event = fl_mock_view_keyboard_send_key_event;
iface->text_filter_key_press = fl_mock_view_keyboard_text_filter_key_press;
iface->lookup_key = fl_mock_view_keyboard_lookup_key;
}

static FlMockViewDelegate* fl_mock_view_delegate_new() {
Expand All @@ -371,11 +356,6 @@ static void fl_mock_view_set_text_filter_result(FlMockViewDelegate* self,
self->text_filter_result = result;
}

static void fl_mock_view_set_layout(FlMockViewDelegate* self,
const MockLayoutData* layout) {
self->layout_data = layout;
}

/***** End FlMockViewDelegate *****/

class KeyboardTester {
Expand All @@ -389,6 +369,20 @@ class KeyboardTester {

manager_ = fl_keyboard_manager_new(FL_BINARY_MESSENGER(view_->messenger),
FL_KEYBOARD_VIEW_DELEGATE(view_));
fl_keyboard_manager_set_lookup_key_handler(
manager_,
[](const GdkKeymapKey* key, gpointer user_data) {
KeyboardTester* self = reinterpret_cast<KeyboardTester*>(user_data);
guint8 group = static_cast<guint8>(key->group);
EXPECT_LT(group, self->layout_data_->size());
const MockGroupLayoutData* group_layout =
(*self->layout_data_)[group];
EXPECT_TRUE(group_layout != nullptr);
EXPECT_TRUE(key->level == 0 || key->level == 1);
bool shift = key->level == 1;
return (*group_layout)[key->keycode * 2 + shift];
},
this);
fl_keyboard_manager_set_redispatch_handler(
manager_,
[](FlKeyEvent* event, gpointer user_data) {
Expand Down Expand Up @@ -516,7 +510,7 @@ class KeyboardTester {
}

void setLayout(const MockLayoutData& layout) {
fl_mock_view_set_layout(view_, &layout);
layout_data_ = &layout;
if (manager_ != nullptr) {
fl_keyboard_manager_notify_layout_changed(manager_);
}
Expand All @@ -527,6 +521,7 @@ class KeyboardTester {
FlKeyboardManager* manager_ = nullptr;
GPtrArray* redispatched_events_ = nullptr;
bool during_redispatch_ = false;
const MockLayoutData* layout_data_;

static gboolean _flushChannelMessagesCb(gpointer data) {
g_autoptr(GMainLoop) loop = reinterpret_cast<GMainLoop*>(data);
Expand Down
7 changes: 0 additions & 7 deletions shell/platform/linux/fl_keyboard_view_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@ gboolean fl_keyboard_view_delegate_text_filter_key_press(
self, event);
}

guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate* self,
const GdkKeymapKey* key) {
g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(self), 0);

return FL_KEYBOARD_VIEW_DELEGATE_GET_IFACE(self)->lookup_key(self, key);
}

GHashTable* fl_keyboard_view_delegate_get_keyboard_state(
FlKeyboardViewDelegate* self) {
g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(self), nullptr);
Expand Down
6 changes: 0 additions & 6 deletions shell/platform/linux/fl_keyboard_view_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ struct _FlKeyboardViewDelegateInterface {
gboolean (*text_filter_key_press)(FlKeyboardViewDelegate* delegate,
FlKeyEvent* event);

guint (*lookup_key)(FlKeyboardViewDelegate* view_delegate,
const GdkKeymapKey* key);

GHashTable* (*get_keyboard_state)(FlKeyboardViewDelegate* delegate);
};

Expand Down Expand Up @@ -77,9 +74,6 @@ gboolean fl_keyboard_view_delegate_text_filter_key_press(
FlKeyboardViewDelegate* delegate,
FlKeyEvent* event);

guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate* delegate,
const GdkKeymapKey* key);

/**
* fl_keyboard_view_delegate_get_keyboard_state:
*
Expand Down
25 changes: 0 additions & 25 deletions shell/platform/linux/fl_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,6 @@ struct _FlView {
// Tracks whether mouse pointer is inside the view.
gboolean pointer_inside;

/* FlKeyboardViewDelegate related properties */
GdkKeymap* keymap;
gulong keymap_keys_changed_cb_id; // Signal connection ID for
// keymap-keys-changed

// Accessible tree from Flutter, exposed as an AtkPlug.
FlViewAccessible* view_accessible;

Expand Down Expand Up @@ -385,13 +380,6 @@ static void fl_view_keyboard_delegate_iface_init(
event);
};

iface->lookup_key = [](FlKeyboardViewDelegate* view_delegate,
const GdkKeymapKey* key) -> guint {
FlView* self = FL_VIEW(view_delegate);
g_return_val_if_fail(self->keymap != nullptr, 0);
return gdk_keymap_lookup_key(self->keymap, key);
};

iface->get_keyboard_state =
[](FlKeyboardViewDelegate* view_delegate) -> GHashTable* {
FlView* self = FL_VIEW(view_delegate);
Expand Down Expand Up @@ -550,10 +538,6 @@ static gboolean leave_notify_event_cb(FlView* self,
return TRUE;
}

static void keymap_keys_changed_cb(FlView* self) {
fl_keyboard_manager_notify_layout_changed(self->keyboard_manager);
}

static void gesture_rotation_begin_cb(FlView* self) {
fl_scrolling_manager_handle_rotation_begin(self->scrolling_manager);
}
Expand Down Expand Up @@ -585,11 +569,6 @@ static GdkGLContext* create_context_cb(FlView* self) {
fl_renderer_gdk_set_window(self->renderer,
gtk_widget_get_parent_window(GTK_WIDGET(self)));

// Must initialize the keymap before the keyboard.
self->keymap = gdk_keymap_get_for_display(gdk_display_get_default());
self->keymap_keys_changed_cb_id = g_signal_connect_swapped(
self->keymap, "keys-changed", G_CALLBACK(keymap_keys_changed_cb), self);

// Create system channel handlers.
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
init_scrolling(self);
Expand Down Expand Up @@ -721,10 +700,6 @@ static void fl_view_dispose(GObject* object) {
g_clear_object(&self->window_state_monitor);
g_clear_object(&self->scrolling_manager);
g_clear_object(&self->keyboard_manager);
if (self->keymap_keys_changed_cb_id != 0) {
g_signal_handler_disconnect(self->keymap, self->keymap_keys_changed_cb_id);
self->keymap_keys_changed_cb_id = 0;
}
g_clear_object(&self->keyboard_handler);
g_clear_object(&self->mouse_cursor_handler);
g_clear_object(&self->platform_handler);
Expand Down

0 comments on commit cbaaeac

Please sign in to comment.