From e53bd2a1038e45a045e02747fc67d102c79b9e9b Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 22 Jan 2025 12:18:20 +1300 Subject: [PATCH] Remove FlKeyboardViewDelegate (#161705) Instead, do the filtering at the point the event is redispatched. --- .../ci/licenses_golden/licenses_flutter | 4 - .../src/flutter/shell/platform/linux/BUILD.gn | 2 - .../linux/fl_keyboard_handler_test.cc | 49 +---- .../platform/linux/fl_keyboard_manager.cc | 59 +----- .../platform/linux/fl_keyboard_manager.h | 21 +-- .../linux/fl_keyboard_manager_test.cc | 169 ++---------------- .../linux/fl_keyboard_view_delegate.cc | 22 --- .../linux/fl_keyboard_view_delegate.h | 55 ------ .../flutter/shell/platform/linux/fl_view.cc | 68 ++++--- 9 files changed, 61 insertions(+), 388 deletions(-) delete mode 100644 engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.cc delete mode 100644 engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.h diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index 390e92369e..fd08431406 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -44394,8 +44394,6 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_layout_test.cc + ../.. ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_manager.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_manager.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_manager_test.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_message_codec.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_method_call.cc + ../../../flutter/LICENSE @@ -47370,8 +47368,6 @@ FILE: ../../../flutter/shell/platform/linux/fl_keyboard_layout_test.cc FILE: ../../../flutter/shell/platform/linux/fl_keyboard_manager.cc FILE: ../../../flutter/shell/platform/linux/fl_keyboard_manager.h FILE: ../../../flutter/shell/platform/linux/fl_keyboard_manager_test.cc -FILE: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.cc -FILE: ../../../flutter/shell/platform/linux/fl_keyboard_view_delegate.h FILE: ../../../flutter/shell/platform/linux/fl_message_codec.cc FILE: ../../../flutter/shell/platform/linux/fl_message_codec_test.cc FILE: ../../../flutter/shell/platform/linux/fl_method_call.cc diff --git a/engine/src/flutter/shell/platform/linux/BUILD.gn b/engine/src/flutter/shell/platform/linux/BUILD.gn index 3ef0b715bc..c9eb379250 100644 --- a/engine/src/flutter/shell/platform/linux/BUILD.gn +++ b/engine/src/flutter/shell/platform/linux/BUILD.gn @@ -82,7 +82,6 @@ source_set("flutter_linux_sources") { "fl_engine_private.h", "fl_keyboard_handler.h", "fl_keyboard_manager.h", - "fl_keyboard_view_delegate.h", "fl_key_event.h", "fl_key_channel_responder.h", "fl_key_embedder_responder.h", @@ -121,7 +120,6 @@ source_set("flutter_linux_sources") { "fl_keyboard_handler.cc", "fl_keyboard_layout.cc", "fl_keyboard_manager.cc", - "fl_keyboard_view_delegate.cc", "fl_message_codec.cc", "fl_method_call.cc", "fl_method_channel.cc", diff --git a/engine/src/flutter/shell/platform/linux/fl_keyboard_handler_test.cc b/engine/src/flutter/shell/platform/linux/fl_keyboard_handler_test.cc index 5cb1f6c86b..b3e4f6aee4 100644 --- a/engine/src/flutter/shell/platform/linux/fl_keyboard_handler_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_keyboard_handler_test.cc @@ -17,59 +17,12 @@ static constexpr char kGetKeyboardStateMethod[] = "getKeyboardState"; static constexpr uint64_t kMockPhysicalKey = 42; static constexpr uint64_t kMockLogicalKey = 42; -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(FlMockKeyboardHandlerDelegate, - fl_mock_keyboard_handler_delegate, - FL, - MOCK_KEYBOARD_HANDLER_DELEGATE, - GObject); - -G_END_DECLS - -struct _FlMockKeyboardHandlerDelegate { - GObject parent_instance; -}; - -static void fl_mock_keyboard_handler_delegate_keyboard_view_delegate_iface_init( - FlKeyboardViewDelegateInterface* iface); - -G_DEFINE_TYPE_WITH_CODE( - FlMockKeyboardHandlerDelegate, - fl_mock_keyboard_handler_delegate, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE( - fl_keyboard_view_delegate_get_type(), - fl_mock_keyboard_handler_delegate_keyboard_view_delegate_iface_init)) - -static void fl_mock_keyboard_handler_delegate_init( - FlMockKeyboardHandlerDelegate* self) {} - -static void fl_mock_keyboard_handler_delegate_class_init( - FlMockKeyboardHandlerDelegateClass* klass) {} - -static void fl_mock_keyboard_handler_delegate_keyboard_view_delegate_iface_init( - FlKeyboardViewDelegateInterface* iface) {} - -static FlMockKeyboardHandlerDelegate* fl_mock_keyboard_handler_delegate_new() { - FlMockKeyboardHandlerDelegate* self = FL_MOCK_KEYBOARD_HANDLER_DELEGATE( - g_object_new(fl_mock_keyboard_handler_delegate_get_type(), nullptr)); - - // Added to stop compiler complaining about an unused function. - FL_IS_MOCK_KEYBOARD_HANDLER_DELEGATE(self); - - return self; -} - TEST(FlKeyboardHandlerTest, KeyboardChannelGetPressedState) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlMockKeyboardHandlerDelegate) view_delegate = - fl_mock_keyboard_handler_delegate_new(); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view_delegate)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_get_pressed_state_handler( manager, [](gpointer user_data) { diff --git a/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc b/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc index 1298a03c7c..5b7abecf19 100644 --- a/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc +++ b/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc @@ -86,8 +86,6 @@ struct _FlKeyboardManager { GWeakRef engine; - GWeakRef view_delegate; - FlKeyboardManagerSendKeyEventHandler send_key_event_handler; gpointer send_key_event_handler_user_data; @@ -101,9 +99,6 @@ struct _FlKeyboardManager { FlKeyChannelResponder* key_channel_responder; - // Events in the process of being redispatched. - GPtrArray* pending_redispatches; - // Record the derived layout. // // It is cleared when the platform reports a layout switch. Each entry, @@ -145,21 +140,7 @@ static void complete_handle_event(FlKeyboardManager* self, GTask* task) { return; } - // Redispatch if needed. - if (!data->handled) { - gboolean filtered = FALSE; - g_autoptr(FlKeyboardViewDelegate) view_delegate = - FL_KEYBOARD_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate)); - if (view_delegate != nullptr) { - filtered = fl_keyboard_view_delegate_text_filter_key_press(view_delegate, - data->event); - } - data->redispatch = !filtered; - if (data->redispatch) { - g_ptr_array_add(self->pending_redispatches, g_object_ref(data->event)); - } - } - + data->redispatch = !data->handled; g_task_return_boolean(task, TRUE); } @@ -222,12 +203,6 @@ static uint16_t convert_key_to_char(FlKeyboardManager* self, // Make sure that Flutter has derived the layout for the group of the event, // if the event contains a goal keycode. static void guarantee_layout(FlKeyboardManager* self, FlKeyEvent* event) { - g_autoptr(FlKeyboardViewDelegate) view_delegate = - FL_KEYBOARD_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate)); - if (view_delegate == nullptr) { - return; - } - guint8 group = fl_key_event_get_group(event); if (fl_keyboard_layout_has_group(self->derived_layout, group)) { return; @@ -313,14 +288,12 @@ static void fl_keyboard_manager_dispose(GObject* object) { g_cancellable_cancel(self->cancellable); g_weak_ref_clear(&self->engine); - g_weak_ref_clear(&self->view_delegate); self->keycode_to_goals.reset(); self->logical_to_mandatory_goals.reset(); g_clear_object(&self->key_embedder_responder); g_clear_object(&self->key_channel_responder); - g_ptr_array_free(self->pending_redispatches, TRUE); g_clear_object(&self->derived_layout); if (self->keymap_keys_changed_cb_id != 0) { g_signal_handler_disconnect(self->keymap, self->keymap_keys_changed_cb_id); @@ -349,24 +322,17 @@ static void fl_keyboard_manager_init(FlKeyboardManager* self) { } } - self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref); - self->keymap = gdk_keymap_get_for_display(gdk_display_get_default()); self->keymap_keys_changed_cb_id = g_signal_connect_swapped( self->keymap, "keys-changed", G_CALLBACK(keymap_keys_changed_cb), self); self->cancellable = g_cancellable_new(); } -FlKeyboardManager* fl_keyboard_manager_new( - FlEngine* engine, - FlKeyboardViewDelegate* view_delegate) { - g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(view_delegate), nullptr); - +FlKeyboardManager* fl_keyboard_manager_new(FlEngine* engine) { FlKeyboardManager* self = FL_KEYBOARD_MANAGER( g_object_new(fl_keyboard_manager_get_type(), nullptr)); g_weak_ref_init(&self->engine, engine); - g_weak_ref_init(&self->view_delegate, view_delegate); self->key_embedder_responder = fl_key_embedder_responder_new( [](const FlutterKeyEvent* event, FlutterKeyEventCallback callback, @@ -417,27 +383,6 @@ FlKeyboardManager* fl_keyboard_manager_new( return self; } -gboolean fl_keyboard_manager_is_redispatched(FlKeyboardManager* self, - FlKeyEvent* event) { - g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE); - - guint32 time = fl_key_event_get_time(event); - gboolean is_press = !!fl_key_event_get_is_press(event); - guint16 keycode = fl_key_event_get_keycode(event); - for (guint i = 0; i < self->pending_redispatches->len; i++) { - FlKeyEvent* e = - FL_KEY_EVENT(g_ptr_array_index(self->pending_redispatches, i)); - if (fl_key_event_get_time(e) == time && - !!fl_key_event_get_is_press(e) == is_press && - fl_key_event_get_keycode(e) == keycode) { - g_ptr_array_remove_index(self->pending_redispatches, i); - return TRUE; - } - } - - return FALSE; -} - void fl_keyboard_manager_handle_event(FlKeyboardManager* self, FlKeyEvent* event, GCancellable* cancellable, diff --git a/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.h b/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.h index ef9c51a704..ca125fde7e 100644 --- a/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.h +++ b/engine/src/flutter/shell/platform/linux/fl_keyboard_manager.h @@ -7,7 +7,8 @@ #include -#include "flutter/shell/platform/linux/fl_keyboard_view_delegate.h" +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/linux/fl_key_event.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h" G_BEGIN_DECLS @@ -37,28 +38,12 @@ G_DECLARE_FINAL_TYPE(FlKeyboardManager, /** * fl_keyboard_manager_new: * @engine: an #FlEngine. - * @view_delegate: An interface that the manager requires to communicate with - * the platform. Usually implemented by FlView. * * Create a new #FlKeyboardManager. * * Returns: a new #FlKeyboardManager. */ -FlKeyboardManager* fl_keyboard_manager_new( - FlEngine* engine, - FlKeyboardViewDelegate* view_delegate); - -/** - * fl_keyboard_manager_is_redispatched: - * @manager: an #FlKeyboardManager. - * @event: an event received from the system. - * - * Checks if an event was redispacthed from this manager. - * - * Returns: %TRUE if the event is redispatched. - */ -gboolean fl_keyboard_manager_is_redispatched(FlKeyboardManager* manager, - FlKeyEvent* event); +FlKeyboardManager* fl_keyboard_manager_new(FlEngine* engine); /** * fl_keyboard_manager_handle_event: diff --git a/engine/src/flutter/shell/platform/linux/fl_keyboard_manager_test.cc b/engine/src/flutter/shell/platform/linux/fl_keyboard_manager_test.cc index 2f61e635b8..f5ced8f3b2 100644 --- a/engine/src/flutter/shell/platform/linux/fl_keyboard_manager_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_keyboard_manager_test.cc @@ -117,62 +117,6 @@ typedef std::vector MockLayoutData; extern const MockLayoutData kLayoutRussian; extern const MockLayoutData kLayoutFrench; -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(FlMockViewDelegate, - fl_mock_view_delegate, - FL, - MOCK_VIEW_DELEGATE, - GObject); - -G_END_DECLS - -struct _FlMockViewDelegate { - GObject parent_instance; - bool text_filter_result; -}; - -static void fl_mock_view_keyboard_delegate_iface_init( - FlKeyboardViewDelegateInterface* iface); - -G_DEFINE_TYPE_WITH_CODE( - FlMockViewDelegate, - fl_mock_view_delegate, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(fl_keyboard_view_delegate_get_type(), - fl_mock_view_keyboard_delegate_iface_init)) - -static void fl_mock_view_delegate_init(FlMockViewDelegate* self) {} - -static void fl_mock_view_delegate_class_init(FlMockViewDelegateClass* klass) {} - -static gboolean fl_mock_view_keyboard_text_filter_key_press( - FlKeyboardViewDelegate* view_delegate, - FlKeyEvent* event) { - FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate); - return self->text_filter_result; -} - -static void fl_mock_view_keyboard_delegate_iface_init( - FlKeyboardViewDelegateInterface* iface) { - iface->text_filter_key_press = fl_mock_view_keyboard_text_filter_key_press; -} - -static FlMockViewDelegate* fl_mock_view_delegate_new() { - FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE( - g_object_new(fl_mock_view_delegate_get_type(), nullptr)); - - // Added to stop compiler complaining about an unused function. - FL_IS_MOCK_VIEW_DELEGATE(self); - - return self; -} - -static void fl_mock_view_set_text_filter_result(FlMockViewDelegate* self, - bool result) { - self->text_filter_result = result; -} - TEST(FlKeyboardManagerTest, EngineNoResponseChannelHandled) { ::testing::NiceMock mock_keymap; @@ -192,9 +136,7 @@ TEST(FlKeyboardManagerTest, EngineNoResponseChannelHandled) { g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); // Don't handle first event - async call never completes. fl_keyboard_manager_set_send_key_event_handler( @@ -245,12 +187,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledSync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -287,11 +227,6 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledSync) { }, loop); g_main_loop_run(loop); - - // Check duplicate event is not detected as redispatched. - g_autoptr(FlKeyEvent) event2 = fl_key_event_new( - 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast(0), 0); - EXPECT_FALSE(fl_keyboard_manager_is_redispatched(manager, event2)); } TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledSync) { @@ -299,12 +234,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledSync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -341,11 +274,6 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledSync) { }, loop); g_main_loop_run(loop); - - // Check duplicate event is not detected as redispatched. - g_autoptr(FlKeyEvent) event2 = fl_key_event_new( - 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast(0), 0); - EXPECT_FALSE(fl_keyboard_manager_is_redispatched(manager, event2)); } TEST(FlKeyboardManagerTest, EngineHandledChannelHandledSync) { @@ -353,12 +281,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledSync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -395,11 +321,6 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledSync) { }, loop); g_main_loop_run(loop); - - // Check duplicate event is not detected as redispatched. - g_autoptr(FlKeyEvent) event2 = fl_key_event_new( - 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast(0), 0); - EXPECT_FALSE(fl_keyboard_manager_is_redispatched(manager, event2)); } TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledSync) { @@ -407,12 +328,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledSync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -449,11 +368,6 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledSync) { }, loop); g_main_loop_run(loop); - - // Check duplicate event is detected as redispatched. - g_autoptr(FlKeyEvent) event2 = fl_key_event_new( - 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast(0), 0); - EXPECT_TRUE(fl_keyboard_manager_is_redispatched(manager, event2)); } static void channel_respond(FlMockBinaryMessenger* messenger, @@ -469,12 +383,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledAsync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -535,12 +447,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledAsync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -601,12 +511,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledAsync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -667,12 +575,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledAsync) { g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); g_autoptr(FlEngine) engine = FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); fl_keyboard_manager_set_lookup_key_handler( manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; }, nullptr); @@ -728,59 +634,12 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledAsync) { g_main_loop_run(loop); } -TEST(FlKeyboardManagerTest, TextFilter) { - ::testing::NiceMock mock_keymap; - - g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlEngine) engine = - FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger", - FL_BINARY_MESSENGER(messenger), nullptr)); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); - - // Event would have been redispatched, but is filtered. - fl_mock_view_set_text_filter_result(view, TRUE); - fl_mock_binary_messenger_set_json_message_channel( - messenger, "flutter/keyevent", - [](FlMockBinaryMessenger* messenger, GTask* task, FlValue* message, - gpointer user_data) { - g_autoptr(FlValue) return_value = fl_value_new_map(); - fl_value_set_string_take(return_value, "handled", - fl_value_new_bool(FALSE)); - return fl_value_ref(return_value); - }, - nullptr); - fl_keyboard_manager_set_send_key_event_handler( - manager, - [](const FlutterKeyEvent* event, FlutterKeyEventCallback callback, - void* callback_user_data, - gpointer user_data) { callback(false, callback_user_data); }, - nullptr); - g_autoptr(FlKeyEvent) event = fl_key_event_new( - 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast(0), 0); - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - fl_keyboard_manager_handle_event( - manager, event, nullptr, - [](GObject* object, GAsyncResult* result, gpointer user_data) { - g_autoptr(FlKeyEvent) redispatched_event = nullptr; - EXPECT_TRUE(fl_keyboard_manager_handle_event_finish( - FL_KEYBOARD_MANAGER(object), result, &redispatched_event, nullptr)); - EXPECT_EQ(redispatched_event, nullptr); - g_main_loop_quit(static_cast(user_data)); - }, - loop); - g_main_loop_run(loop); -} - TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) { ::testing::NiceMock mock_keymap; g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlEngine) engine = fl_engine_new(project); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); g_autoptr(GPtrArray) call_records = g_ptr_array_new_with_free_func( reinterpret_cast(call_record_free)); @@ -915,9 +774,7 @@ TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) { g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlEngine) engine = fl_engine_new(project); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); g_autoptr(GPtrArray) call_records = g_ptr_array_new_with_free_func( reinterpret_cast(call_record_free)); @@ -971,9 +828,7 @@ TEST(FlKeyboardManagerTest, GetPressedState) { g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlEngine) engine = fl_engine_new(project); - g_autoptr(FlMockViewDelegate) view = fl_mock_view_delegate_new(); - g_autoptr(FlKeyboardManager) manager = - fl_keyboard_manager_new(engine, FL_KEYBOARD_VIEW_DELEGATE(view)); + g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine); // Dispatch a key event. g_autoptr(FlKeyEvent) event = fl_key_event_new( diff --git a/engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.cc b/engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.cc deleted file mode 100644 index 27ec02f363..0000000000 --- a/engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.cc +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/shell/platform/linux/fl_keyboard_view_delegate.h" - -G_DEFINE_INTERFACE(FlKeyboardViewDelegate, - fl_keyboard_view_delegate, - G_TYPE_OBJECT) - -static void fl_keyboard_view_delegate_default_init( - FlKeyboardViewDelegateInterface* iface) {} - -gboolean fl_keyboard_view_delegate_text_filter_key_press( - FlKeyboardViewDelegate* self, - FlKeyEvent* event) { - g_return_val_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(self), false); - g_return_val_if_fail(event != nullptr, false); - - return FL_KEYBOARD_VIEW_DELEGATE_GET_IFACE(self)->text_filter_key_press( - self, event); -} diff --git a/engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.h b/engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.h deleted file mode 100644 index edb706f773..0000000000 --- a/engine/src/flutter/shell/platform/linux/fl_keyboard_view_delegate.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_KEYBOARD_VIEW_DELEGATE_H_ -#define FLUTTER_SHELL_PLATFORM_LINUX_FL_KEYBOARD_VIEW_DELEGATE_H_ - -#include -#include -#include -#include - -#include "flutter/shell/platform/embedder/embedder.h" -#include "flutter/shell/platform/linux/fl_key_event.h" -#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h" - -G_BEGIN_DECLS - -G_DECLARE_INTERFACE(FlKeyboardViewDelegate, - fl_keyboard_view_delegate, - FL, - KEYBOARD_VIEW_DELEGATE, - GObject); - -/** - * FlKeyboardViewDelegate: - * - * An interface for a class that provides `FlKeyboardHandler` with - * platform-related features. - * - * This interface is typically implemented by `FlView`. - */ - -struct _FlKeyboardViewDelegateInterface { - GTypeInterface g_iface; - - gboolean (*text_filter_key_press)(FlKeyboardViewDelegate* delegate, - FlKeyEvent* event); -}; - -/** - * fl_keyboard_view_delegate_text_filter_key_press: - * - * Handles `FlKeyboardHandler`'s request to check if the GTK text input IM - * filter would like to handle a GDK event. - * - * The ownership of the `event` is kept by the keyboard handler. - */ -gboolean fl_keyboard_view_delegate_text_filter_key_press( - FlKeyboardViewDelegate* delegate, - FlKeyEvent* event); - -G_END_DECLS - -#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEYBOARD_VIEW_DELEGATE_H_ diff --git a/engine/src/flutter/shell/platform/linux/fl_view.cc b/engine/src/flutter/shell/platform/linux/fl_view.cc index ea634d4cea..92eafd772d 100644 --- a/engine/src/flutter/shell/platform/linux/fl_view.cc +++ b/engine/src/flutter/shell/platform/linux/fl_view.cc @@ -15,7 +15,6 @@ #include "flutter/shell/platform/linux/fl_key_event.h" #include "flutter/shell/platform/linux/fl_keyboard_handler.h" #include "flutter/shell/platform/linux/fl_keyboard_manager.h" -#include "flutter/shell/platform/linux/fl_keyboard_view_delegate.h" #include "flutter/shell/platform/linux/fl_plugin_registrar_private.h" #include "flutter/shell/platform/linux/fl_pointer_manager.h" #include "flutter/shell/platform/linux/fl_renderer_gdk.h" @@ -68,6 +67,9 @@ struct _FlView { // Manages keyboard events. FlKeyboardManager* keyboard_manager; + // Key events that have been redispatched. + GPtrArray* redispatched_key_events; + // Flutter system channel handlers. FlKeyboardHandler* keyboard_handler; FlTextInputHandler* text_input_handler; @@ -90,9 +92,6 @@ static void fl_renderable_iface_init(FlRenderableInterface* iface); static void fl_view_plugin_registry_iface_init( FlPluginRegistryInterface* iface); -static void fl_view_keyboard_delegate_iface_init( - FlKeyboardViewDelegateInterface* iface); - static void fl_view_text_input_delegate_iface_init( FlTextInputViewDelegateInterface* iface); @@ -103,10 +102,8 @@ G_DEFINE_TYPE_WITH_CODE( G_IMPLEMENT_INTERFACE(fl_renderable_get_type(), fl_renderable_iface_init) G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(), fl_view_plugin_registry_iface_init) - G_IMPLEMENT_INTERFACE(fl_keyboard_view_delegate_get_type(), - fl_view_keyboard_delegate_iface_init) - G_IMPLEMENT_INTERFACE(fl_text_input_view_delegate_get_type(), - fl_view_text_input_delegate_iface_init)) + G_IMPLEMENT_INTERFACE(fl_text_input_view_delegate_get_type(), + fl_view_text_input_delegate_iface_init)) // Emit the first frame signal in the main thread. static gboolean first_frame_idle_cb(gpointer user_data) { @@ -138,8 +135,8 @@ static void init_keyboard(FlView* self) { self->text_input_handler = fl_text_input_handler_new( messenger, im_context, FL_TEXT_INPUT_VIEW_DELEGATE(self)); g_clear_object(&self->keyboard_manager); - self->keyboard_manager = - fl_keyboard_manager_new(self->engine, FL_KEYBOARD_VIEW_DELEGATE(self)); + self->keyboard_manager = fl_keyboard_manager_new(self->engine); + g_ptr_array_set_size(self->redispatched_key_events, 0); g_clear_object(&self->keyboard_handler); self->keyboard_handler = fl_keyboard_handler_new(messenger, self->keyboard_manager); @@ -332,16 +329,6 @@ static void fl_view_plugin_registry_iface_init( iface->get_registrar_for_plugin = fl_view_get_registrar_for_plugin; } -static void fl_view_keyboard_delegate_iface_init( - FlKeyboardViewDelegateInterface* iface) { - iface->text_filter_key_press = [](FlKeyboardViewDelegate* view_delegate, - FlKeyEvent* event) { - FlView* self = FL_VIEW(view_delegate); - return fl_text_input_handler_filter_keypress(self->text_input_handler, - event); - }; -} - static void fl_view_text_input_delegate_iface_init( FlTextInputViewDelegateInterface* iface) { iface->translate_coordinates = [](FlTextInputViewDelegate* delegate, @@ -656,6 +643,7 @@ static void fl_view_dispose(GObject* object) { g_clear_object(&self->pointer_manager); g_clear_object(&self->touch_manager); g_clear_object(&self->keyboard_manager); + g_clear_pointer(&self->redispatched_key_events, g_ptr_array_unref); g_clear_object(&self->keyboard_handler); g_clear_object(&self->view_accessible); g_clear_object(&self->cancellable); @@ -673,32 +661,59 @@ static void fl_view_realize(GtkWidget* widget) { gtk_widget_realize(GTK_WIDGET(self->gl_area)); } +static gboolean event_is_redispatched(FlView* self, FlKeyEvent* event) { + guint32 time = fl_key_event_get_time(event); + gboolean is_press = !!fl_key_event_get_is_press(event); + guint16 keycode = fl_key_event_get_keycode(event); + for (guint i = 0; i < self->redispatched_key_events->len; i++) { + FlKeyEvent* e = + FL_KEY_EVENT(g_ptr_array_index(self->redispatched_key_events, i)); + if (fl_key_event_get_time(e) == time && + !!fl_key_event_get_is_press(e) == is_press && + fl_key_event_get_keycode(e) == keycode) { + g_ptr_array_remove_index(self->redispatched_key_events, i); + return TRUE; + } + } + + return FALSE; +} + static gboolean handle_key_event(FlView* self, GdkEventKey* key_event) { g_autoptr(FlKeyEvent) event = fl_key_event_new_from_gdk_event( gdk_event_copy(reinterpret_cast(key_event))); - if (fl_keyboard_manager_is_redispatched(self->keyboard_manager, event)) { + if (event_is_redispatched(self, event)) { return FALSE; } fl_keyboard_manager_handle_event( self->keyboard_manager, event, self->cancellable, [](GObject* object, GAsyncResult* result, gpointer user_data) { + FlView* self = FL_VIEW(user_data); + g_autoptr(FlKeyEvent) redispatch_event = nullptr; g_autoptr(GError) error = nullptr; if (!fl_keyboard_manager_handle_event_finish( FL_KEYBOARD_MANAGER(object), result, &redispatch_event, &error)) { - if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - g_warning("Failed to handle key event: %s", error->message); + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + return; } + + g_warning("Failed to handle key event: %s", error->message); } if (redispatch_event != nullptr) { - gdk_event_put(fl_key_event_get_origin(redispatch_event)); + if (!fl_text_input_handler_filter_keypress(self->text_input_handler, + redispatch_event)) { + g_ptr_array_add(self->redispatched_key_events, + g_object_ref(redispatch_event)); + gdk_event_put(fl_key_event_get_origin(redispatch_event)); + } } }, - nullptr); + self); return TRUE; } @@ -746,6 +761,9 @@ static void fl_view_init(FlView* self) { .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0}; self->background_color = gdk_rgba_copy(&default_background); + self->redispatched_key_events = + g_ptr_array_new_with_free_func(g_object_unref); + GtkWidget* event_box = gtk_event_box_new(); gtk_widget_set_hexpand(event_box, TRUE); gtk_widget_set_vexpand(event_box, TRUE);