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

Commit 3bd3591

Browse files
committed
Add FlKeyEventChannel
1 parent 5ad4f9e commit 3bd3591

File tree

5 files changed

+296
-2
lines changed

5 files changed

+296
-2
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_engine.cc
11961196
FILE: ../../../flutter/shell/platform/linux/fl_engine_private.h
11971197
FILE: ../../../flutter/shell/platform/linux/fl_json_message_codec.cc
11981198
FILE: ../../../flutter/shell/platform/linux/fl_json_message_codec_test.cc
1199+
FILE: ../../../flutter/shell/platform/linux/fl_key_event_channel.cc
1200+
FILE: ../../../flutter/shell/platform/linux/fl_key_event_channel.h
11991201
FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc
12001202
FILE: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc
12011203
FILE: ../../../flutter/shell/platform/linux/fl_renderer.cc

shell/platform/linux/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ source_set("flutter_linux") {
7272
"fl_dart_project.cc",
7373
"fl_engine.cc",
7474
"fl_json_message_codec.cc",
75+
"fl_key_event_channel.cc",
7576
"fl_message_codec.cc",
7677
"fl_renderer.cc",
7778
"fl_renderer_x11.cc",
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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_channel.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+
struct _FlKeyEventChannel {
10+
GObject parent_instance;
11+
12+
FlBasicMessageChannel* channel;
13+
};
14+
15+
G_DEFINE_TYPE(FlKeyEventChannel, fl_key_event_channel, G_TYPE_OBJECT)
16+
17+
static void fl_key_event_channel_dispose(GObject* object) {
18+
FlKeyEventChannel* self = FL_KEY_EVENT_CHANNEL(object);
19+
20+
g_clear_object(&self->channel);
21+
22+
G_OBJECT_CLASS(fl_key_event_channel_parent_class)->dispose(object);
23+
}
24+
25+
static void fl_key_event_channel_class_init(FlKeyEventChannelClass* klass) {
26+
G_OBJECT_CLASS(klass)->dispose = fl_key_event_channel_dispose;
27+
}
28+
29+
static void fl_key_event_channel_init(FlKeyEventChannel* self) {}
30+
31+
FlKeyEventChannel* fl_key_event_channel_new(FlBinaryMessenger* messenger) {
32+
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
33+
34+
FlKeyEventChannel* self = FL_KEY_EVENT_CHANNEL(
35+
g_object_new(fl_key_event_channel_get_type(), nullptr));
36+
37+
g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
38+
self->channel = fl_basic_message_channel_new(messenger, "flutter/keyevent",
39+
FL_MESSAGE_CODEC(codec));
40+
41+
return self;
42+
}
43+
44+
void fl_key_event_channel_send_key_event(FlKeyEventChannel* self,
45+
const gchar* type,
46+
int64_t key_code,
47+
int64_t scan_code,
48+
int64_t modifiers,
49+
int64_t unicodeScalarValues) {
50+
g_autoptr(FlValue) message = fl_value_new_map();
51+
fl_value_set_string_take(message, "type", fl_value_new_string(type));
52+
fl_value_set_string_take(message, "keymap", fl_value_new_string("linux"));
53+
fl_value_set_string_take(message, "keyCode", fl_value_new_int(key_code));
54+
fl_value_set_string_take(message, "scanCode", fl_value_new_int(scan_code));
55+
fl_value_set_string_take(message, "modifiers", fl_value_new_int(modifiers));
56+
// FIXME(robert-ancell) Using GLFW toolkit as Flutter doesn't understand
57+
// anything else
58+
fl_value_set_string_take(message, "toolkit", fl_value_new_string("glfw"));
59+
if (unicodeScalarValues != 0)
60+
fl_value_set_string_take(message, "unicodeScalarValues",
61+
fl_value_new_int(unicodeScalarValues));
62+
63+
fl_basic_message_channel_send(self->channel, message, nullptr, nullptr,
64+
nullptr);
65+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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_CHANNEL_H_
6+
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_CHANNEL_H_
7+
8+
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
9+
10+
G_BEGIN_DECLS
11+
12+
G_DECLARE_FINAL_TYPE(FlKeyEventChannel,
13+
fl_key_event_channel,
14+
FL,
15+
KEY_EVENT_CHANNEL,
16+
GObject);
17+
18+
/**
19+
* FlKeyEventChannel:
20+
*
21+
* #FlKeyEventChannel is a platform channel that implements the shell side
22+
* of SystemChannels.keyEvent from the Flutter services library.
23+
*/
24+
25+
/**
26+
* fl_key_event_channel_new:
27+
* @messenger: an #FlBinaryMessenger
28+
*
29+
* Creates a new key event channel.
30+
*
31+
* Returns: a new #FlKeyEventChannel
32+
*/
33+
FlKeyEventChannel* fl_key_event_channel_new(FlBinaryMessenger* messenger);
34+
35+
void fl_key_event_channel_send_key_event(FlKeyEventChannel* channel,
36+
const gchar* type,
37+
int64_t key_code,
38+
int64_t scan_code,
39+
int64_t modifiers,
40+
int64_t unicodeScalarValues);
41+
42+
G_END_DECLS
43+
44+
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_CHANNEL_H_

shell/platform/linux/fl_view.cc

Lines changed: 184 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"
66

77
#include "flutter/shell/platform/linux/fl_engine_private.h"
8+
#include "flutter/shell/platform/linux/fl_key_event_channel.h"
89
#include "flutter/shell/platform/linux/fl_renderer_x11.h"
910
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
1011

@@ -19,12 +20,160 @@ struct _FlView {
1920
FlRendererX11* renderer;
2021
FlEngine* engine;
2122
int64_t button_state;
23+
24+
// Flutter system channels
25+
FlKeyEventChannel* key_event_channel;
2226
};
2327

2428
enum { PROP_FLUTTER_PROJECT = 1, PROP_LAST };
2529

2630
G_DEFINE_TYPE(FlView, fl_view, GTK_TYPE_WIDGET)
2731

32+
static int gdk_keyval_to_glfw_key_code(guint keyval) {
33+
switch (keyval) {
34+
case GDK_KEY_space:
35+
return 32;
36+
case GDK_KEY_apostrophe:
37+
return 39;
38+
case GDK_KEY_comma:
39+
return 44;
40+
case GDK_KEY_minus:
41+
return 45;
42+
case GDK_KEY_period:
43+
return 46;
44+
case GDK_KEY_slash:
45+
return 47;
46+
case GDK_KEY_0:
47+
return 48;
48+
case GDK_KEY_1:
49+
return 49;
50+
case GDK_KEY_2:
51+
return 50;
52+
case GDK_KEY_3:
53+
return 51;
54+
case GDK_KEY_4:
55+
return 52;
56+
case GDK_KEY_5:
57+
return 53;
58+
case GDK_KEY_6:
59+
return 54;
60+
case GDK_KEY_7:
61+
return 55;
62+
case GDK_KEY_8:
63+
return 56;
64+
case GDK_KEY_9:
65+
return 57;
66+
case GDK_KEY_semicolon:
67+
return 59;
68+
case GDK_KEY_equal:
69+
return 61;
70+
case GDK_KEY_a:
71+
return 65;
72+
case GDK_KEY_b:
73+
return 66;
74+
case GDK_KEY_c:
75+
return 67;
76+
case GDK_KEY_d:
77+
return 68;
78+
case GDK_KEY_e:
79+
return 69;
80+
case GDK_KEY_f:
81+
return 70;
82+
case GDK_KEY_g:
83+
return 71;
84+
case GDK_KEY_h:
85+
return 72;
86+
case GDK_KEY_i:
87+
return 73;
88+
case GDK_KEY_j:
89+
return 74;
90+
case GDK_KEY_k:
91+
return 75;
92+
case GDK_KEY_l:
93+
return 76;
94+
case GDK_KEY_m:
95+
return 77;
96+
case GDK_KEY_n:
97+
return 78;
98+
case GDK_KEY_o:
99+
return 79;
100+
case GDK_KEY_p:
101+
return 80;
102+
case GDK_KEY_q:
103+
return 81;
104+
case GDK_KEY_r:
105+
return 82;
106+
case GDK_KEY_s:
107+
return 83;
108+
case GDK_KEY_t:
109+
return 84;
110+
case GDK_KEY_u:
111+
return 85;
112+
case GDK_KEY_v:
113+
return 86;
114+
case GDK_KEY_w:
115+
return 87;
116+
case GDK_KEY_x:
117+
return 88;
118+
case GDK_KEY_y:
119+
return 89;
120+
case GDK_KEY_z:
121+
return 90;
122+
case GDK_KEY_bracketleft:
123+
return 91;
124+
case GDK_KEY_bracketright:
125+
return 92;
126+
case GDK_KEY_grave:
127+
return 96;
128+
case GDK_KEY_Escape:
129+
return 256;
130+
case GDK_KEY_Return:
131+
return 257;
132+
case GDK_KEY_Tab:
133+
return 258;
134+
case GDK_KEY_BackSpace:
135+
return 259;
136+
case GDK_KEY_Insert:
137+
return 260;
138+
case GDK_KEY_Delete:
139+
return 261;
140+
case GDK_KEY_Right:
141+
return 262;
142+
case GDK_KEY_Left:
143+
return 263;
144+
case GDK_KEY_Down:
145+
return 264;
146+
case GDK_KEY_Up:
147+
return 265;
148+
case GDK_KEY_Page_Up:
149+
return 266;
150+
case GDK_KEY_Page_Down:
151+
return 267;
152+
case GDK_KEY_Home:
153+
return 268;
154+
case GDK_KEY_End:
155+
return 269;
156+
case GDK_KEY_Shift_L:
157+
return 340;
158+
case GDK_KEY_Control_L:
159+
return 341;
160+
case GDK_KEY_Alt_L:
161+
return 342;
162+
case GDK_KEY_Super_L:
163+
return 343;
164+
case GDK_KEY_Shift_R:
165+
return 344;
166+
case GDK_KEY_Control_R:
167+
return 345;
168+
case GDK_KEY_Alt_R:
169+
return 346;
170+
case GDK_KEY_Super_R:
171+
return 347;
172+
default:
173+
return 0;
174+
}
175+
}
176+
28177
// Convert a GDK button event into a Flutter event and send to the engine
29178
static gboolean fl_view_send_pointer_button_event(FlView* self,
30179
GdkEventButton* event) {
@@ -74,6 +223,10 @@ static void fl_view_constructed(GObject* object) {
74223

75224
self->renderer = fl_renderer_x11_new();
76225
self->engine = fl_engine_new(self->project, FL_RENDERER(self->renderer));
226+
227+
// Create system channels
228+
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
229+
self->key_event_channel = fl_key_event_channel_new(messenger);
77230
}
78231

79232
static void fl_view_set_property(GObject* object,
@@ -115,6 +268,7 @@ static void fl_view_dispose(GObject* object) {
115268
g_clear_object(&self->project);
116269
g_clear_object(&self->renderer);
117270
g_clear_object(&self->engine);
271+
g_clear_object(&self->key_event_channel);
118272

119273
G_OBJECT_CLASS(fl_view_parent_class)->dispose(object);
120274
}
@@ -137,7 +291,8 @@ static void fl_view_realize(GtkWidget* widget) {
137291
window_attributes.visual = gtk_widget_get_visual(widget);
138292
window_attributes.event_mask =
139293
gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK |
140-
GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
294+
GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
295+
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK;
141296

142297
gint window_attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
143298

@@ -205,6 +360,29 @@ static gboolean fl_view_motion_notify_event(GtkWidget* widget,
205360
return TRUE;
206361
}
207362

363+
static gboolean fl_view_key_press_event(GtkWidget* widget, GdkEventKey* event) {
364+
FlView* self = FL_VIEW(widget);
365+
366+
fl_key_event_channel_send_key_event(
367+
self->key_event_channel, "keydown",
368+
gdk_keyval_to_glfw_key_code(event->keyval), event->hardware_keycode, 0,
369+
gdk_keyval_to_unicode(event->keyval));
370+
371+
return TRUE;
372+
}
373+
374+
static gboolean fl_view_key_release_event(GtkWidget* widget,
375+
GdkEventKey* event) {
376+
FlView* self = FL_VIEW(widget);
377+
378+
fl_key_event_channel_send_key_event(
379+
self->key_event_channel, "keyup",
380+
gdk_keyval_to_glfw_key_code(event->keyval), event->hardware_keycode, 0,
381+
gdk_keyval_to_unicode(event->keyval));
382+
383+
return TRUE;
384+
}
385+
208386
static void fl_view_class_init(FlViewClass* klass) {
209387
G_OBJECT_CLASS(klass)->constructed = fl_view_constructed;
210388
G_OBJECT_CLASS(klass)->set_property = fl_view_set_property;
@@ -215,6 +393,8 @@ static void fl_view_class_init(FlViewClass* klass) {
215393
GTK_WIDGET_CLASS(klass)->button_press_event = fl_view_button_press_event;
216394
GTK_WIDGET_CLASS(klass)->button_release_event = fl_view_button_release_event;
217395
GTK_WIDGET_CLASS(klass)->motion_notify_event = fl_view_motion_notify_event;
396+
GTK_WIDGET_CLASS(klass)->key_press_event = fl_view_key_press_event;
397+
GTK_WIDGET_CLASS(klass)->key_release_event = fl_view_key_release_event;
218398

219399
g_object_class_install_property(
220400
G_OBJECT_CLASS(klass), PROP_FLUTTER_PROJECT,
@@ -225,7 +405,9 @@ static void fl_view_class_init(FlViewClass* klass) {
225405
G_PARAM_STATIC_STRINGS)));
226406
}
227407

228-
static void fl_view_init(FlView* self) {}
408+
static void fl_view_init(FlView* self) {
409+
gtk_widget_set_can_focus(GTK_WIDGET(self), TRUE);
410+
}
229411

230412
G_MODULE_EXPORT FlView* fl_view_new(FlDartProject* project) {
231413
return static_cast<FlView*>(

0 commit comments

Comments
 (0)