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

Commit 263c1ba

Browse files
committed
Review Changes
1 parent 118ffac commit 263c1ba

File tree

6 files changed

+248
-204
lines changed

6 files changed

+248
-204
lines changed

shell/platform/linux/fl_key_event_plugin.cc

Lines changed: 123 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@
1010
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
1111
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
1212

13+
// Definition of the FlKeyEventPlugin GObject class.
14+
15+
struct _FlKeyEventPlugin {
16+
GObject parent_instance;
17+
18+
FlBasicMessageChannel* channel = nullptr;
19+
FlTextInputPlugin* text_input_plugin = nullptr;
20+
FlKeyEventPluginCallback response_callback = nullptr;
21+
GPtrArray* pending_events;
22+
};
23+
24+
G_DEFINE_TYPE(FlKeyEventPlugin, fl_key_event_plugin, G_TYPE_OBJECT)
25+
26+
namespace {
27+
1328
static constexpr char kChannelName[] = "flutter/keyevent";
1429
static constexpr char kTypeKey[] = "type";
1530
static constexpr char kTypeValueUp[] = "keyup";
@@ -29,13 +44,11 @@ static constexpr uint64_t kMaxPendingEvents = 1000;
2944
// Declare and define a private pair object to bind the id and the event
3045
// together.
3146

32-
G_BEGIN_DECLS
3347
G_DECLARE_FINAL_TYPE(FlKeyEventPair,
3448
fl_key_event_pair,
3549
FL,
3650
KEY_EVENT_PAIR,
3751
GObject);
38-
G_END_DECLS
3952

4053
struct _FlKeyEventPair {
4154
GObject parent_instance;
@@ -46,18 +59,27 @@ struct _FlKeyEventPair {
4659

4760
G_DEFINE_TYPE(FlKeyEventPair, fl_key_event_pair, G_TYPE_OBJECT)
4861

62+
// Dispose method for FlKeyEventPair.
4963
static void fl_key_event_pair_dispose(GObject* object) {
64+
// Redundant, but added so that we don't get a warning about unused function
65+
// for FL_IS_KEY_EVENT_PAIR.
5066
g_return_if_fail(FL_IS_KEY_EVENT_PAIR(object));
67+
5168
FlKeyEventPair* self = FL_KEY_EVENT_PAIR(object);
52-
gdk_event_free(reinterpret_cast<GdkEvent*>(self->event));
69+
g_clear_pointer(&self->event, gdk_event_free);
70+
G_OBJECT_CLASS(fl_key_event_pair_parent_class)->dispose(object);
5371
}
5472

73+
// Class Initialization method for FlKeyEventPair class.
5574
static void fl_key_event_pair_class_init(FlKeyEventPairClass* klass) {
5675
G_OBJECT_CLASS(klass)->dispose = fl_key_event_pair_dispose;
5776
}
5877

78+
// Initialization for FlKeyEventPair instances.
5979
static void fl_key_event_pair_init(FlKeyEventPair* self) {}
6080

81+
// Creates a new FlKeyEventPair instance, given a unique ID, and an event struct
82+
// to keep.
6183
FlKeyEventPair* fl_key_event_pair_new(uint64_t id, GdkEventKey* event) {
6284
FlKeyEventPair* self =
6385
FL_KEY_EVENT_PAIR(g_object_new(fl_key_event_pair_get_type(), nullptr));
@@ -72,14 +94,11 @@ FlKeyEventPair* fl_key_event_pair_new(uint64_t id, GdkEventKey* event) {
7294
}
7395

7496
// Declare and define a private class to hold response data from the framework.
75-
76-
G_BEGIN_DECLS
7797
G_DECLARE_FINAL_TYPE(FlKeyEventResponseData,
7898
fl_key_event_response_data,
7999
FL,
80100
KEY_EVENT_RESPONSE_DATA,
81101
GObject);
82-
G_END_DECLS
83102

84103
struct _FlKeyEventResponseData {
85104
GObject parent_instance;
@@ -89,8 +108,10 @@ struct _FlKeyEventResponseData {
89108
gpointer user_data;
90109
};
91110

111+
// Definition for FlKeyEventResponseData private class.
92112
G_DEFINE_TYPE(FlKeyEventResponseData, fl_key_event_response_data, G_TYPE_OBJECT)
93113

114+
// Dispose method for FlKeyEventResponseData private class.
94115
static void fl_key_event_response_data_dispose(GObject* object) {
95116
g_return_if_fail(FL_IS_KEY_EVENT_RESPONSE_DATA(object));
96117
FlKeyEventResponseData* self = FL_KEY_EVENT_RESPONSE_DATA(object);
@@ -99,13 +120,18 @@ static void fl_key_event_response_data_dispose(GObject* object) {
99120
reinterpret_cast<gpointer*>(&(self->plugin)));
100121
}
101122

123+
// Class initialization method for FlKeyEventResponseData private class.
102124
static void fl_key_event_response_data_class_init(
103125
FlKeyEventResponseDataClass* klass) {
104126
G_OBJECT_CLASS(klass)->dispose = fl_key_event_response_data_dispose;
105127
}
106128

129+
// Instance initialization method for FlKeyEventResponseData private class.
107130
static void fl_key_event_response_data_init(FlKeyEventResponseData* self) {}
108131

132+
// Creates a new FlKeyEventResponseData private class with a plugin that created
133+
// the request, a unique ID for tracking, and optional user data.
134+
// Will keep a weak pointer to the plugin.
109135
FlKeyEventResponseData* fl_key_event_response_data_new(FlKeyEventPlugin* plugin,
110136
uint64_t id,
111137
gpointer user_data) {
@@ -122,64 +148,9 @@ FlKeyEventResponseData* fl_key_event_response_data_new(FlKeyEventPlugin* plugin,
122148
return self;
123149
}
124150

125-
// Definition of the FlKeyEventPlugin GObject class.
126-
127-
struct _FlKeyEventPlugin {
128-
GObject parent_instance;
129-
130-
FlBasicMessageChannel* channel = nullptr;
131-
FlTextInputPlugin* text_input_plugin = nullptr;
132-
FlKeyEventPluginCallback response_callback = nullptr;
133-
GPtrArray* pending_events;
134-
};
135-
136-
G_DEFINE_TYPE(FlKeyEventPlugin, fl_key_event_plugin, G_TYPE_OBJECT)
137-
138-
static void fl_key_event_plugin_dispose(GObject* object) {
139-
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(object);
140-
141-
g_clear_object(&self->channel);
142-
g_object_remove_weak_pointer(
143-
G_OBJECT(self->text_input_plugin),
144-
reinterpret_cast<gpointer*>(&(self->text_input_plugin)));
145-
g_ptr_array_free(self->pending_events, TRUE);
146-
147-
G_OBJECT_CLASS(fl_key_event_plugin_parent_class)->dispose(object);
148-
}
149-
150-
static void fl_key_event_plugin_class_init(FlKeyEventPluginClass* klass) {
151-
G_OBJECT_CLASS(klass)->dispose = fl_key_event_plugin_dispose;
152-
}
153-
154-
static void fl_key_event_plugin_init(FlKeyEventPlugin* self) {}
155-
156-
FlKeyEventPlugin* fl_key_event_plugin_new(
157-
FlBinaryMessenger* messenger,
158-
FlTextInputPlugin* text_input_plugin,
159-
FlKeyEventPluginCallback response_callback,
160-
const char* channel_name) {
161-
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
162-
g_return_val_if_fail(FL_IS_TEXT_INPUT_PLUGIN(text_input_plugin), nullptr);
163-
164-
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(
165-
g_object_new(fl_key_event_plugin_get_type(), nullptr));
166-
167-
g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
168-
self->channel = fl_basic_message_channel_new(
169-
messenger, channel_name == nullptr ? kChannelName : channel_name,
170-
FL_MESSAGE_CODEC(codec));
171-
self->response_callback = response_callback;
172-
// Add a weak pointer so we know if the text input plugin goes away.
173-
g_object_add_weak_pointer(
174-
G_OBJECT(text_input_plugin),
175-
reinterpret_cast<gpointer*>(&(self->text_input_plugin)));
176-
self->text_input_plugin = text_input_plugin;
177-
178-
self->pending_events = g_ptr_array_new_with_free_func(g_object_unref);
179-
return self;
180-
}
181-
182-
uint64_t fl_get_event_id(GdkEventKey* event) {
151+
// Calculates a unique ID for a given GdkEventKey object to use for
152+
// identification of responses from the framework.
153+
static uint64_t get_event_id(GdkEventKey* event) {
183154
// Combine the event timestamp, the type of event, and the hardware keycode
184155
// (scan code) of the event to come up with a unique id for this event that
185156
// can be derived solely from the event data itself, so that we can identify
@@ -189,7 +160,8 @@ uint64_t fl_get_event_id(GdkEventKey* event) {
189160
(static_cast<uint64_t>(event->hardware_keycode) & 0xffff) << 48;
190161
}
191162

192-
GdkEventKey* fl_find_pending_event(FlKeyEventPlugin* self, uint64_t id) {
163+
// Finds an event in the event queue that was sent to the framework by its ID.
164+
static GdkEventKey* find_pending_event(FlKeyEventPlugin* self, uint64_t id) {
193165
if (self->pending_events->len == 0 ||
194166
FL_KEY_EVENT_PAIR(g_ptr_array_index(self->pending_events, 0))->id != id) {
195167
return nullptr;
@@ -198,7 +170,8 @@ GdkEventKey* fl_find_pending_event(FlKeyEventPlugin* self, uint64_t id) {
198170
return FL_KEY_EVENT_PAIR(g_ptr_array_index(self->pending_events, 0))->event;
199171
}
200172

201-
void fl_remove_pending_event(FlKeyEventPlugin* self, uint64_t id) {
173+
// Removes an event from the pending event queue.
174+
static void remove_pending_event(FlKeyEventPlugin* self, uint64_t id) {
202175
if (self->pending_events->len == 0 ||
203176
FL_KEY_EVENT_PAIR(g_ptr_array_index(self->pending_events, 0))->id != id) {
204177
g_warning(
@@ -210,9 +183,11 @@ void fl_remove_pending_event(FlKeyEventPlugin* self, uint64_t id) {
210183
g_ptr_array_remove_index(self->pending_events, 0);
211184
}
212185

213-
void fl_add_pending_event(FlKeyEventPlugin* self,
214-
uint64_t id,
215-
GdkEventKey* event) {
186+
// Adds an GdkEventKey to the pending event queue, with a unique ID, and the
187+
// plugin that added it.
188+
static void add_pending_event(FlKeyEventPlugin* self,
189+
uint64_t id,
190+
GdkEventKey* event) {
216191
if (self->pending_events->len > kMaxPendingEvents) {
217192
g_warning(
218193
"There are %d keyboard events that have not yet received a "
@@ -222,14 +197,18 @@ void fl_add_pending_event(FlKeyEventPlugin* self,
222197
g_ptr_array_add(self->pending_events, fl_key_event_pair_new(id, event));
223198
}
224199

225-
void fl_handle_response(GObject* object,
226-
GAsyncResult* result,
227-
gpointer user_data) {
200+
// Handles a response from the framework to a key event sent to the framework
201+
// earlier.
202+
static void handle_response(GObject* object,
203+
GAsyncResult* result,
204+
gpointer user_data) {
228205
g_autoptr(FlKeyEventResponseData) data =
229206
FL_KEY_EVENT_RESPONSE_DATA(user_data);
230207

231208
// Will also return if the weak pointer has been destroyed.
232-
g_return_if_fail(FL_IS_KEY_EVENT_PLUGIN(data->plugin));
209+
if (data->plugin == nullptr) {
210+
return;
211+
}
233212

234213
FlKeyEventPlugin* self = data->plugin;
235214

@@ -238,14 +217,13 @@ void fl_handle_response(GObject* object,
238217
FlValue* message =
239218
fl_basic_message_channel_send_finish(messageChannel, result, &error);
240219
if (error != nullptr) {
241-
g_error("Unable to retrieve framework response: %s", error->message);
242-
g_error_free(error);
220+
g_warning("Unable to retrieve framework response: %s", error->message);
243221
return;
244222
}
245223
g_autoptr(FlValue) handled_value = fl_value_lookup_string(message, "handled");
246-
bool handled = false;
224+
bool handled = FALSE;
247225
if (handled_value != nullptr) {
248-
GdkEventKey* event = fl_find_pending_event(self, data->id);
226+
GdkEventKey* event = find_pending_event(self, data->id);
249227
if (event == nullptr) {
250228
g_warning(
251229
"Event response for event id %ld received, but event was received "
@@ -273,33 +251,88 @@ void fl_handle_response(GObject* object,
273251
if (handled) {
274252
// Because the event was handled, we no longer need to track it. Unhandled
275253
// events will be removed when the event is re-dispatched to the window.
276-
fl_remove_pending_event(self, data->id);
254+
remove_pending_event(self, data->id);
277255
}
278256

279257
if (self->response_callback != nullptr) {
280258
self->response_callback(object, message, handled, data->user_data);
281259
}
282260
}
283261

262+
// Disposes of an FlKeyEventPlugin instance.
263+
static void fl_key_event_plugin_dispose(GObject* object) {
264+
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(object);
265+
266+
g_clear_object(&self->channel);
267+
g_object_remove_weak_pointer(
268+
G_OBJECT(self->text_input_plugin),
269+
reinterpret_cast<gpointer*>(&(self->text_input_plugin)));
270+
g_ptr_array_free(self->pending_events, TRUE);
271+
272+
G_OBJECT_CLASS(fl_key_event_plugin_parent_class)->dispose(object);
273+
}
274+
275+
} // namespace
276+
277+
// Initializes the FlKeyEventPlugin class methods.
278+
static void fl_key_event_plugin_class_init(FlKeyEventPluginClass* klass) {
279+
G_OBJECT_CLASS(klass)->dispose = fl_key_event_plugin_dispose;
280+
}
281+
282+
// Initializes an FlKeyEventPlugin instance.
283+
static void fl_key_event_plugin_init(FlKeyEventPlugin* self) {}
284+
285+
// Creates a new FlKeyEventPlugin instance, with a messenger used to send
286+
// messages to the framework, an FlTextInputPlugin used to handle key events
287+
// that the framework doesn't handle. Mainly for testing purposes, it also takes
288+
// an optional callback to call when a response is received, and an optional
289+
// channel name to use when sending messages.
290+
FlKeyEventPlugin* fl_key_event_plugin_new(
291+
FlBinaryMessenger* messenger,
292+
FlTextInputPlugin* text_input_plugin,
293+
FlKeyEventPluginCallback response_callback,
294+
const char* channel_name) {
295+
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
296+
g_return_val_if_fail(FL_IS_TEXT_INPUT_PLUGIN(text_input_plugin), nullptr);
297+
298+
FlKeyEventPlugin* self = FL_KEY_EVENT_PLUGIN(
299+
g_object_new(fl_key_event_plugin_get_type(), nullptr));
300+
301+
g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
302+
self->channel = fl_basic_message_channel_new(
303+
messenger, channel_name == nullptr ? kChannelName : channel_name,
304+
FL_MESSAGE_CODEC(codec));
305+
self->response_callback = response_callback;
306+
// Add a weak pointer so we know if the text input plugin goes away.
307+
g_object_add_weak_pointer(
308+
G_OBJECT(text_input_plugin),
309+
reinterpret_cast<gpointer*>(&(self->text_input_plugin)));
310+
self->text_input_plugin = text_input_plugin;
311+
312+
self->pending_events = g_ptr_array_new_with_free_func(g_object_unref);
313+
return self;
314+
}
315+
316+
// Sends a key event to the framework.
284317
bool fl_key_event_plugin_send_key_event(FlKeyEventPlugin* self,
285318
GdkEventKey* event,
286319
gpointer user_data) {
287-
g_return_val_if_fail(FL_IS_KEY_EVENT_PLUGIN(self), false);
288-
g_return_val_if_fail(event != nullptr, false);
320+
g_return_val_if_fail(FL_IS_KEY_EVENT_PLUGIN(self), FALSE);
321+
g_return_val_if_fail(event != nullptr, FALSE);
289322

290323
// Get an ID for the event, so we can match them up when we get a response
291324
// from the framework. Use the event time, type, and hardware keycode as a
292325
// unique ID, since they are part of the event structure that we can look up
293326
// when we receive a random event that may or may not have been
294327
// tracked/produced by this code.
295-
uint64_t id = fl_get_event_id(event);
328+
uint64_t id = get_event_id(event);
296329
if (self->pending_events->len != 0 &&
297330
FL_KEY_EVENT_PAIR(g_ptr_array_index(self->pending_events, 0))->id == id) {
298331
// If the event is at the head of the queue of pending events we've seen,
299332
// and has the same id, then we know that this is a re-dispatched event, and
300333
// we shouldn't respond to it, but we should remove it from tracking.
301-
fl_remove_pending_event(self, id);
302-
return false;
334+
remove_pending_event(self, id);
335+
return FALSE;
303336
}
304337

305338
const gchar* type;
@@ -311,7 +344,7 @@ bool fl_key_event_plugin_send_key_event(FlKeyEventPlugin* self,
311344
type = kTypeValueUp;
312345
break;
313346
default:
314-
return false;
347+
return FALSE;
315348
}
316349

317350
int64_t scan_code = event->hardware_keycode;
@@ -345,9 +378,9 @@ bool fl_key_event_plugin_send_key_event(FlKeyEventPlugin* self,
345378
// Remove lock states from state mask.
346379
guint state = event->state & ~(GDK_LOCK_MASK | GDK_MOD2_MASK);
347380

348-
static bool shift_lock_pressed = false;
349-
static bool caps_lock_pressed = false;
350-
static bool num_lock_pressed = false;
381+
static bool shift_lock_pressed = FALSE;
382+
static bool caps_lock_pressed = FALSE;
383+
static bool num_lock_pressed = FALSE;
351384
switch (event->keyval) {
352385
case GDK_KEY_Num_Lock:
353386
num_lock_pressed = event->type == GDK_KEY_PRESS;
@@ -381,13 +414,13 @@ bool fl_key_event_plugin_send_key_event(FlKeyEventPlugin* self,
381414
}
382415

383416
// Track the event as pending a response from the framework.
384-
fl_add_pending_event(self, id, event);
417+
add_pending_event(self, id, event);
385418
FlKeyEventResponseData* data =
386419
fl_key_event_response_data_new(self, id, user_data);
387420
// Send the message off to the framework for handling (or not).
388421
fl_basic_message_channel_send(self->channel, message, nullptr,
389-
fl_handle_response, data);
422+
handle_response, data);
390423
// Return true before we know what the framework will do, because if it
391424
// doesn't handle the key, we'll re-dispatch it later.
392-
return true;
425+
return TRUE;
393426
}

0 commit comments

Comments
 (0)