Remove FlKeyboardViewDelegate (#161705)
Instead, do the filtering at the point the event is redispatched.
This commit is contained in:
parent
d35626d47a
commit
e53bd2a103
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
@ -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_
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user