Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit dd37446

Browse files
Move keymap from FlKeyboardViewDelegate to FlKeyboardManager (#55942)
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.
1 parent 0d8a876 commit dd37446

File tree

9 files changed

+153
-68
lines changed

9 files changed

+153
-68
lines changed

shell/platform/linux/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ executable("flutter_linux_unittests") {
248248
"testing/mock_engine.cc",
249249
"testing/mock_epoxy.cc",
250250
"testing/mock_im_context.cc",
251+
"testing/mock_keymap.cc",
251252
"testing/mock_plugin_registrar.cc",
252253
"testing/mock_renderer.cc",
253254
"testing/mock_settings.cc",

shell/platform/linux/fl_keyboard_manager.cc

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ struct _FlKeyboardManager {
118118

119119
GWeakRef view_delegate;
120120

121+
FlKeyboardManagerLookupKeyHandler lookup_key_handler;
122+
gpointer lookup_key_handler_user_data;
123+
121124
FlKeyboardManagerRedispatchEventHandler redispatch_handler;
122125
gpointer redispatch_handler_user_data;
123126

@@ -157,10 +160,19 @@ struct _FlKeyboardManager {
157160
// It is set up when the manager is initialized and is not changed ever after.
158161
std::unique_ptr<std::map<uint64_t, const LayoutGoal*>>
159162
logical_to_mandatory_goals;
163+
164+
GdkKeymap* keymap;
165+
gulong keymap_keys_changed_cb_id; // Signal connection ID for
166+
// keymap-keys-changed
160167
};
161168

162169
G_DEFINE_TYPE(FlKeyboardManager, fl_keyboard_manager, G_TYPE_OBJECT);
163170

171+
static void keymap_keys_changed_cb(FlKeyboardManager* self) {
172+
g_clear_object(&self->derived_layout);
173+
self->derived_layout = fl_keyboard_layout_new();
174+
}
175+
164176
// This is an exact copy of g_ptr_array_find_with_equal_func. Somehow CI
165177
// reports that can not find symbol g_ptr_array_find_with_equal_func, despite
166178
// the fact that it runs well locally.
@@ -292,13 +304,18 @@ static void responder_handle_channel_event_callback(bool handled,
292304
responder_handle_event_callback(handled, user_data_ptr, FALSE);
293305
}
294306

295-
static uint16_t convert_key_to_char(FlKeyboardViewDelegate* view_delegate,
307+
static uint16_t convert_key_to_char(FlKeyboardManager* self,
296308
guint keycode,
297309
gint group,
298310
gint level) {
299311
GdkKeymapKey key = {keycode, group, level};
300312
constexpr int kBmpMax = 0xD7FF;
301-
guint origin = fl_keyboard_view_delegate_lookup_key(view_delegate, &key);
313+
guint origin;
314+
if (self->lookup_key_handler != nullptr) {
315+
origin = self->lookup_key_handler(&key, self->lookup_key_handler_user_data);
316+
} else {
317+
origin = gdk_keymap_lookup_key(self->keymap, &key);
318+
}
302319
return origin < kBmpMax ? origin : 0xFFFF;
303320
}
304321

@@ -329,8 +346,8 @@ static void guarantee_layout(FlKeyboardManager* self, FlKeyEvent* event) {
329346
std::string debug_layout_data;
330347
for (uint16_t keycode = 0; keycode < 128; keycode += 1) {
331348
std::vector<uint16_t> this_key_clues = {
332-
convert_key_to_char(view_delegate, keycode, group, 0),
333-
convert_key_to_char(view_delegate, keycode, group, 1), // Shift
349+
convert_key_to_char(self, keycode, group, 0),
350+
convert_key_to_char(self, keycode, group, 1), // Shift
334351
};
335352
debug_format_layout_data(debug_layout_data, keycode, this_key_clues[0],
336353
this_key_clues[1]);
@@ -344,8 +361,8 @@ static void guarantee_layout(FlKeyboardManager* self, FlKeyEvent* event) {
344361
for (const LayoutGoal& keycode_goal : layout_goals) {
345362
uint16_t keycode = keycode_goal.keycode;
346363
std::vector<uint16_t> this_key_clues = {
347-
convert_key_to_char(view_delegate, keycode, group, 0),
348-
convert_key_to_char(view_delegate, keycode, group, 1), // Shift
364+
convert_key_to_char(self, keycode, group, 0),
365+
convert_key_to_char(self, keycode, group, 1), // Shift
349366
};
350367

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

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

432453
self->last_sequence_id = 1;
454+
455+
self->keymap = gdk_keymap_get_for_display(gdk_display_get_default());
456+
self->keymap_keys_changed_cb_id = g_signal_connect_swapped(
457+
self->keymap, "keys-changed", G_CALLBACK(keymap_keys_changed_cb), self);
433458
}
434459

435460
FlKeyboardManager* fl_keyboard_manager_new(
@@ -511,16 +536,25 @@ GHashTable* fl_keyboard_manager_get_pressed_state(FlKeyboardManager* self) {
511536
self->key_embedder_responder);
512537
}
513538

539+
void fl_keyboard_manager_set_lookup_key_handler(
540+
FlKeyboardManager* self,
541+
FlKeyboardManagerLookupKeyHandler lookup_key_handler,
542+
gpointer user_data) {
543+
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
544+
self->lookup_key_handler = lookup_key_handler;
545+
self->lookup_key_handler_user_data = user_data;
546+
}
547+
514548
void fl_keyboard_manager_notify_layout_changed(FlKeyboardManager* self) {
515549
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
516-
g_clear_object(&self->derived_layout);
517-
self->derived_layout = fl_keyboard_layout_new();
550+
keymap_keys_changed_cb(self);
518551
}
519552

520553
void fl_keyboard_manager_set_redispatch_handler(
521554
FlKeyboardManager* self,
522555
FlKeyboardManagerRedispatchEventHandler redispatch_handler,
523556
gpointer user_data) {
557+
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
524558
self->redispatch_handler = redispatch_handler;
525559
self->redispatch_handler_user_data = user_data;
526560
}

shell/platform/linux/fl_keyboard_manager.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,26 @@ void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager* manager,
9494
*/
9595
GHashTable* fl_keyboard_manager_get_pressed_state(FlKeyboardManager* manager);
9696

97+
typedef guint (*FlKeyboardManagerLookupKeyHandler)(const GdkKeymapKey* key,
98+
gpointer user_data);
99+
100+
/**
101+
* fl_keyboard_manager_set_lookup_key_handler:
102+
* @manager: the #FlKeyboardManager self.
103+
*
104+
* Set the handler for key lookup, for testing purposes only.
105+
*/
106+
void fl_keyboard_manager_set_lookup_key_handler(
107+
FlKeyboardManager* manager,
108+
FlKeyboardManagerLookupKeyHandler lookup_key_handler,
109+
gpointer user_data);
110+
97111
/**
98112
* fl_keyboard_manager_notify_layout_changed:
99113
* @manager: the #FlKeyboardManager self.
100114
*
101-
* Notify the manager the keyboard layout has changed.
115+
* Notify the manager the keyboard layout has changed, for testing purposes
116+
* only.
102117
*/
103118
void fl_keyboard_manager_notify_layout_changed(FlKeyboardManager* manager);
104119

shell/platform/linux/fl_keyboard_manager_test.cc

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h"
1616
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
1717
#include "flutter/shell/platform/linux/testing/fl_test.h"
18+
#include "flutter/shell/platform/linux/testing/mock_keymap.h"
1819
#include "flutter/shell/platform/linux/testing/mock_text_input_handler.h"
1920
#include "flutter/testing/testing.h"
2021

@@ -282,7 +283,6 @@ struct _FlMockViewDelegate {
282283
FlMockKeyBinaryMessenger* messenger;
283284
EmbedderCallHandler embedder_handler;
284285
bool text_filter_result;
285-
const MockLayoutData* layout_data;
286286
};
287287

288288
static void fl_mock_view_keyboard_delegate_iface_init(
@@ -329,24 +329,10 @@ static gboolean fl_mock_view_keyboard_text_filter_key_press(
329329
return self->text_filter_result;
330330
}
331331

332-
static guint fl_mock_view_keyboard_lookup_key(
333-
FlKeyboardViewDelegate* view_delegate,
334-
const GdkKeymapKey* key) {
335-
FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate);
336-
guint8 group = static_cast<guint8>(key->group);
337-
EXPECT_LT(group, self->layout_data->size());
338-
const MockGroupLayoutData* group_layout = (*self->layout_data)[group];
339-
EXPECT_TRUE(group_layout != nullptr);
340-
EXPECT_TRUE(key->level == 0 || key->level == 1);
341-
bool shift = key->level == 1;
342-
return (*group_layout)[key->keycode * 2 + shift];
343-
}
344-
345332
static void fl_mock_view_keyboard_delegate_iface_init(
346333
FlKeyboardViewDelegateInterface* iface) {
347334
iface->send_key_event = fl_mock_view_keyboard_send_key_event;
348335
iface->text_filter_key_press = fl_mock_view_keyboard_text_filter_key_press;
349-
iface->lookup_key = fl_mock_view_keyboard_lookup_key;
350336
}
351337

352338
static FlMockViewDelegate* fl_mock_view_delegate_new() {
@@ -371,11 +357,6 @@ static void fl_mock_view_set_text_filter_result(FlMockViewDelegate* self,
371357
self->text_filter_result = result;
372358
}
373359

374-
static void fl_mock_view_set_layout(FlMockViewDelegate* self,
375-
const MockLayoutData* layout) {
376-
self->layout_data = layout;
377-
}
378-
379360
/***** End FlMockViewDelegate *****/
380361

381362
class KeyboardTester {
@@ -389,6 +370,20 @@ class KeyboardTester {
389370

390371
manager_ = fl_keyboard_manager_new(FL_BINARY_MESSENGER(view_->messenger),
391372
FL_KEYBOARD_VIEW_DELEGATE(view_));
373+
fl_keyboard_manager_set_lookup_key_handler(
374+
manager_,
375+
[](const GdkKeymapKey* key, gpointer user_data) {
376+
KeyboardTester* self = reinterpret_cast<KeyboardTester*>(user_data);
377+
guint8 group = static_cast<guint8>(key->group);
378+
EXPECT_LT(group, self->layout_data_->size());
379+
const MockGroupLayoutData* group_layout =
380+
(*self->layout_data_)[group];
381+
EXPECT_TRUE(group_layout != nullptr);
382+
EXPECT_TRUE(key->level == 0 || key->level == 1);
383+
bool shift = key->level == 1;
384+
return (*group_layout)[key->keycode * 2 + shift];
385+
},
386+
this);
392387
fl_keyboard_manager_set_redispatch_handler(
393388
manager_,
394389
[](FlKeyEvent* event, gpointer user_data) {
@@ -516,7 +511,7 @@ class KeyboardTester {
516511
}
517512

518513
void setLayout(const MockLayoutData& layout) {
519-
fl_mock_view_set_layout(view_, &layout);
514+
layout_data_ = &layout;
520515
if (manager_ != nullptr) {
521516
fl_keyboard_manager_notify_layout_changed(manager_);
522517
}
@@ -527,6 +522,7 @@ class KeyboardTester {
527522
FlKeyboardManager* manager_ = nullptr;
528523
GPtrArray* redispatched_events_ = nullptr;
529524
bool during_redispatch_ = false;
525+
const MockLayoutData* layout_data_;
530526

531527
static gboolean _flushChannelMessagesCb(gpointer data) {
532528
g_autoptr(GMainLoop) loop = reinterpret_cast<GMainLoop*>(data);
@@ -538,6 +534,7 @@ class KeyboardTester {
538534
// Make sure that the keyboard can be disposed without crashes when there are
539535
// unresolved pending events.
540536
TEST(FlKeyboardManagerTest, DisposeWithUnresolvedPends) {
537+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
541538
KeyboardTester tester;
542539
std::vector<CallRecord> call_records;
543540

@@ -558,6 +555,7 @@ TEST(FlKeyboardManagerTest, DisposeWithUnresolvedPends) {
558555
}
559556

560557
TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
558+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
561559
KeyboardTester tester;
562560
std::vector<CallRecord> call_records;
563561
g_autoptr(GPtrArray) redispatched =
@@ -645,6 +643,7 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
645643
}
646644

647645
TEST(FlKeyboardManagerTest, SingleDelegateWithSyncResponds) {
646+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
648647
KeyboardTester tester;
649648
gboolean handler_handled = false;
650649
std::vector<CallRecord> call_records;
@@ -692,6 +691,7 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithSyncResponds) {
692691
}
693692

694693
TEST(FlKeyboardManagerTest, WithTwoAsyncDelegates) {
694+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
695695
KeyboardTester tester;
696696
std::vector<CallRecord> call_records;
697697
g_autoptr(GPtrArray) redispatched =
@@ -751,6 +751,7 @@ TEST(FlKeyboardManagerTest, WithTwoAsyncDelegates) {
751751
}
752752

753753
TEST(FlKeyboardManagerTest, TextInputHandlerReturnsFalse) {
754+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
754755
KeyboardTester tester;
755756
g_autoptr(GPtrArray) redispatched =
756757
g_ptr_array_new_with_free_func(g_object_unref);
@@ -774,6 +775,7 @@ TEST(FlKeyboardManagerTest, TextInputHandlerReturnsFalse) {
774775
}
775776

776777
TEST(FlKeyboardManagerTest, TextInputHandlerReturnsTrue) {
778+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
777779
KeyboardTester tester;
778780
g_autoptr(GPtrArray) redispatched =
779781
g_ptr_array_new_with_free_func(g_object_unref);
@@ -794,6 +796,7 @@ TEST(FlKeyboardManagerTest, TextInputHandlerReturnsTrue) {
794796
}
795797

796798
TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
799+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
797800
KeyboardTester tester;
798801

799802
std::vector<CallRecord> call_records;
@@ -887,6 +890,7 @@ TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
887890
}
888891

889892
TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
893+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
890894
KeyboardTester tester;
891895
std::vector<CallRecord> call_records;
892896
tester.recordEmbedderCallsTo(call_records);
@@ -925,6 +929,7 @@ TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
925929
}
926930

927931
TEST(FlKeyboardManagerTest, GetPressedState) {
932+
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
928933
KeyboardTester tester;
929934
tester.respondToTextInputWith(true);
930935

shell/platform/linux/fl_keyboard_view_delegate.cc

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@ gboolean fl_keyboard_view_delegate_text_filter_key_press(
3232
self, event);
3333
}
3434

35-
guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate* self,
36-
const GdkKeymapKey* key) {
37-
g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(self), 0);
38-
39-
return FL_KEYBOARD_VIEW_DELEGATE_GET_IFACE(self)->lookup_key(self, key);
40-
}
41-
4235
GHashTable* fl_keyboard_view_delegate_get_keyboard_state(
4336
FlKeyboardViewDelegate* self) {
4437
g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(self), nullptr);

shell/platform/linux/fl_keyboard_view_delegate.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ struct _FlKeyboardViewDelegateInterface {
4242
gboolean (*text_filter_key_press)(FlKeyboardViewDelegate* delegate,
4343
FlKeyEvent* event);
4444

45-
guint (*lookup_key)(FlKeyboardViewDelegate* view_delegate,
46-
const GdkKeymapKey* key);
47-
4845
GHashTable* (*get_keyboard_state)(FlKeyboardViewDelegate* delegate);
4946
};
5047

@@ -77,9 +74,6 @@ gboolean fl_keyboard_view_delegate_text_filter_key_press(
7774
FlKeyboardViewDelegate* delegate,
7875
FlKeyEvent* event);
7976

80-
guint fl_keyboard_view_delegate_lookup_key(FlKeyboardViewDelegate* delegate,
81-
const GdkKeymapKey* key);
82-
8377
/**
8478
* fl_keyboard_view_delegate_get_keyboard_state:
8579
*

0 commit comments

Comments
 (0)