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
2428enum { PROP_FLUTTER_PROJECT = 1 , PROP_LAST };
2529
2630G_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
29178static 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
79232static 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+
208386static 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
230412G_MODULE_EXPORT FlView* fl_view_new (FlDartProject* project) {
231413 return static_cast <FlView*>(
0 commit comments