Skip to content

Commit f2ce662

Browse files
Refactor event redispatching (#161701)
Instead of doing the redispatching from inside FlKeyboardManager, return the event asynchronously to the code that provided the event in the first case. That code has all the context on how to do the redispatch - this will be more complicated in a multi-view case.
1 parent 12518fa commit f2ce662

File tree

10 files changed

+482
-649
lines changed

10 files changed

+482
-649
lines changed

engine/src/flutter/ci/licenses_golden/licenses_flutter

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44394,8 +44394,6 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_layout_test.cc + ../..
4439444394
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_manager.cc + ../../../flutter/LICENSE
4439544395
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_manager.h + ../../../flutter/LICENSE
4439644396
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_manager_test.cc + ../../../flutter/LICENSE
44397-
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.cc + ../../../flutter/LICENSE
44398-
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.h + ../../../flutter/LICENSE
4439944397
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.cc + ../../../flutter/LICENSE
4440044398
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.h + ../../../flutter/LICENSE
4440144399
ORIGIN: ../../../flutter/shell/platform/linux/fl_message_codec.cc + ../../../flutter/LICENSE
@@ -47372,8 +47370,6 @@ FILE: ../../../flutter/shell/platform/linux/fl_keyboard_layout_test.cc
4737247370
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_manager.cc
4737347371
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_manager.h
4737447372
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_manager_test.cc
47375-
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.cc
47376-
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.h
4737747373
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.cc
4737847374
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.h
4737947375
FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc

engine/src/flutter/shell/platform/linux/BUILD.gn

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ source_set("flutter_linux_sources") {
8282
"fl_engine_private.h",
8383
"fl_keyboard_handler.h",
8484
"fl_keyboard_manager.h",
85-
"fl_keyboard_pending_event.h",
8685
"fl_keyboard_view_delegate.h",
8786
"fl_key_event.h",
8887
"fl_key_channel_responder.h",
@@ -122,7 +121,6 @@ source_set("flutter_linux_sources") {
122121
"fl_keyboard_handler.cc",
123122
"fl_keyboard_layout.cc",
124123
"fl_keyboard_manager.cc",
125-
"fl_keyboard_pending_event.cc",
126124
"fl_keyboard_view_delegate.cc",
127125
"fl_message_codec.cc",
128126
"fl_method_call.cc",

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,6 @@ GdkEvent* fl_key_event_get_origin(FlKeyEvent* self) {
111111
return self->origin;
112112
}
113113

114-
uint64_t fl_key_event_hash(FlKeyEvent* self) {
115-
g_return_val_if_fail(FL_IS_KEY_EVENT(self), 0);
116-
117-
// Combine the event timestamp, the type of event, and the hardware keycode
118-
// (scan code) of the event to come up with a unique id for this event that
119-
// can be derived solely from the event data itself, so that we can identify
120-
// whether or not we have seen this event already.
121-
guint64 type =
122-
static_cast<uint64_t>(self->is_press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
123-
guint64 keycode = static_cast<uint64_t>(self->keycode);
124-
return (self->time & 0xffffffff) | ((type & 0xffff) << 32) |
125-
((keycode & 0xffff) << 48);
126-
}
127-
128114
static void fl_key_event_dispose(GObject* object) {
129115
FlKeyEvent* self = FL_KEY_EVENT(object);
130116

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,4 @@ guint8 fl_key_event_get_group(FlKeyEvent* event);
5555

5656
GdkEvent* fl_key_event_get_origin(FlKeyEvent* event);
5757

58-
/**
59-
* fl_key_event_hash:
60-
* @event: an #FlKeyEvent.
61-
*
62-
* Calculates a unique ID for a given FlKeyEvent object to use for
63-
* identification of responses from the framework.
64-
*
65-
* Returns: a hash code.
66-
*/
67-
uint64_t fl_key_event_hash(FlKeyEvent* event);
68-
6958
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_H_

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

Lines changed: 90 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "flutter/shell/platform/linux/fl_key_channel_responder.h"
1414
#include "flutter/shell/platform/linux/fl_key_embedder_responder.h"
1515
#include "flutter/shell/platform/linux/fl_keyboard_layout.h"
16-
#include "flutter/shell/platform/linux/fl_keyboard_pending_event.h"
1716
#include "flutter/shell/platform/linux/key_mapping.h"
1817

1918
// Turn on this flag to print complete layout data when switching IMEs. The data
@@ -53,6 +52,35 @@ void debug_format_layout_data(std::string& debug_layout_data,
5352

5453
} // namespace
5554

55+
typedef struct {
56+
// Event being handled.
57+
FlKeyEvent* event;
58+
59+
// TRUE if the embedder has responded.
60+
gboolean embedder_responded;
61+
62+
// TRUE if the channel has responded.
63+
gboolean channel_responded;
64+
65+
// TRUE if this event is to be redispatched;
66+
gboolean redispatch;
67+
68+
// TRUE if either the embedder of channel handled this event (or both).
69+
gboolean handled;
70+
} HandleEventData;
71+
72+
static HandleEventData* handle_event_data_new(FlKeyEvent* event) {
73+
HandleEventData* data =
74+
static_cast<HandleEventData*>(g_new0(HandleEventData, 1));
75+
data->event = FL_KEY_EVENT(g_object_ref(event));
76+
return data;
77+
}
78+
79+
static void handle_event_data_free(HandleEventData* data) {
80+
g_object_unref(data->event);
81+
g_free(data);
82+
}
83+
5684
struct _FlKeyboardManager {
5785
GObject parent_instance;
5886

@@ -66,26 +94,14 @@ struct _FlKeyboardManager {
6694
FlKeyboardManagerLookupKeyHandler lookup_key_handler;
6795
gpointer lookup_key_handler_user_data;
6896

69-
FlKeyboardManagerRedispatchEventHandler redispatch_handler;
70-
gpointer redispatch_handler_user_data;
71-
7297
FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler;
7398
gpointer get_pressed_state_handler_user_data;
7499

75100
FlKeyEmbedderResponder* key_embedder_responder;
76101

77102
FlKeyChannelResponder* key_channel_responder;
78103

79-
// An array of #FlKeyboardPendingEvent.
80-
//
81-
// Its elements are *not* unreferenced when removed. When FlKeyboardManager is
82-
// disposed, this array will be set with a free_func so that the elements are
83-
// unreferenced when removed.
84-
GPtrArray* pending_responds;
85-
86-
// An array of #FlKeyboardPendingEvent.
87-
//
88-
// Its elements are unreferenced when removed.
104+
// Events in the process of being redispatched.
89105
GPtrArray* pending_redispatches;
90106

91107
// Record the derived layout.
@@ -120,88 +136,44 @@ static void keymap_keys_changed_cb(FlKeyboardManager* self) {
120136
self->derived_layout = fl_keyboard_layout_new();
121137
}
122138

123-
// This is an exact copy of g_ptr_array_find_with_equal_func. Somehow CI
124-
// reports that can not find symbol g_ptr_array_find_with_equal_func, despite
125-
// the fact that it runs well locally.
126-
static gboolean g_ptr_array_find_with_equal_func1(GPtrArray* haystack,
127-
gconstpointer needle,
128-
GEqualFunc equal_func,
129-
guint* index_) {
130-
guint i;
131-
g_return_val_if_fail(haystack != NULL, FALSE);
132-
if (equal_func == NULL) {
133-
equal_func = g_direct_equal;
134-
}
135-
for (i = 0; i < haystack->len; i++) {
136-
if (equal_func(g_ptr_array_index(haystack, i), needle)) {
137-
if (index_ != NULL) {
138-
*index_ = i;
139-
}
140-
return TRUE;
141-
}
142-
}
143-
144-
return FALSE;
145-
}
146-
147-
// Compare a #FlKeyboardPendingEvent with the given hash.
148-
static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b) {
149-
FlKeyboardPendingEvent* pending =
150-
FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
151-
uint64_t hash = *reinterpret_cast<const uint64_t*>(b);
152-
return fl_keyboard_pending_event_get_hash(pending) == hash;
153-
}
139+
static void complete_handle_event(FlKeyboardManager* self, GTask* task) {
140+
HandleEventData* data =
141+
static_cast<HandleEventData*>(g_task_get_task_data(task));
154142

155-
// The callback used by a responder after the event was dispatched.
156-
static void responder_handle_event_callback(FlKeyboardManager* self,
157-
FlKeyboardPendingEvent* pending) {
158-
g_autoptr(FlKeyboardViewDelegate) view_delegate =
159-
FL_KEYBOARD_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate));
160-
if (view_delegate == nullptr) {
143+
// Waiting for responses.
144+
if (!data->embedder_responded || !data->channel_responded) {
161145
return;
162146
}
163147

164-
// All responders have replied.
165-
if (fl_keyboard_pending_event_is_complete(pending)) {
166-
g_ptr_array_remove(self->pending_responds, pending);
167-
bool should_redispatch =
168-
!fl_keyboard_pending_event_get_any_handled(pending) &&
169-
!fl_keyboard_view_delegate_text_filter_key_press(
170-
view_delegate, fl_keyboard_pending_event_get_event(pending));
171-
if (should_redispatch) {
172-
g_ptr_array_add(self->pending_redispatches, g_object_ref(pending));
173-
FlKeyEvent* event = fl_keyboard_pending_event_get_event(pending);
174-
if (self->redispatch_handler != nullptr) {
175-
self->redispatch_handler(event, self->redispatch_handler_user_data);
176-
} else {
177-
GdkEventType event_type =
178-
gdk_event_get_event_type(fl_key_event_get_origin(event));
179-
g_return_if_fail(event_type == GDK_KEY_PRESS ||
180-
event_type == GDK_KEY_RELEASE);
181-
gdk_event_put(fl_key_event_get_origin(event));
182-
}
148+
// Redispatch if needed.
149+
if (!data->handled) {
150+
gboolean filtered = FALSE;
151+
g_autoptr(FlKeyboardViewDelegate) view_delegate =
152+
FL_KEYBOARD_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate));
153+
if (view_delegate != nullptr) {
154+
filtered = fl_keyboard_view_delegate_text_filter_key_press(view_delegate,
155+
data->event);
156+
}
157+
data->redispatch = !filtered;
158+
if (data->redispatch) {
159+
g_ptr_array_add(self->pending_redispatches, g_object_ref(data->event));
183160
}
184161
}
185-
}
186162

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-
}
163+
g_task_return_boolean(task, TRUE);
194164
}
195165

196166
static void responder_handle_embedder_event_callback(bool handled,
197167
gpointer user_data) {
198168
g_autoptr(GTask) task = G_TASK(user_data);
199169
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
200170

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);
171+
HandleEventData* data =
172+
static_cast<HandleEventData*>(g_task_get_task_data(G_TASK(task)));
173+
data->embedder_responded = TRUE;
174+
if (handled) {
175+
data->handled = TRUE;
176+
}
205177

206178
complete_handle_event(self, task);
207179
}
@@ -212,6 +184,10 @@ static void responder_handle_channel_event_cb(GObject* object,
212184
g_autoptr(GTask) task = G_TASK(user_data);
213185
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
214186

187+
HandleEventData* data =
188+
static_cast<HandleEventData*>(g_task_get_task_data(G_TASK(task)));
189+
data->channel_responded = TRUE;
190+
215191
g_autoptr(GError) error = nullptr;
216192
gboolean handled;
217193
if (!fl_key_channel_responder_handle_event_finish(
@@ -221,11 +197,9 @@ static void responder_handle_channel_event_cb(GObject* object,
221197
}
222198
handled = FALSE;
223199
}
224-
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);
200+
if (handled) {
201+
data->handled = TRUE;
202+
}
229203

230204
complete_handle_event(self, task);
231205
}
@@ -346,8 +320,6 @@ static void fl_keyboard_manager_dispose(GObject* object) {
346320

347321
g_clear_object(&self->key_embedder_responder);
348322
g_clear_object(&self->key_channel_responder);
349-
g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
350-
g_ptr_array_free(self->pending_responds, TRUE);
351323
g_ptr_array_free(self->pending_redispatches, TRUE);
352324
g_clear_object(&self->derived_layout);
353325
if (self->keymap_keys_changed_cb_id != 0) {
@@ -377,7 +349,6 @@ static void fl_keyboard_manager_init(FlKeyboardManager* self) {
377349
}
378350
}
379351

380-
self->pending_responds = g_ptr_array_new();
381352
self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
382353

383354
self->keymap = gdk_keymap_get_for_display(gdk_display_get_default());
@@ -450,19 +421,21 @@ gboolean fl_keyboard_manager_is_redispatched(FlKeyboardManager* self,
450421
FlKeyEvent* event) {
451422
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
452423

453-
uint64_t hash = fl_key_event_hash(event);
454-
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 {
464-
return FALSE;
424+
guint32 time = fl_key_event_get_time(event);
425+
gboolean is_press = !!fl_key_event_get_is_press(event);
426+
guint16 keycode = fl_key_event_get_keycode(event);
427+
for (guint i = 0; i < self->pending_redispatches->len; i++) {
428+
FlKeyEvent* e =
429+
FL_KEY_EVENT(g_ptr_array_index(self->pending_redispatches, i));
430+
if (fl_key_event_get_time(e) == time &&
431+
!!fl_key_event_get_is_press(e) == is_press &&
432+
fl_key_event_get_keycode(e) == keycode) {
433+
g_ptr_array_remove_index(self->pending_redispatches, i);
434+
return TRUE;
435+
}
465436
}
437+
438+
return FALSE;
466439
}
467440

468441
void fl_keyboard_manager_handle_event(FlKeyboardManager* self,
@@ -477,9 +450,9 @@ void fl_keyboard_manager_handle_event(FlKeyboardManager* self,
477450

478451
guarantee_layout(self, event);
479452

480-
FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(event);
481-
g_ptr_array_add(self->pending_responds, pending);
482-
g_task_set_task_data(task, g_object_ref(pending), g_object_unref);
453+
g_task_set_task_data(
454+
task, handle_event_data_new(event),
455+
reinterpret_cast<GDestroyNotify>(handle_event_data_free));
483456

484457
uint64_t specified_logical_key = fl_keyboard_layout_get_logical_key(
485458
self->derived_layout, fl_key_event_get_group(event),
@@ -492,18 +465,21 @@ void fl_keyboard_manager_handle_event(FlKeyboardManager* self,
492465
self->cancellable, responder_handle_channel_event_cb, g_object_ref(task));
493466
}
494467

495-
gboolean fl_keyboard_manager_handle_event_finish(FlKeyboardManager* self,
496-
GAsyncResult* result,
497-
GError** error) {
468+
gboolean fl_keyboard_manager_handle_event_finish(
469+
FlKeyboardManager* self,
470+
GAsyncResult* result,
471+
FlKeyEvent** redispatched_event,
472+
GError** error) {
498473
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
499474
g_return_val_if_fail(g_task_is_valid(result, self), FALSE);
500-
return g_task_propagate_boolean(G_TASK(result), error);
501-
}
502475

503-
gboolean fl_keyboard_manager_is_state_clear(FlKeyboardManager* self) {
504-
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
505-
return self->pending_responds->len == 0 &&
506-
self->pending_redispatches->len == 0;
476+
HandleEventData* data =
477+
static_cast<HandleEventData*>(g_task_get_task_data(G_TASK(result)));
478+
if (redispatched_event != nullptr && data->redispatch) {
479+
*redispatched_event = FL_KEY_EVENT(g_object_ref(data->event));
480+
}
481+
482+
return g_task_propagate_boolean(G_TASK(result), error);
507483
}
508484

509485
void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager* self,
@@ -543,15 +519,6 @@ void fl_keyboard_manager_set_lookup_key_handler(
543519
self->lookup_key_handler_user_data = user_data;
544520
}
545521

546-
void fl_keyboard_manager_set_redispatch_handler(
547-
FlKeyboardManager* self,
548-
FlKeyboardManagerRedispatchEventHandler redispatch_handler,
549-
gpointer user_data) {
550-
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
551-
self->redispatch_handler = redispatch_handler;
552-
self->redispatch_handler_user_data = user_data;
553-
}
554-
555522
void fl_keyboard_manager_set_get_pressed_state_handler(
556523
FlKeyboardManager* self,
557524
FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler,

0 commit comments

Comments
 (0)