Make fl_keyboard_manager_handle_event async (#161637)
In this way we can tell when this call completes, which should help testing and refactoring.
This commit is contained in:
parent
82a58ee499
commit
a6045c9985
@ -20,16 +20,6 @@
|
||||
// is used in unit tests.
|
||||
#define DEBUG_PRINT_LAYOUT
|
||||
|
||||
/* Declarations of private classes */
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlKeyboardManagerData,
|
||||
fl_keyboard_manager_data,
|
||||
FL,
|
||||
KEYBOARD_MANAGER_DATA,
|
||||
GObject);
|
||||
|
||||
/* End declarations */
|
||||
|
||||
namespace {
|
||||
|
||||
static bool is_eascii(uint16_t character) {
|
||||
@ -63,55 +53,6 @@ void debug_format_layout_data(std::string& debug_layout_data,
|
||||
|
||||
} // namespace
|
||||
|
||||
/* Define FlKeyboardManagerData */
|
||||
|
||||
/**
|
||||
* FlKeyboardManagerData:
|
||||
* The user_data used when #FlKeyboardManager sends event to
|
||||
* responders.
|
||||
*/
|
||||
|
||||
struct _FlKeyboardManagerData {
|
||||
GObject parent_instance;
|
||||
|
||||
// The owner manager.
|
||||
GWeakRef manager;
|
||||
|
||||
FlKeyboardPendingEvent* pending;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlKeyboardManagerData, fl_keyboard_manager_data, G_TYPE_OBJECT)
|
||||
|
||||
static void fl_keyboard_manager_data_dispose(GObject* object) {
|
||||
g_return_if_fail(FL_IS_KEYBOARD_MANAGER_DATA(object));
|
||||
FlKeyboardManagerData* self = FL_KEYBOARD_MANAGER_DATA(object);
|
||||
|
||||
g_weak_ref_clear(&self->manager);
|
||||
|
||||
G_OBJECT_CLASS(fl_keyboard_manager_data_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void fl_keyboard_manager_data_class_init(
|
||||
FlKeyboardManagerDataClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = fl_keyboard_manager_data_dispose;
|
||||
}
|
||||
|
||||
static void fl_keyboard_manager_data_init(FlKeyboardManagerData* self) {}
|
||||
|
||||
// Creates a new FlKeyboardManagerData private class with all information.
|
||||
static FlKeyboardManagerData* fl_keyboard_manager_data_new(
|
||||
FlKeyboardManager* manager,
|
||||
FlKeyboardPendingEvent* pending) {
|
||||
FlKeyboardManagerData* self = FL_KEYBOARD_MANAGER_DATA(
|
||||
g_object_new(fl_keyboard_manager_data_get_type(), nullptr));
|
||||
|
||||
g_weak_ref_init(&self->manager, manager);
|
||||
self->pending = FL_KEYBOARD_PENDING_EVENT(g_object_ref(pending));
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Define FlKeyboardManager */
|
||||
|
||||
struct _FlKeyboardManager {
|
||||
GObject parent_instance;
|
||||
|
||||
@ -211,25 +152,6 @@ static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b) {
|
||||
return fl_keyboard_pending_event_get_hash(pending) == hash;
|
||||
}
|
||||
|
||||
// Try to remove a pending event from `pending_redispatches` with the target
|
||||
// hash.
|
||||
//
|
||||
// Returns true if the event is found and removed.
|
||||
static bool fl_keyboard_manager_remove_redispatched(FlKeyboardManager* self,
|
||||
uint64_t hash) {
|
||||
guint result_index;
|
||||
gboolean found = g_ptr_array_find_with_equal_func1(
|
||||
self->pending_redispatches, static_cast<const uint64_t*>(&hash),
|
||||
compare_pending_by_hash, &result_index);
|
||||
if (found) {
|
||||
// The removed object is freed due to `pending_redispatches`'s free_func.
|
||||
g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// The callback used by a responder after the event was dispatched.
|
||||
static void responder_handle_event_callback(FlKeyboardManager* self,
|
||||
FlKeyboardPendingEvent* pending) {
|
||||
@ -262,25 +184,33 @@ static void responder_handle_event_callback(FlKeyboardManager* self,
|
||||
}
|
||||
}
|
||||
|
||||
static void complete_handle_event(FlKeyboardManager* self, GTask* task) {
|
||||
FlKeyboardPendingEvent* pending =
|
||||
FL_KEYBOARD_PENDING_EVENT(g_task_get_task_data(task));
|
||||
|
||||
if (fl_keyboard_pending_event_is_complete(pending)) {
|
||||
g_task_return_boolean(task, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void responder_handle_embedder_event_callback(bool handled,
|
||||
gpointer user_data) {
|
||||
g_autoptr(FlKeyboardManagerData) data = FL_KEYBOARD_MANAGER_DATA(user_data);
|
||||
g_autoptr(GTask) task = G_TASK(user_data);
|
||||
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
|
||||
|
||||
fl_keyboard_pending_event_mark_embedder_replied(data->pending, handled);
|
||||
FlKeyboardPendingEvent* pending =
|
||||
FL_KEYBOARD_PENDING_EVENT(g_task_get_task_data(task));
|
||||
fl_keyboard_pending_event_mark_embedder_replied(pending, handled);
|
||||
responder_handle_event_callback(self, pending);
|
||||
|
||||
g_autoptr(FlKeyboardManager) self =
|
||||
FL_KEYBOARD_MANAGER(g_weak_ref_get(&data->manager));
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
responder_handle_event_callback(self, data->pending);
|
||||
complete_handle_event(self, task);
|
||||
}
|
||||
|
||||
static void responder_handle_channel_event_cb(GObject* object,
|
||||
GAsyncResult* result,
|
||||
gpointer user_data) {
|
||||
g_autoptr(FlKeyboardManagerData) data = FL_KEYBOARD_MANAGER_DATA(user_data);
|
||||
g_autoptr(GTask) task = G_TASK(user_data);
|
||||
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
|
||||
|
||||
g_autoptr(GError) error = nullptr;
|
||||
gboolean handled;
|
||||
@ -289,18 +219,15 @@ static void responder_handle_channel_event_cb(GObject* object,
|
||||
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
g_warning("Failed to handle key event in platform: %s", error->message);
|
||||
}
|
||||
return;
|
||||
handled = FALSE;
|
||||
}
|
||||
|
||||
g_autoptr(FlKeyboardManager) self =
|
||||
FL_KEYBOARD_MANAGER(g_weak_ref_get(&data->manager));
|
||||
if (self == nullptr) {
|
||||
return;
|
||||
}
|
||||
FlKeyboardPendingEvent* pending =
|
||||
FL_KEYBOARD_PENDING_EVENT(g_task_get_task_data(task));
|
||||
fl_keyboard_pending_event_mark_channel_replied(pending, handled);
|
||||
responder_handle_event_callback(self, pending);
|
||||
|
||||
fl_keyboard_pending_event_mark_channel_replied(data->pending, handled);
|
||||
|
||||
responder_handle_event_callback(self, data->pending);
|
||||
complete_handle_event(self, task);
|
||||
}
|
||||
|
||||
static uint16_t convert_key_to_char(FlKeyboardManager* self,
|
||||
@ -519,34 +446,58 @@ FlKeyboardManager* fl_keyboard_manager_new(
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager* self,
|
||||
FlKeyEvent* event) {
|
||||
gboolean fl_keyboard_manager_is_redispatched(FlKeyboardManager* self,
|
||||
FlKeyEvent* event) {
|
||||
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
|
||||
g_return_val_if_fail(event != nullptr, FALSE);
|
||||
|
||||
uint64_t hash = fl_key_event_hash(event);
|
||||
|
||||
guint result_index;
|
||||
gboolean found = g_ptr_array_find_with_equal_func1(
|
||||
self->pending_redispatches, static_cast<const uint64_t*>(&hash),
|
||||
compare_pending_by_hash, &result_index);
|
||||
if (found) {
|
||||
// The removed object is freed due to `pending_redispatches`'s free_func.
|
||||
g_ptr_array_remove_index_fast(self->pending_redispatches, result_index);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void fl_keyboard_manager_handle_event(FlKeyboardManager* self,
|
||||
FlKeyEvent* event,
|
||||
GCancellable* cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data) {
|
||||
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
|
||||
g_return_if_fail(event != nullptr);
|
||||
|
||||
g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data);
|
||||
|
||||
guarantee_layout(self, event);
|
||||
|
||||
uint64_t incoming_hash = fl_key_event_hash(event);
|
||||
if (fl_keyboard_manager_remove_redispatched(self, incoming_hash)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(event);
|
||||
|
||||
g_ptr_array_add(self->pending_responds, pending);
|
||||
g_autoptr(FlKeyboardManagerData) data =
|
||||
fl_keyboard_manager_data_new(self, pending);
|
||||
g_task_set_task_data(task, g_object_ref(pending), g_object_unref);
|
||||
|
||||
uint64_t specified_logical_key = fl_keyboard_layout_get_logical_key(
|
||||
self->derived_layout, fl_key_event_get_group(event),
|
||||
fl_key_event_get_keycode(event));
|
||||
fl_key_embedder_responder_handle_event(
|
||||
self->key_embedder_responder, event, specified_logical_key,
|
||||
responder_handle_embedder_event_callback, g_object_ref(data));
|
||||
responder_handle_embedder_event_callback, g_object_ref(task));
|
||||
fl_key_channel_responder_handle_event(
|
||||
self->key_channel_responder, event, specified_logical_key,
|
||||
self->cancellable, responder_handle_channel_event_cb, g_object_ref(data));
|
||||
self->cancellable, responder_handle_channel_event_cb, g_object_ref(task));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
gboolean fl_keyboard_manager_handle_event_finish(FlKeyboardManager* self,
|
||||
GAsyncResult* result,
|
||||
GError** error) {
|
||||
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), FALSE);
|
||||
g_return_val_if_fail(g_task_is_valid(result, self), FALSE);
|
||||
return g_task_propagate_boolean(G_TASK(result), error);
|
||||
}
|
||||
|
||||
gboolean fl_keyboard_manager_is_state_clear(FlKeyboardManager* self) {
|
||||
|
@ -48,18 +48,52 @@ 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);
|
||||
|
||||
/**
|
||||
* fl_keyboard_manager_handle_event:
|
||||
* @manager: the #FlKeyboardManager self.
|
||||
* @manager: an #FlKeyboardManager.
|
||||
* @event: the event to be dispatched. It is usually a wrap of a GdkEventKey.
|
||||
* This event will be managed and released by #FlKeyboardManager.
|
||||
* @cancellable: (allow-none): a #GCancellable or %NULL.
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the view is
|
||||
* added.
|
||||
* @user_data: (closure): user data to pass to @callback.
|
||||
*
|
||||
* Make the manager process a system key event. This might eventually send
|
||||
* messages to the framework, trigger text input effects, or redispatch the
|
||||
* event back to the system.
|
||||
*/
|
||||
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager* manager,
|
||||
FlKeyEvent* event);
|
||||
void fl_keyboard_manager_handle_event(FlKeyboardManager* manager,
|
||||
FlKeyEvent* event,
|
||||
GCancellable* cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* fl_keyboard_manager_handle_event_finish:
|
||||
* @manager: an #FlKeyboardManager.
|
||||
* @result: a #GAsyncResult.
|
||||
* @error: (allow-none): #GError location to store the error occurring, or %NULL
|
||||
* to ignore.
|
||||
*
|
||||
* Completes request started with fl_keyboard_manager_handle_event().
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
*/
|
||||
gboolean fl_keyboard_manager_handle_event_finish(FlKeyboardManager* manager,
|
||||
GAsyncResult* result,
|
||||
GError** error);
|
||||
|
||||
/**
|
||||
* fl_keyboard_manager_is_state_clear:
|
||||
|
@ -198,7 +198,7 @@ int redispatch_events_and_clear(FlKeyboardManager* manager, GPtrArray* events) {
|
||||
guint event_count = events->len;
|
||||
for (guint event_id = 0; event_id < event_count; event_id += 1) {
|
||||
FlKeyEvent* event = FL_KEY_EVENT(g_ptr_array_index(events, event_id));
|
||||
EXPECT_FALSE(fl_keyboard_manager_handle_event(manager, event));
|
||||
EXPECT_TRUE(fl_keyboard_manager_is_redispatched(manager, event));
|
||||
}
|
||||
g_ptr_array_set_size(events, 0);
|
||||
return event_count;
|
||||
@ -227,7 +227,7 @@ TEST(FlKeyboardManagerTest, DisposeWithUnresolvedPends) {
|
||||
nullptr);
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
fl_keyboard_manager_handle_event(manager, event1);
|
||||
fl_keyboard_manager_handle_event(manager, event1, nullptr, nullptr, nullptr);
|
||||
|
||||
// Handle second event.
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
@ -238,7 +238,7 @@ TEST(FlKeyboardManagerTest, DisposeWithUnresolvedPends) {
|
||||
nullptr);
|
||||
g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
|
||||
0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
fl_keyboard_manager_handle_event(manager, event2);
|
||||
fl_keyboard_manager_handle_event(manager, event2, nullptr, nullptr, nullptr);
|
||||
|
||||
// Passes if the cleanup does not crash.
|
||||
}
|
||||
@ -293,7 +293,13 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
|
||||
// Dispatch a key event
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event1));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event1, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
EXPECT_EQ(redispatched->len, 0u);
|
||||
EXPECT_EQ(call_records->len, 1u);
|
||||
@ -311,7 +317,13 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
|
||||
/// Test 2: Two events that are unhandled by the framework
|
||||
g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
|
||||
0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event2));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event2, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
EXPECT_EQ(redispatched->len, 0u);
|
||||
EXPECT_EQ(call_records->len, 1u);
|
||||
@ -322,7 +334,13 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
|
||||
// Dispatch another key event
|
||||
g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyB, GDK_KEY_b, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event3));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event3, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
EXPECT_EQ(redispatched->len, 0u);
|
||||
EXPECT_EQ(call_records->len, 2u);
|
||||
@ -358,7 +376,13 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
|
||||
/// redispatching only works once.
|
||||
g_autoptr(FlKeyEvent) event4 = fl_key_event_new(
|
||||
0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event4));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event4, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
EXPECT_EQ(redispatched->len, 0u);
|
||||
EXPECT_EQ(call_records->len, 1u);
|
||||
@ -419,7 +443,13 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithSyncResponds) {
|
||||
// Dispatch a key event
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event1));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event1, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
EXPECT_EQ(call_records->len, 1u);
|
||||
EXPECT_KEY_EVENT(static_cast<CallRecord*>(g_ptr_array_index(call_records, 0)),
|
||||
@ -444,7 +474,13 @@ TEST(FlKeyboardManagerTest, SingleDelegateWithSyncResponds) {
|
||||
call_records);
|
||||
g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
|
||||
0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event2));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event2, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
EXPECT_EQ(call_records->len, 1u);
|
||||
EXPECT_KEY_EVENT(static_cast<CallRecord*>(g_ptr_array_index(call_records, 0)),
|
||||
@ -521,7 +557,13 @@ TEST(FlKeyboardManagerTest, WithTwoAsyncDelegates) {
|
||||
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event1));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event1, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(redispatched->len, 0u);
|
||||
EXPECT_EQ(embedder_call_records->len, 1u);
|
||||
@ -543,7 +585,13 @@ TEST(FlKeyboardManagerTest, WithTwoAsyncDelegates) {
|
||||
/// Test 2: All delegates respond false
|
||||
g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
|
||||
0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event2));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event2, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(redispatched->len, 0u);
|
||||
EXPECT_EQ(embedder_call_records->len, 1u);
|
||||
@ -608,7 +656,13 @@ TEST(FlKeyboardManagerTest, TextInputHandlerReturnsFalse) {
|
||||
nullptr);
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
// The event was redispatched because no one handles it.
|
||||
EXPECT_TRUE(redispatched);
|
||||
@ -653,7 +707,13 @@ TEST(FlKeyboardManagerTest, TextInputHandlerReturnsTrue) {
|
||||
nullptr);
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event(manager, event));
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
flush_channel_messages();
|
||||
// The event was not redispatched because handler handles it.
|
||||
EXPECT_FALSE(redispatched);
|
||||
@ -686,10 +746,12 @@ TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
|
||||
auto sendTap = [&](guint8 keycode, guint keyval, guint8 group) {
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
0, TRUE, keycode, keyval, static_cast<GdkModifierType>(0), group);
|
||||
fl_keyboard_manager_handle_event(manager, event1);
|
||||
fl_keyboard_manager_handle_event(manager, event1, nullptr, nullptr,
|
||||
nullptr);
|
||||
g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
|
||||
0, FALSE, keycode, keyval, static_cast<GdkModifierType>(0), group);
|
||||
fl_keyboard_manager_handle_event(manager, event2);
|
||||
fl_keyboard_manager_handle_event(manager, event2, nullptr, nullptr,
|
||||
nullptr);
|
||||
};
|
||||
|
||||
/* US keyboard layout */
|
||||
@ -862,7 +924,13 @@ TEST(FlKeyboardManagerTest, GetPressedState) {
|
||||
// Dispatch a key event.
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
fl_keyboard_manager_handle_event(manager, event);
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, nullptr));
|
||||
},
|
||||
nullptr);
|
||||
|
||||
GHashTable* pressedState = fl_keyboard_manager_get_pressed_state(manager);
|
||||
EXPECT_EQ(g_hash_table_size(pressedState), 1u);
|
||||
|
@ -673,25 +673,42 @@ static void fl_view_realize(GtkWidget* widget) {
|
||||
gtk_widget_realize(GTK_WIDGET(self->gl_area));
|
||||
}
|
||||
|
||||
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)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fl_keyboard_manager_handle_event(
|
||||
self->keyboard_manager, event, self->cancellable,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, &error)) {
|
||||
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
g_warning("Failed to handle key event: %s", error->message);
|
||||
}
|
||||
}
|
||||
},
|
||||
nullptr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Implements GtkWidget::key_press_event.
|
||||
static gboolean fl_view_key_press_event(GtkWidget* widget,
|
||||
GdkEventKey* key_event) {
|
||||
FlView* self = FL_VIEW(widget);
|
||||
|
||||
GdkEvent* event = reinterpret_cast<GdkEvent*>(key_event);
|
||||
return fl_keyboard_manager_handle_event(
|
||||
self->keyboard_manager,
|
||||
fl_key_event_new_from_gdk_event(gdk_event_copy(event)));
|
||||
return handle_key_event(self, key_event);
|
||||
}
|
||||
|
||||
// Implements GtkWidget::key_release_event.
|
||||
static gboolean fl_view_key_release_event(GtkWidget* widget,
|
||||
GdkEventKey* key_event) {
|
||||
FlView* self = FL_VIEW(widget);
|
||||
GdkEvent* event = reinterpret_cast<GdkEvent*>(key_event);
|
||||
return fl_keyboard_manager_handle_event(
|
||||
self->keyboard_manager,
|
||||
fl_key_event_new_from_gdk_event(gdk_event_copy(event)));
|
||||
return handle_key_event(self, key_event);
|
||||
}
|
||||
|
||||
static void fl_view_class_init(FlViewClass* klass) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user