Remove FlKeyboardViewDelegate (#161705)

Instead, do the filtering at the point the event is redispatched.
This commit is contained in:
Robert Ancell 2025-01-22 12:18:20 +13:00 committed by GitHub
parent d35626d47a
commit e53bd2a103
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 61 additions and 388 deletions

View File

@ -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

View File

@ -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",

View File

@ -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) {

View File

@ -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,

View File

@ -7,7 +7,8 @@
#include <gdk/gdk.h>
#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:

View File

@ -117,62 +117,6 @@ typedef std::vector<const MockGroupLayoutData*> 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<flutter::testing::MockKeymap> 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<GdkModifierType>(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<GdkModifierType>(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<GdkModifierType>(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<GdkModifierType>(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<flutter::testing::MockKeymap> 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<GdkModifierType>(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<GMainLoop*>(user_data));
},
loop);
g_main_loop_run(loop);
}
TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
::testing::NiceMock<flutter::testing::MockKeymap> 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<GDestroyNotify>(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<GDestroyNotify>(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(

View File

@ -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);
}

View File

@ -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 <gdk/gdk.h>
#include <cinttypes>
#include <functional>
#include <memory>
#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_

View File

@ -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<GdkEvent*>(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);