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+
5684struct _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
196166static 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
468441void 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
509485void 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-
555522void fl_keyboard_manager_set_get_pressed_state_handler (
556523 FlKeyboardManager* self,
557524 FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler,
0 commit comments