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

Commit 72f7a7c

Browse files
Add FlKeyEventPlugin (#18313)
1 parent 6c5f239 commit 72f7a7c

File tree

5 files changed

+343
-3
lines changed

5 files changed

+343
-3
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_json_message_codec.cc
12021202
FILE: ../../../flutter/shell/platform/linux/fl_json_message_codec_test.cc
12031203
FILE: ../../../flutter/shell/platform/linux/fl_json_method_codec.cc
12041204
FILE: ../../../flutter/shell/platform/linux/fl_json_method_codec_test.cc
1205+
FILE: ../../../flutter/shell/platform/linux/fl_key_event_plugin.cc
1206+
FILE: ../../../flutter/shell/platform/linux/fl_key_event_plugin.h
12051207
FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc
12061208
FILE: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc
12071209
FILE: ../../../flutter/shell/platform/linux/fl_method_call.cc

shell/platform/linux/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ source_set("flutter_linux") {
7979
"fl_engine.cc",
8080
"fl_json_message_codec.cc",
8181
"fl_json_method_codec.cc",
82+
"fl_key_event_plugin.cc",
8283
"fl_message_codec.cc",
8384
"fl_method_call.cc",
8485
"fl_method_channel.cc",
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
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+
5+
#include "flutter/shell/platform/linux/fl_key_event_plugin.h"
6+
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
7+
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
8+
9+
static constexpr char kChannelName[] = "flutter/keyevent";
10+
static constexpr char kTypeKey[] = "type";
11+
static constexpr char kTypeValueUp[] = "keyup";
12+
static constexpr char kTypeValueDown[] = "keydown";
13+
static constexpr char kKeymapKey[] = "keymap";
14+
static constexpr char kKeyCodeKey[] = "keyCode";
15+
static constexpr char kScanCodeKey[] = "scanCode";
16+
static constexpr char kModifiersKey[] = "modifiers";
17+
static constexpr char kToolkitKey[] = "toolkit";
18+
static constexpr char kUnicodeScalarValuesKey[] = "unicodeScalarValues";
19+
20+
static constexpr char kGLFWToolkit[] = "glfw";
21+
static constexpr char kLinuxKeymap[] = "linux";
22+
23+
struct _FlKeyEventPlugin {
24+
GObject parent_instance;
25+
26+
FlBasicMessageChannel* channel;
27+
};
28+
29+
G_DEFINE_TYPE(FlKeyEventPlugin, fl_key_event_plugin, G_TYPE_OBJECT)
30+
31+
// Converts a Gdk key code to its GLFW equivalent.
32+
// TODO(robert-ancell) Create a "gtk" toolkit in Flutter so we don't have to
33+
// convert values. https://github.com/flutter/flutter/issues/57603
34+
static int gdk_keyval_to_glfw_key_code(guint keyval) {
35+
switch (keyval) {
36+
case GDK_KEY_space:
37+
return 32;
38+
case GDK_KEY_apostrophe:
39+
return 39;
40+
case GDK_KEY_comma:
41+
return 44;
42+
case GDK_KEY_minus:
43+
return 45;
44+
case GDK_KEY_period:
45+
return 46;
46+
case GDK_KEY_slash:
47+
return 47;
48+
case GDK_KEY_0:
49+
return 48;
50+
case GDK_KEY_1:
51+
return 49;
52+
case GDK_KEY_2:
53+
return 50;
54+
case GDK_KEY_3:
55+
return 51;
56+
case GDK_KEY_4:
57+
return 52;
58+
case GDK_KEY_5:
59+
return 53;
60+
case GDK_KEY_6:
61+
return 54;
62+
case GDK_KEY_7:
63+
return 55;
64+
case GDK_KEY_8:
65+
return 56;
66+
case GDK_KEY_9:
67+
return 57;
68+
case GDK_KEY_semicolon:
69+
return 59;
70+
case GDK_KEY_equal:
71+
return 61;
72+
case GDK_KEY_a:
73+
return 65;
74+
case GDK_KEY_b:
75+
return 66;
76+
case GDK_KEY_c:
77+
return 67;
78+
case GDK_KEY_d:
79+
return 68;
80+
case GDK_KEY_e:
81+
return 69;
82+
case GDK_KEY_f:
83+
return 70;
84+
case GDK_KEY_g:
85+
return 71;
86+
case GDK_KEY_h:
87+
return 72;
88+
case GDK_KEY_i:
89+
return 73;
90+
case GDK_KEY_j:
91+
return 74;
92+
case GDK_KEY_k:
93+
return 75;
94+
case GDK_KEY_l:
95+
return 76;
96+
case GDK_KEY_m:
97+
return 77;
98+
case GDK_KEY_n:
99+
return 78;
100+
case GDK_KEY_o:
101+
return 79;
102+
case GDK_KEY_p:
103+
return 80;
104+
case GDK_KEY_q:
105+
return 81;
106+
case GDK_KEY_r:
107+
return 82;
108+
case GDK_KEY_s:
109+
return 83;
110+
case GDK_KEY_t:
111+
return 84;
112+
case GDK_KEY_u:
113+
return 85;
114+
case GDK_KEY_v:
115+
return 86;
116+
case GDK_KEY_w:
117+
return 87;
118+
case GDK_KEY_x:
119+
return 88;
120+
case GDK_KEY_y:
121+
return 89;
122+
case GDK_KEY_z:
123+
return 90;
124+
case GDK_KEY_bracketleft:
125+
return 91;
126+
case GDK_KEY_bracketright:
127+
return 92;
128+
case GDK_KEY_grave:
129+
return 96;
130+
case GDK_KEY_Escape:
131+
return 256;
132+
case GDK_KEY_Return:
133+
return 257;
134+
case GDK_KEY_Tab:
135+
return 258;
136+
case GDK_KEY_BackSpace:
137+
return 259;
138+
case GDK_KEY_Insert:
139+
return 260;
140+
case GDK_KEY_Delete:
141+
return 261;
142+
case GDK_KEY_Right:
143+
return 262;
144+
case GDK_KEY_Left:
145+
return 263;
146+
case GDK_KEY_Down:
147+
return 264;
148+
case GDK_KEY_Up:
149+
return 265;
150+
case GDK_KEY_Page_Up:
151+
return 266;
152+
case GDK_KEY_Page_Down:
153+
return 267;
154+
case GDK_KEY_Home:
155+
return 268;
156+
case GDK_KEY_End:
157+
return 269;
158+
case GDK_KEY_Shift_L:
159+
return 340;
160+
case GDK_KEY_Control_L:
161+
return 341;
162+
case GDK_KEY_Alt_L:
163+
return 342;
164+
case GDK_KEY_Super_L:
165+
return 343;
166+
case GDK_KEY_Shift_R:
167+
return 344;
168+
case GDK_KEY_Control_R:
169+
return 345;
170+
case GDK_KEY_Alt_R:
171+
return 346;
172+
case GDK_KEY_Super_R:
173+
return 347;
174+
default:
175+
return 0;
176+
}
177+
}
178+
179+
// Converts a Gdk key state to its GLFW equivalent.
180+
int64_t gdk_state_to_glfw_modifiers(guint8 state) {
181+
int64_t modifiers = 0;
182+
183+
if ((state & GDK_SHIFT_MASK) != 0)
184+
modifiers |= 0x0001;
185+
if ((state & GDK_CONTROL_MASK) != 0)
186+
modifiers |= 0x0002;
187+
if ((state & GDK_MOD1_MASK) != 0)
188+
modifiers |= 0x0004;
189+
if ((state & GDK_SUPER_MASK) != 0)
190+
modifiers |= 0x0008;
191+
192+
return modifiers;
193+
}
194+
195+
static void fl_key_event_plugin_dispose(GObject* object) {
196+
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(object);
197+
198+
g_clear_object(&self->channel);
199+
200+
G_OBJECT_CLASS(fl_key_event_plugin_parent_class)->dispose(object);
201+
}
202+
203+
static void fl_key_event_plugin_class_init(FlKeyEventPluginClass* klass) {
204+
G_OBJECT_CLASS(klass)->dispose = fl_key_event_plugin_dispose;
205+
}
206+
207+
static void fl_key_event_plugin_init(FlKeyEventPlugin* self) {}
208+
209+
FlKeyEventPlugin* fl_key_event_plugin_new(FlBinaryMessenger* messenger) {
210+
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
211+
212+
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(
213+
g_object_new(fl_key_event_plugin_get_type(), nullptr));
214+
215+
g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
216+
self->channel = fl_basic_message_channel_new(messenger, kChannelName,
217+
FL_MESSAGE_CODEC(codec));
218+
219+
return self;
220+
}
221+
222+
void fl_key_event_plugin_send_key_event(FlKeyEventPlugin* self,
223+
GdkEventKey* event) {
224+
g_return_if_fail(FL_IS_KEY_EVENT_PLUGIN(self));
225+
g_return_if_fail(event != nullptr);
226+
227+
const gchar* type;
228+
if (event->type == GDK_KEY_PRESS)
229+
type = kTypeValueDown;
230+
else if (event->type == GDK_KEY_RELEASE)
231+
type = kTypeValueUp;
232+
else
233+
return;
234+
235+
int64_t scan_code = event->hardware_keycode;
236+
int64_t key_code = gdk_keyval_to_glfw_key_code(event->keyval);
237+
int64_t modifiers = gdk_state_to_glfw_modifiers(event->state);
238+
int64_t unicodeScalarValues = gdk_keyval_to_unicode(event->keyval);
239+
240+
g_autoptr(FlValue) message = fl_value_new_map();
241+
fl_value_set_string_take(message, kTypeKey, fl_value_new_string(type));
242+
fl_value_set_string_take(message, kKeymapKey,
243+
fl_value_new_string(kLinuxKeymap));
244+
fl_value_set_string_take(message, kScanCodeKey, fl_value_new_int(scan_code));
245+
fl_value_set_string_take(message, kToolkitKey,
246+
fl_value_new_string(kGLFWToolkit));
247+
fl_value_set_string_take(message, kKeyCodeKey, fl_value_new_int(key_code));
248+
fl_value_set_string_take(message, kModifiersKey, fl_value_new_int(modifiers));
249+
if (unicodeScalarValues != 0)
250+
fl_value_set_string_take(message, kUnicodeScalarValuesKey,
251+
fl_value_new_int(unicodeScalarValues));
252+
253+
fl_basic_message_channel_send(self->channel, message, nullptr, nullptr,
254+
nullptr);
255+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
5+
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_PLUGIN_H_
6+
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_PLUGIN_H_
7+
8+
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
9+
10+
#include <gdk/gdk.h>
11+
12+
G_BEGIN_DECLS
13+
14+
G_DECLARE_FINAL_TYPE(FlKeyEventPlugin,
15+
fl_key_event_plugin,
16+
FL,
17+
KEY_EVENT_PLUGIN,
18+
GObject);
19+
20+
/**
21+
* FlKeyEventPlugin:
22+
*
23+
* #FlKeyEventPlugin is a plugin that implements the shell side
24+
* of SystemChannels.keyEvent from the Flutter services library.
25+
*/
26+
27+
/**
28+
* fl_key_event_plugin_new:
29+
* @messenger: an #FlBinaryMessenger.
30+
*
31+
* Creates a #FlKeyEventPlugin.
32+
*
33+
* Returns: a new #FlKeyEventPlugin.
34+
*/
35+
FlKeyEventPlugin* fl_key_event_plugin_new(FlBinaryMessenger* messenger);
36+
37+
/**
38+
* fl_key_event_plugin_send_key_event:
39+
* @plugin: an #FlKeyEventPlugin.
40+
* @event: a #GdkEventKey.
41+
*
42+
* Sends a key event to Flutter.
43+
*/
44+
void fl_key_event_plugin_send_key_event(FlKeyEventPlugin* plugin,
45+
GdkEventKey* event);
46+
47+
G_END_DECLS
48+
49+
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_PLUGIN_H_

0 commit comments

Comments
 (0)