Skip to content

Commit a6045c9

Browse files
Make fl_keyboard_manager_handle_event async (#161637)
In this way we can tell when this call completes, which should help testing and refactoring.
1 parent 82a58ee commit a6045c9

4 files changed

Lines changed: 207 additions & 137 deletions

File tree

engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc

Lines changed: 60 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,6 @@
2020
// is used in unit tests.
2121
#define DEBUG_PRINT_LAYOUT
2222

23-
/* Declarations of private classes */
24-
25-
G_DECLARE_FINAL_TYPE(FlKeyboardManagerData,
26-
fl_keyboard_manager_data,
27-
FL,
28-
KEYBOARD_MANAGER_DATA,
29-
GObject);
30-
31-
/* End declarations */
32-
3323
namespace {
3424

3525
static bool is_eascii(uint16_t character) {
@@ -63,55 +53,6 @@ void debug_format_layout_data(std::string& debug_layout_data,
6353

6454
} // namespace
6555

66-
/* Define FlKeyboardManagerData */
67-
68-
/**
69-
* FlKeyboardManagerData:
70-
* The user_data used when #FlKeyboardManager sends event to
71-
* responders.
72-
*/
73-
74-
struct _FlKeyboardManagerData {
75-
GObject parent_instance;
76-
77-
// The owner manager.
78-
GWeakRef manager;
79-
80-
FlKeyboardPendingEvent* pending;
81-
};
82-
83-
G_DEFINE_TYPE(FlKeyboardManagerData, fl_keyboard_manager_data, G_TYPE_OBJECT)
84-
85-
static void fl_keyboard_manager_data_dispose(GObject* object) {
86-
g_return_if_fail(FL_IS_KEYBOARD_MANAGER_DATA(object));
87-
FlKeyboardManagerData* self = FL_KEYBOARD_MANAGER_DATA(object);
88-
89-
g_weak_ref_clear(&self->manager);
90-
91-
G_OBJECT_CLASS(fl_keyboard_manager_data_parent_class)->dispose(object);
92-
}
93-
94-
static void fl_keyboard_manager_data_class_init(
95-
FlKeyboardManagerDataClass* klass) {
96-
G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_data_dispose;
97-
}
98-
99-
static void fl_keyboard_manager_data_init(FlKeyboardManagerData* self) {}
100-
101-
// Creates a new FlKeyboardManagerData private class with all information.
102-
static FlKeyboardManagerData* fl_keyboard_manager_data_new(
103-
FlKeyboardManager* manager,
104-
FlKeyboardPendingEvent* pending) {
105-
FlKeyboardManagerData* self = FL_KEYBOARD_MANAGER_DATA(
106-
g_object_new(fl_keyboard_manager_data_get_type(), nullptr));
107-
108-
g_weak_ref_init(&self->manager, manager);
109-
self->pending = FL_KEYBOARD_PENDING_EVENT(g_object_ref(pending));
110-
return self;
111-
}
112-
113-
/* Define FlKeyboardManager */
114-
11556
struct _FlKeyboardManager {
11657
GObject parent_instance;
11758

@@ -211,25 +152,6 @@ static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b) {
211152
return fl_keyboard_pending_event_get_hash(pending) == hash;
212153
}
213154

214-
// Try to remove a pending event from `pending_redispatches` with the target
215-
// hash.
216-
//
217-
// Returns true if the event is found and removed.
218-
static bool fl_keyboard_manager_remove_redispatched(FlKeyboardManager* self,
219-
uint64_t hash) {
220-
guint result_index;
221-
gboolean found = g_ptr_array_find_with_equal_func1(
222-
self->pending_redispatches, static_cast<const uint64_t*>(&hash),
223-
compare_pending_by_hash, &result_index);
224-
if (found) {
225-
// The removed object is freed due to `pending_redispatches`'s free_func.
226-
g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
227-
return TRUE;
228-
} else {
229-
return FALSE;
230-
}
231-
}
232-
233155
// The callback used by a responder after the event was dispatched.
234156
static void responder_handle_event_callback(FlKeyboardManager* self,
235157
FlKeyboardPendingEvent* pending) {
@@ -262,25 +184,33 @@ static void responder_handle_event_callback(FlKeyboardManager* self,
262184
}
263185
}
264186

187+
static void complete_handle_event(FlKeyboardManager* self, GTask* task) {
188+
FlKeyboardPendingEvent* pending =
189+
FL_KEYBOARD_PENDING_EVENT(g_task_get_task_data(task));
190+
191+
if (fl_keyboard_pending_event_is_complete(pending)) {
192+
g_task_return_boolean(task, TRUE);
193+
}
194+
}
195+
265196
static void responder_handle_embedder_event_callback(bool handled,
266197
gpointer user_data) {
267-
g_autoptr(FlKeyboardManagerData) data = FL_KEYBOARD_MANAGER_DATA(user_data);
268-
269-
fl_keyboard_pending_event_mark_embedder_replied(data->pending, handled);
198+
g_autoptr(GTask) task = G_TASK(user_data);
199+
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
270200

271-
g_autoptr(FlKeyboardManager) self =
272-
FL_KEYBOARD_MANAGER(g_weak_ref_get(&data->manager));
273-
if (self == nullptr) {
274-
return;
275-
}
201+
FlKeyboardPendingEvent* pending =
202+
FL_KEYBOARD_PENDING_EVENT(g_task_get_task_data(task));
203+
fl_keyboard_pending_event_mark_embedder_replied(pending, handled);
204+
responder_handle_event_callback(self, pending);
276205

277-
responder_handle_event_callback(self, data->pending);
206+
complete_handle_event(self, task);
278207
}
279208

280209
static void responder_handle_channel_event_cb(GObject* object,
281210
GAsyncResult* result,
282211
gpointer user_data) {
283-
g_autoptr(FlKeyboardManagerData) data = FL_KEYBOARD_MANAGER_DATA(user_data);
212+
g_autoptr(GTask) task = G_TASK(user_data);
213+
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
284214

285215
g_autoptr(GError) error = nullptr;
286216
gboolean handled;
@@ -289,18 +219,15 @@ static void responder_handle_channel_event_cb(GObject* object,
289219
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
290220
g_warning("Failed to handle key event in platform: %s", error->message);
291221
}
292-
return;
293-
}
294-
295-
g_autoptr(FlKeyboardManager) self =
296-
FL_KEYBOARD_MANAGER(g_weak_ref_get(&data->manager));
297-
if (self == nullptr) {
298-
return;
222+
handled = FALSE;
299223
}
300224

301-
fl_keyboard_pending_event_mark_channel_replied(data->pending, handled);
225+
FlKeyboardPendingEvent* pending =
226+
FL_KEYBOARD_PENDING_EVENT(g_task_get_task_data(task));
227+
fl_keyboard_pending_event_mark_channel_replied(pending, handled);
228+
responder_handle_event_callback(self, pending);
302229

303-
responder_handle_event_callback(self, data->pending);
230+
complete_handle_event(self, task);
304231
}
305232

306233
static uint16_t convert_key_to_char(FlKeyboardManager* self,
@@ -519,34 +446,58 @@ FlKeyboardManager* fl_keyboard_manager_new(
519446
return self;
520447
}
521448

522-
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager* self,
523-
FlKeyEvent* event) {
449+
gboolean fl_keyboard_manager_is_redispatched(FlKeyboardManager* self,
450+
FlKeyEvent* event) {
524451
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
525-
g_return_val_if_fail(event != nullptr, FALSE);
526452

527-
guarantee_layout(self, event);
453+
uint64_t hash = fl_key_event_hash(event);
528454

529-
uint64_t incoming_hash = fl_key_event_hash(event);
530-
if (fl_keyboard_manager_remove_redispatched(self, incoming_hash)) {
455+
guint result_index;
456+
gboolean found = g_ptr_array_find_with_equal_func1(
457+
self->pending_redispatches, static_cast<const uint64_t*>(&hash),
458+
compare_pending_by_hash, &result_index);
459+
if (found) {
460+
// The removed object is freed due to `pending_redispatches`'s free_func.
461+
g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
462+
return TRUE;
463+
} else {
531464
return FALSE;
532465
}
466+
}
533467

534-
FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(event);
468+
void fl_keyboard_manager_handle_event(FlKeyboardManager* self,
469+
FlKeyEvent* event,
470+
GCancellable* cancellable,
471+
GAsyncReadyCallback callback,
472+
gpointer user_data) {
473+
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
474+
g_return_if_fail(event != nullptr);
475+
476+
g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data);
477+
478+
guarantee_layout(self, event);
535479

480+
FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(event);
536481
g_ptr_array_add(self->pending_responds, pending);
537-
g_autoptr(FlKeyboardManagerData) data =
538-
fl_keyboard_manager_data_new(self, pending);
482+
g_task_set_task_data(task, g_object_ref(pending), g_object_unref);
483+
539484
uint64_t specified_logical_key = fl_keyboard_layout_get_logical_key(
540485
self->derived_layout, fl_key_event_get_group(event),
541486
fl_key_event_get_keycode(event));
542487
fl_key_embedder_responder_handle_event(
543488
self->key_embedder_responder, event, specified_logical_key,
544-
responder_handle_embedder_event_callback, g_object_ref(data));
489+
responder_handle_embedder_event_callback, g_object_ref(task));
545490
fl_key_channel_responder_handle_event(
546491
self->key_channel_responder, event, specified_logical_key,
547-
self->cancellable, responder_handle_channel_event_cb, g_object_ref(data));
492+
self->cancellable, responder_handle_channel_event_cb, g_object_ref(task));
493+
}
548494

549-
return TRUE;
495+
gboolean fl_keyboard_manager_handle_event_finish(FlKeyboardManager* self,
496+
GAsyncResult* result,
497+
GError** error) {
498+
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
499+
g_return_val_if_fail(g_task_is_valid(result, self), FALSE);
500+
return g_task_propagate_boolean(G_TASK(result), error);
550501
}
551502

552503
gboolean fl_keyboard_manager_is_state_clear(FlKeyboardManager* self) {

engine/src/flutter/shell/platform/linux/fl_keyboard_manager.h

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,52 @@ FlKeyboardManager* fl_keyboard_manager_new(
4848
FlEngine* engine,
4949
FlKeyboardViewDelegate* view_delegate);
5050

51+
/**
52+
* fl_keyboard_manager_is_redispatched:
53+
* @manager: an #FlKeyboardManager.
54+
* @event: an event received from the system.
55+
*
56+
* Checks if an event was redispacthed from this manager.
57+
*
58+
* Returns: %TRUE if the event is redispatched.
59+
*/
60+
gboolean fl_keyboard_manager_is_redispatched(FlKeyboardManager* manager,
61+
FlKeyEvent* event);
62+
5163
/**
5264
* fl_keyboard_manager_handle_event:
53-
* @manager: the #FlKeyboardManager self.
65+
* @manager: an #FlKeyboardManager.
5466
* @event: the event to be dispatched. It is usually a wrap of a GdkEventKey.
5567
* This event will be managed and released by #FlKeyboardManager.
68+
* @cancellable: (allow-none): a #GCancellable or %NULL.
69+
* @callback: (scope async): a #GAsyncReadyCallback to call when the view is
70+
* added.
71+
* @user_data: (closure): user data to pass to @callback.
5672
*
5773
* Make the manager process a system key event. This might eventually send
5874
* messages to the framework, trigger text input effects, or redispatch the
5975
* event back to the system.
6076
*/
61-
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager* manager,
62-
FlKeyEvent* event);
77+
void fl_keyboard_manager_handle_event(FlKeyboardManager* manager,
78+
FlKeyEvent* event,
79+
GCancellable* cancellable,
80+
GAsyncReadyCallback callback,
81+
gpointer user_data);
82+
83+
/**
84+
* fl_keyboard_manager_handle_event_finish:
85+
* @manager: an #FlKeyboardManager.
86+
* @result: a #GAsyncResult.
87+
* @error: (allow-none): #GError location to store the error occurring, or %NULL
88+
* to ignore.
89+
*
90+
* Completes request started with fl_keyboard_manager_handle_event().
91+
*
92+
* Returns: %TRUE on success.
93+
*/
94+
gboolean fl_keyboard_manager_handle_event_finish(FlKeyboardManager* manager,
95+
GAsyncResult* result,
96+
GError** error);
6397

6498
/**
6599
* fl_keyboard_manager_is_state_clear:

0 commit comments

Comments
 (0)