Flutter Linux Embedder
fl_key_channel_responder_test.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "flutter/shell/platform/linux/testing/linux_test.h"
8 #include "gtest/gtest.h"
9 
11 #include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
12 
13 typedef struct {
14  const gchar* expected_message;
15  gboolean handled;
16 } KeyEventData;
17 
18 static void set_key_event_channel(FlMockBinaryMessenger* messenger,
19  const gchar* expected_message,
20  gboolean handled) {
21  KeyEventData* data = g_new0(KeyEventData, 1);
22  data->expected_message = expected_message;
23  data->handled = handled;
24  fl_mock_binary_messenger_set_json_message_channel(
25  messenger, "flutter/keyevent",
26  [](FlMockBinaryMessenger* messenger, GTask* task, FlValue* message,
27  gpointer user_data) {
28  g_autofree KeyEventData* data = static_cast<KeyEventData*>(user_data);
29 
30  g_autofree gchar* message_string = fl_value_to_string(message);
31  EXPECT_STREQ(message_string, data->expected_message);
32 
33  FlValue* response = fl_value_new_map();
34  fl_value_set_string_take(response, "handled",
35  fl_value_new_bool(data->handled));
36 
37  return response;
38  },
39  data);
40 }
41 
42 class FlKeyChannelResponderTest : public flutter::testing::LinuxTest {
43  protected:
44  void SetUp() override {
45  messenger = fl_mock_binary_messenger_new();
46  responder = fl_key_channel_responder_new(FL_BINARY_MESSENGER(messenger));
47  }
48 
50  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
51  g_clear_object(&responder);
52  g_clear_object(&messenger);
53  }
54 
55  void TestLockEvent(guint key_code,
56  const char* down_expected,
57  const char* up_expected);
58 
59  FlMockBinaryMessenger* messenger = nullptr;
60  FlKeyChannelResponder* responder = nullptr;
61 };
62 
63 // Test sending a letter "A";
66  messenger,
67  "{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, keyCode: 65, "
68  "modifiers: 0, unicodeScalarValues: 65}",
69  FALSE);
70  g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
71  12345, TRUE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
73  responder, event1, 0, nullptr,
74  [](GObject* object, GAsyncResult* result, gpointer user_data) {
75  gboolean handled;
77  FL_KEY_CHANNEL_RESPONDER(object), result, &handled, nullptr));
78  EXPECT_FALSE(handled);
79  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
80  },
81  loop);
82  g_main_loop_run(loop);
83 
85  messenger,
86  "{type: keyup, keymap: linux, scanCode: 4, toolkit: gtk, keyCode: 65, "
87  "modifiers: 0, unicodeScalarValues: 65}",
88  FALSE);
89  g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
90  23456, FALSE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
92  responder, event2, 0, nullptr,
93  [](GObject* object, GAsyncResult* result, gpointer user_data) {
94  gboolean handled;
96  FL_KEY_CHANNEL_RESPONDER(object), result, &handled, nullptr));
97  EXPECT_FALSE(handled);
98  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
99  },
100  loop);
101  g_main_loop_run(loop);
102 }
103 
105  const char* down_expected,
106  const char* up_expected) {
107  set_key_event_channel(messenger, down_expected, FALSE);
108  g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
109  12345, TRUE, 0x04, key_code, static_cast<GdkModifierType>(0), 0);
111  responder, event1, 0, nullptr,
112  [](GObject* object, GAsyncResult* result, gpointer user_data) {
113  gboolean handled;
115  FL_KEY_CHANNEL_RESPONDER(object), result, &handled, nullptr));
116  EXPECT_FALSE(handled);
117  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
118  },
119  loop);
120  g_main_loop_run(loop);
121 
122  set_key_event_channel(messenger, up_expected, FALSE);
123  g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
124  12346, FALSE, 0x04, key_code, static_cast<GdkModifierType>(0), 0);
126  responder, event2, 0, nullptr,
127  [](GObject* object, GAsyncResult* result, gpointer user_data) {
128  gboolean handled;
130  FL_KEY_CHANNEL_RESPONDER(object), result, &handled, nullptr));
131  EXPECT_FALSE(handled);
132  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
133  },
134  loop);
135  g_main_loop_run(loop);
136 }
137 
138 // Test sending a "NumLock" keypress.
139 TEST_F(FlKeyChannelResponderTest, SendNumLockKeyEvent) {
140  TestLockEvent(GDK_KEY_Num_Lock,
141  "{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
142  "keyCode: 65407, modifiers: 16}",
143  "{type: keyup, keymap: linux, scanCode: 4, toolkit: gtk, "
144  "keyCode: 65407, modifiers: 0}");
145 }
146 
147 // Test sending a "CapsLock" keypress.
148 TEST_F(FlKeyChannelResponderTest, SendCapsLockKeyEvent) {
149  TestLockEvent(GDK_KEY_Caps_Lock,
150  "{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
151  "keyCode: 65509, modifiers: 2}",
152  "{type: keyup, keymap: linux, scanCode: 4, toolkit: gtk, "
153  "keyCode: 65509, modifiers: 0}");
154 }
155 
156 // Test sending a "ShiftLock" keypress.
157 TEST_F(FlKeyChannelResponderTest, SendShiftLockKeyEvent) {
158  TestLockEvent(GDK_KEY_Shift_Lock,
159  "{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
160  "keyCode: 65510, modifiers: 2}",
161  "{type: keyup, keymap: linux, scanCode: 4, toolkit: gtk, "
162  "keyCode: 65510, modifiers: 0}");
163 }
164 
165 TEST_F(FlKeyChannelResponderTest, TestKeyEventHandledByFramework) {
167  messenger,
168  "{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
169  "keyCode: 65, modifiers: 0, unicodeScalarValues: 65}",
170  TRUE);
171  g_autoptr(FlKeyEvent) event = fl_key_event_new(
172  12345, TRUE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
174  responder, event, 0, nullptr,
175  [](GObject* object, GAsyncResult* result, gpointer user_data) {
176  gboolean handled;
178  FL_KEY_CHANNEL_RESPONDER(object), result, &handled, nullptr));
179  EXPECT_TRUE(handled);
180  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
181  },
182  loop);
183  g_main_loop_run(loop);
184 }
185 
186 TEST_F(FlKeyChannelResponderTest, UseSpecifiedLogicalKey) {
188  messenger,
189  "{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
190  "keyCode: 65, modifiers: 0, unicodeScalarValues: 65, "
191  "specifiedLogicalKey: 888}",
192  TRUE);
193  g_autoptr(FlKeyEvent) event = fl_key_event_new(
194  12345, TRUE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
196  responder, event, 888, nullptr,
197  [](GObject* object, GAsyncResult* result, gpointer user_data) {
198  gboolean handled;
200  FL_KEY_CHANNEL_RESPONDER(object), result, &handled, nullptr));
201  EXPECT_TRUE(handled);
202  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
203  },
204  loop);
205  g_main_loop_run(loop);
206 }
void TestLockEvent(guint key_code, const char *down_expected, const char *up_expected)
const char * message
g_autoptr(FlEngine) engine
const char FlTextDirection FlAssertiveness gpointer user_data
void fl_binary_messenger_shutdown(FlBinaryMessenger *self)
return TRUE
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)
TEST_F(FlKeyChannelResponderTest, SendKeyEvent)
static void set_key_event_channel(FlMockBinaryMessenger *messenger, const gchar *expected_message, gboolean handled)
FlKeyEvent * fl_key_event_new(guint32 time, gboolean is_press, guint16 keycode, guint keyval, GdkModifierType state, guint8 group)
Definition: fl_key_event.cc:34
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
G_MODULE_EXPORT gchar * fl_value_to_string(FlValue *value)
Definition: fl_value.cc:846
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:255
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42