Refactor FlKeyboardHandler (#55601)
Refactor FlKeyboardHandler to be more GObject and less C++.
Done as we will need to move the handler from FlView to FlEngine to
support multi-view.
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 9be3b1f..b7119de 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -44809,6 +44809,8 @@
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_handler.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_handler.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_handler_test.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.h + ../../../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
@@ -47715,6 +47717,8 @@
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_handler.cc
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_handler.h
FILE: ../../../flutter/shell/platform/linux/fl_keyboard_handler_test.cc
+FILE: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.cc
+FILE: ../../../flutter/shell/platform/linux/fl_keyboard_pending_event.h
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
diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn
index 13511e9..36045a9 100644
--- a/shell/platform/linux/BUILD.gn
+++ b/shell/platform/linux/BUILD.gn
@@ -81,6 +81,7 @@
"fl_dart_project_private.h",
"fl_engine_private.h",
"fl_keyboard_handler.h",
+ "fl_keyboard_pending_event.h",
"fl_keyboard_view_delegate.h",
"fl_key_event.h",
"fl_key_responder.h",
@@ -116,6 +117,7 @@
"fl_key_event.cc",
"fl_key_responder.cc",
"fl_keyboard_handler.cc",
+ "fl_keyboard_pending_event.cc",
"fl_keyboard_view_delegate.cc",
"fl_message_codec.cc",
"fl_method_call.cc",
diff --git a/shell/platform/linux/fl_key_channel_responder.cc b/shell/platform/linux/fl_key_channel_responder.cc
index c79ac94..8c6e28b 100644
--- a/shell/platform/linux/fl_key_channel_responder.cc
+++ b/shell/platform/linux/fl_key_channel_responder.cc
@@ -212,9 +212,11 @@
g_return_if_fail(event != nullptr);
g_return_if_fail(callback != nullptr);
- const gchar* type = event->is_press ? kTypeValueDown : kTypeValueUp;
- int64_t scan_code = event->keycode;
- int64_t unicode_scarlar_values = gdk_keyval_to_unicode(event->keyval);
+ const gchar* type =
+ fl_key_event_get_is_press(event) ? kTypeValueDown : kTypeValueUp;
+ int64_t scan_code = fl_key_event_get_keycode(event);
+ int64_t unicode_scarlar_values =
+ gdk_keyval_to_unicode(fl_key_event_get_keyval(event));
// For most modifier keys, GTK keeps track of the "pressed" state of the
// modifier keys. Flutter uses this information to keep modifier keys from
@@ -239,20 +241,21 @@
// interactions (for example, if shift-lock is on, tab traversal is broken).
// Remove lock states from state mask.
- guint state = event->state & ~(GDK_LOCK_MASK | GDK_MOD2_MASK);
+ guint state =
+ fl_key_event_get_state(event) & ~(GDK_LOCK_MASK | GDK_MOD2_MASK);
static bool shift_lock_pressed = FALSE;
static bool caps_lock_pressed = FALSE;
static bool num_lock_pressed = FALSE;
- switch (event->keyval) {
+ switch (fl_key_event_get_keyval(event)) {
case GDK_KEY_Num_Lock:
- num_lock_pressed = event->is_press;
+ num_lock_pressed = fl_key_event_get_is_press(event);
break;
case GDK_KEY_Caps_Lock:
- caps_lock_pressed = event->is_press;
+ caps_lock_pressed = fl_key_event_get_is_press(event);
break;
case GDK_KEY_Shift_Lock:
- shift_lock_pressed = event->is_press;
+ shift_lock_pressed = fl_key_event_get_is_press(event);
break;
}
@@ -269,7 +272,7 @@
fl_value_set_string_take(message, kToolkitKey,
fl_value_new_string(kGtkToolkit));
fl_value_set_string_take(message, kKeyCodeKey,
- fl_value_new_int(event->keyval));
+ fl_value_new_int(fl_key_event_get_keyval(event)));
fl_value_set_string_take(message, kModifiersKey, fl_value_new_int(state));
if (unicode_scarlar_values != 0) {
fl_value_set_string_take(message, kUnicodeScalarValuesKey,
diff --git a/shell/platform/linux/fl_key_channel_responder_test.cc b/shell/platform/linux/fl_key_channel_responder_test.cc
index 4972f59..2d38456 100644
--- a/shell/platform/linux/fl_key_channel_responder_test.cc
+++ b/shell/platform/linux/fl_key_channel_responder_test.cc
@@ -29,33 +29,6 @@
g_main_loop_quit(static_cast<GMainLoop*>(user_data));
}
-namespace {
-// A global variable to store new event. It is a global variable so that it can
-// be returned by #fl_key_event_new_by_mock for easy use.
-FlKeyEvent _g_key_event;
-} // namespace
-
-// Create a new #FlKeyEvent with the given information.
-//
-// This event is passed to #fl_key_responder_handle_event,
-// which assumes that the event is managed by callee.
-// Therefore #fl_key_event_new_by_mock doesn't need to
-// dynamically allocate, but reuses the same global object.
-static FlKeyEvent* fl_key_event_new_by_mock(guint32 time_in_milliseconds,
- bool is_press,
- guint keyval,
- guint16 keycode,
- GdkModifierType state,
- gboolean is_modifier) {
- _g_key_event.is_press = is_press;
- _g_key_event.time = time_in_milliseconds;
- _g_key_event.state = state;
- _g_key_event.keyval = keyval;
- _g_key_event.keycode = keycode;
- _g_key_event.origin = nullptr;
- return &_g_key_event;
-}
-
// Test sending a letter "A";
TEST(FlKeyChannelResponderTest, SendKeyEvent) {
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
@@ -69,11 +42,9 @@
g_autoptr(FlKeyResponder) responder =
FL_KEY_RESPONDER(fl_key_channel_responder_new(messenger, &mock));
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12345, true, GDK_KEY_A, 0x04,
- static_cast<GdkModifierType>(0), false),
- responder_callback, loop);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 12345, TRUE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, responder_callback, loop);
expected_value =
"{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, keyCode: 65, "
"modifiers: 0, unicodeScalarValues: 65}";
@@ -82,11 +53,9 @@
// Blocks here until echo_response_cb is called.
g_main_loop_run(loop);
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(23456, false, GDK_KEY_A, 0x04,
- static_cast<GdkModifierType>(0), false),
- responder_callback, loop);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 23456, FALSE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event2, responder_callback, loop);
expected_value =
"{type: keyup, keymap: linux, scanCode: 4, toolkit: gtk, keyCode: 65, "
"modifiers: 0, unicodeScalarValues: 65}";
@@ -110,11 +79,9 @@
g_autoptr(FlKeyResponder) responder =
FL_KEY_RESPONDER(fl_key_channel_responder_new(messenger, &mock));
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12345, true, key_code, 0x04,
- static_cast<GdkModifierType>(0), false),
- responder_callback, loop);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 12345, TRUE, 0x04, key_code, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, responder_callback, loop);
expected_value = down_expected;
expected_handled = FALSE;
@@ -123,11 +90,9 @@
expected_value = up_expected;
expected_handled = FALSE;
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12346, false, key_code, 0x04,
- static_cast<GdkModifierType>(0), false),
- responder_callback, loop);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 12346, FALSE, 0x04, key_code, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event2, responder_callback, loop);
// Blocks here until echo_response_cb is called.
g_main_loop_run(loop);
@@ -172,11 +137,9 @@
g_autoptr(FlKeyResponder) responder =
FL_KEY_RESPONDER(fl_key_channel_responder_new(messenger, &mock));
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12345, true, GDK_KEY_A, 0x04,
- static_cast<GdkModifierType>(0), false),
- responder_callback, loop);
+ g_autoptr(FlKeyEvent) event = fl_key_event_new(
+ 12345, TRUE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event, responder_callback, loop);
expected_handled = TRUE;
expected_value =
"{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
@@ -198,11 +161,10 @@
g_autoptr(FlKeyResponder) responder =
FL_KEY_RESPONDER(fl_key_channel_responder_new(messenger, &mock));
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12345, true, GDK_KEY_A, 0x04,
- static_cast<GdkModifierType>(0), false),
- responder_callback, loop, 888);
+ g_autoptr(FlKeyEvent) event = fl_key_event_new(
+ 12345, TRUE, 0x04, GDK_KEY_A, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event, responder_callback, loop,
+ 888);
expected_handled = TRUE;
expected_value =
"{type: keydown, keymap: linux, scanCode: 4, toolkit: gtk, "
diff --git a/shell/platform/linux/fl_key_embedder_responder.cc b/shell/platform/linux/fl_key_embedder_responder.cc
index 100d618..922922a 100644
--- a/shell/platform/linux/fl_key_embedder_responder.cc
+++ b/shell/platform/linux/fl_key_embedder_responder.cc
@@ -297,16 +297,16 @@
return (logical_id & kValueMask) | plane;
}
-static uint64_t event_to_physical_key(const FlKeyEvent* event) {
- auto found = xkb_to_physical_key_map.find(event->keycode);
+static uint64_t event_to_physical_key(FlKeyEvent* event) {
+ auto found = xkb_to_physical_key_map.find(fl_key_event_get_keycode(event));
if (found != xkb_to_physical_key_map.end()) {
return found->second;
}
- return apply_id_plane(event->keycode, kGtkPlane);
+ return apply_id_plane(fl_key_event_get_keycode(event), kGtkPlane);
}
-static uint64_t event_to_logical_key(const FlKeyEvent* event) {
- guint keyval = event->keyval;
+static uint64_t event_to_logical_key(FlKeyEvent* event) {
+ guint keyval = fl_key_event_get_keyval(event);
auto found = gtk_keyval_to_logical_key_map.find(keyval);
if (found != gtk_keyval_to_logical_key_map.end()) {
return found->second;
@@ -319,14 +319,15 @@
return apply_id_plane(keyval, kGtkPlane);
}
-static uint64_t event_to_timestamp(const FlKeyEvent* event) {
- return kMicrosecondsPerMillisecond * static_cast<double>(event->time);
+static uint64_t event_to_timestamp(FlKeyEvent* event) {
+ return kMicrosecondsPerMillisecond *
+ static_cast<double>(fl_key_event_get_time(event));
}
-// Returns a newly accocated UTF-8 string from event->keyval that must be
-// freed later with g_free().
-static char* event_to_character(const FlKeyEvent* event) {
- gunichar unicodeChar = gdk_keyval_to_unicode(event->keyval);
+// Returns a newly accocated UTF-8 string from fl_key_event_get_keyval(event)
+// that must be freed later with g_free().
+static char* event_to_character(FlKeyEvent* event) {
+ gunichar unicodeChar = gdk_keyval_to_unicode(fl_key_event_get_keyval(event));
glong items_written;
gchar* result = g_ucs4_to_utf8(&unicodeChar, 1, NULL, &items_written, NULL);
if (items_written == 0) {
@@ -790,11 +791,11 @@
const uint64_t physical_key = corrected_modifier_physical_key(
self->modifier_bit_to_checked_keys, physical_key_from_event, logical_key);
const double timestamp = event_to_timestamp(event);
- const bool is_down_event = event->is_press;
+ const bool is_down_event = fl_key_event_get_is_press(event);
SyncStateLoopContext sync_state_context;
sync_state_context.self = self;
- sync_state_context.state = event->state;
+ sync_state_context.state = fl_key_event_get_state(event);
sync_state_context.timestamp = timestamp;
sync_state_context.is_down = is_down_event;
sync_state_context.event_logical_key = logical_key;
diff --git a/shell/platform/linux/fl_key_embedder_responder_test.cc b/shell/platform/linux/fl_key_embedder_responder_test.cc
index aac675d..3a1ab31 100644
--- a/shell/platform/linux/fl_key_embedder_responder_test.cc
+++ b/shell/platform/linux/fl_key_embedder_responder_test.cc
@@ -16,9 +16,6 @@
constexpr gboolean kRelease = FALSE;
constexpr gboolean kPress = TRUE;
-constexpr gboolean kIsModifier = TRUE;
-constexpr gboolean kIsNotModifier = FALSE;
-
constexpr guint16 kKeyCodeDigit1 = 0x0au;
constexpr guint16 kKeyCodeKeyA = 0x26u;
constexpr guint16 kKeyCodeShiftLeft = 0x32u;
@@ -100,33 +97,6 @@
return self;
}
-namespace {
-// A global variable to store new event. It is a global variable so that it can
-// be returned by #fl_key_event_new_by_mock for easy use.
-FlKeyEvent _g_key_event;
-} // namespace
-
-// Create a new #FlKeyEvent with the given information.
-//
-// This event is passed to #fl_key_responder_handle_event,
-// which assumes that the event is managed by callee.
-// Therefore #fl_key_event_new_by_mock doesn't need to
-// dynamically allocate, but reuses the same global object.
-static FlKeyEvent* fl_key_event_new_by_mock(guint32 time_in_milliseconds,
- bool is_press,
- guint keyval,
- guint16 keycode,
- GdkModifierType state,
- gboolean is_modifier) {
- _g_key_event.is_press = is_press;
- _g_key_event.time = time_in_milliseconds;
- _g_key_event.state = state;
- _g_key_event.keyval = keyval;
- _g_key_event.keycode = keycode;
- _g_key_event.origin = nullptr;
- return &_g_key_event;
-}
-
static gboolean g_expected_handled;
static gpointer g_expected_user_data;
@@ -176,11 +146,11 @@
// On a QWERTY keyboard, press key Q (physically key A), and release.
// Key down
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12345, kPress, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 =
+ fl_key_event_new(12345, kPress, kKeyCodeKeyA, GDK_KEY_a,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -196,11 +166,11 @@
g_ptr_array_clear(g_call_records);
// Key up
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12346, kRelease, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(12346, kRelease, kKeyCodeKeyA, GDK_KEY_a,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -217,11 +187,11 @@
// On an AZERTY keyboard, press key Q (physically key A), and release.
// Key down
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12347, kPress, GDK_KEY_q, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 =
+ fl_key_event_new(12347, kPress, kKeyCodeKeyA, GDK_KEY_q,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -237,11 +207,11 @@
g_ptr_array_clear(g_call_records);
// Key up
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12348, kRelease, GDK_KEY_q, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 =
+ fl_key_event_new(12348, kRelease, kKeyCodeKeyA, GDK_KEY_q,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -272,11 +242,11 @@
// On an AZERTY keyboard, press physical key 1, and release.
// Key down
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(12345, kPress, GDK_KEY_ampersand, kKeyCodeDigit1,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data, kLogicalDigit1);
+ g_autoptr(FlKeyEvent) event =
+ fl_key_event_new(12345, kPress, kKeyCodeDigit1, GDK_KEY_ampersand,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event, verify_response_handled,
+ &user_data, kLogicalDigit1);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -306,11 +276,11 @@
FlKeyEmbedderCallRecord* record;
// Press shift right
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_Shift_R, kKeyCodeShiftRight,
- static_cast<GdkModifierType>(0), kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 =
+ fl_key_event_new(101, kPress, kKeyCodeShiftRight, GDK_KEY_Shift_R,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -324,11 +294,10 @@
g_ptr_array_clear(g_call_records);
// Press key A
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA,
- GDK_SHIFT_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_SHIFT_MASK, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -342,11 +311,10 @@
g_ptr_array_clear(g_call_records);
// Release shift right
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Shift_R,
- kKeyCodeShiftRight, GDK_SHIFT_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 103, kRelease, kKeyCodeShiftRight, GDK_KEY_Shift_R, GDK_SHIFT_MASK, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -360,11 +328,11 @@
g_ptr_array_clear(g_call_records);
// Release key A
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_A, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 =
+ fl_key_event_new(104, kRelease, kKeyCodeKeyA, GDK_KEY_A,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -399,11 +367,11 @@
FlKeyEmbedderCallRecord* record;
// Press Numpad 1 (stage 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_KP_End, kKeyCodeNumpad1,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 =
+ fl_key_event_new(101, kPress, kKeyCodeNumpad1, GDK_KEY_KP_End,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -417,11 +385,11 @@
g_ptr_array_clear(g_call_records);
// Press NumLock (stage 0 -> 1)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kPress, kKeyCodeNumLock, GDK_KEY_Num_Lock,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -435,11 +403,10 @@
g_ptr_array_clear(g_call_records);
// Release numpad 1 (stage 1)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_KP_1, kKeyCodeNumpad1,
- GDK_MOD2_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 104, kRelease, kKeyCodeNumpad1, GDK_KEY_KP_1, GDK_MOD2_MASK, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -453,11 +420,10 @@
g_ptr_array_clear(g_call_records);
// Release NumLock (stage 1 -> 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- GDK_MOD2_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 = fl_key_event_new(
+ 103, kRelease, kKeyCodeNumLock, GDK_KEY_Num_Lock, GDK_MOD2_MASK, 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -471,11 +437,10 @@
g_ptr_array_clear(g_call_records);
// Press Numpad 1 (stage 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_KP_End, kKeyCodeNumpad1,
- GDK_MOD2_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event5 = fl_key_event_new(
+ 101, kPress, kKeyCodeNumpad1, GDK_KEY_KP_End, GDK_MOD2_MASK, 0);
+ fl_key_responder_handle_event(responder, event5, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -489,11 +454,10 @@
g_ptr_array_clear(g_call_records);
// Press NumLock (stage 2 -> 3)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- GDK_MOD2_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event6 = fl_key_event_new(
+ 102, kPress, kKeyCodeNumLock, GDK_KEY_Num_Lock, GDK_MOD2_MASK, 0);
+ fl_key_responder_handle_event(responder, event6, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -507,11 +471,10 @@
g_ptr_array_clear(g_call_records);
// Release numpad 1 (stage 3)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_KP_1, kKeyCodeNumpad1,
- GDK_MOD2_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event7 = fl_key_event_new(
+ 104, kRelease, kKeyCodeNumpad1, GDK_KEY_KP_1, GDK_MOD2_MASK, 0);
+ fl_key_responder_handle_event(responder, event7, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -525,11 +488,10 @@
g_ptr_array_clear(g_call_records);
// Release NumLock (stage 3 -> 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- GDK_MOD2_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event8 = fl_key_event_new(
+ 103, kRelease, kKeyCodeNumLock, GDK_KEY_Num_Lock, GDK_MOD2_MASK, 0);
+ fl_key_responder_handle_event(responder, event8, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -562,11 +524,10 @@
GdkModifierType state = static_cast<GdkModifierType>(0);
// Press shift left
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_Shift_L, kKeyCodeShiftLeft,
- state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 101, kPress, kKeyCodeShiftLeft, GDK_KEY_Shift_L, state, 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -582,11 +543,10 @@
state = GDK_SHIFT_MASK;
// Press digit 1, which is '!' on a US keyboard
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_exclam, kKeyCodeDigit1,
- state, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kPress, kKeyCodeDigit1, GDK_KEY_exclam, state, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -600,11 +560,10 @@
g_ptr_array_clear(g_call_records);
// Release shift
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Shift_L,
- kKeyCodeShiftLeft, state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 103, kRelease, kKeyCodeShiftLeft, GDK_KEY_Shift_L, state, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -620,11 +579,10 @@
state = static_cast<GdkModifierType>(0);
// Release digit 1, which is "1" because shift has been released.
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_1, kKeyCodeDigit1, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 =
+ fl_key_event_new(104, kRelease, kKeyCodeDigit1, GDK_KEY_1, state, 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -655,11 +613,11 @@
FlKeyEmbedderCallRecord* record;
// Press CapsLock (stage 0 -> 1)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
- static_cast<GdkModifierType>(0), kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 =
+ fl_key_event_new(101, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -673,11 +631,10 @@
g_ptr_array_clear(g_call_records);
// Press key A (stage 1)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA,
- GDK_LOCK_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -691,11 +648,10 @@
g_ptr_array_clear(g_call_records);
// Release CapsLock (stage 1 -> 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Caps_Lock,
- kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 103, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -709,11 +665,10 @@
g_ptr_array_clear(g_call_records);
// Release key A (stage 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_A, kKeyCodeKeyA,
- GDK_LOCK_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 = fl_key_event_new(104, kRelease, kKeyCodeKeyA,
+ GDK_KEY_A, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -727,11 +682,10 @@
g_ptr_array_clear(g_call_records);
// Press CapsLock (stage 2 -> 3)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(105, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
- GDK_LOCK_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event5 = fl_key_event_new(
+ 105, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event5, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -745,11 +699,10 @@
g_ptr_array_clear(g_call_records);
// Press key A (stage 3)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(106, kPress, GDK_KEY_A, kKeyCodeKeyA,
- GDK_LOCK_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event6 =
+ fl_key_event_new(106, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event6, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -763,11 +716,10 @@
g_ptr_array_clear(g_call_records);
// Release CapsLock (stage 3 -> 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(107, kRelease, GDK_KEY_Caps_Lock,
- kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event7 = fl_key_event_new(
+ 107, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event7, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -781,11 +733,11 @@
g_ptr_array_clear(g_call_records);
// Release key A (stage 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(108, kRelease, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event8 =
+ fl_key_event_new(108, kRelease, kKeyCodeKeyA, GDK_KEY_a,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event8, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -816,11 +768,10 @@
FlKeyEmbedderCallRecord* record;
// Press key A (stage 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 101, kPress, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -834,11 +785,10 @@
g_ptr_array_clear(g_call_records);
// Press CapsLock (stage 0 -> 1)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
- GDK_LOCK_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 102, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -852,11 +802,10 @@
g_ptr_array_clear(g_call_records);
// Release CapsLock (stage 1 -> 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Caps_Lock,
- kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 103, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -870,11 +819,10 @@
g_ptr_array_clear(g_call_records);
// Release key A (stage 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_A, kKeyCodeKeyA,
- GDK_LOCK_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 = fl_key_event_new(104, kRelease, kKeyCodeKeyA,
+ GDK_KEY_A, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -888,11 +836,10 @@
g_ptr_array_clear(g_call_records);
// Press key A (stage 2)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(105, kPress, GDK_KEY_A, kKeyCodeKeyA,
- GDK_LOCK_MASK, kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event5 =
+ fl_key_event_new(105, kPress, kKeyCodeKeyA, GDK_KEY_A, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event5, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -906,11 +853,11 @@
g_ptr_array_clear(g_call_records);
// Press CapsLock (stage 2 -> 3)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(106, kPress, GDK_KEY_Caps_Lock, kKeyCodeCapsLock,
- static_cast<GdkModifierType>(0), kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event6 =
+ fl_key_event_new(106, kPress, kKeyCodeCapsLock, GDK_KEY_Caps_Lock,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event6, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -924,11 +871,10 @@
g_ptr_array_clear(g_call_records);
// Release CapsLock (stage 3 -> 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(107, kRelease, GDK_KEY_Caps_Lock,
- kKeyCodeCapsLock, GDK_LOCK_MASK, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event7 = fl_key_event_new(
+ 107, kRelease, kKeyCodeCapsLock, GDK_KEY_Caps_Lock, GDK_LOCK_MASK, 0);
+ fl_key_responder_handle_event(responder, event7, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -942,11 +888,11 @@
g_ptr_array_clear(g_call_records);
// Release key A (stage 0)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(108, kRelease, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event8 =
+ fl_key_event_new(108, kRelease, kKeyCodeKeyA, GDK_KEY_a,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event8, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -973,11 +919,10 @@
FlKeyEmbedderCallRecord* record;
// Press KeyA
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 101, kPress, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
@@ -987,11 +932,10 @@
// Another KeyA down events, which usually means a repeated event.
g_expected_handled = false;
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 102, kPress, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
@@ -1007,11 +951,11 @@
g_ptr_array_clear(g_call_records);
// Release KeyA
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_q, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 =
+ fl_key_event_new(103, kRelease, kKeyCodeKeyA, GDK_KEY_q,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1033,11 +977,11 @@
// Release KeyA before it was even pressed.
g_expected_handled = true; // The empty event is always handled.
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_q, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event =
+ fl_key_event_new(103, kRelease, kKeyCodeKeyA, GDK_KEY_q,
+ static_cast<GdkModifierType>(0), 0);
+ fl_key_responder_handle_event(responder, event, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
@@ -1069,11 +1013,10 @@
GdkModifierType state = GDK_CONTROL_MASK;
// Send a ControlLeft up
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kRelease, GDK_KEY_Control_L,
- kKeyCodeControlLeft, state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 101, kRelease, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 2u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1099,11 +1042,10 @@
// Send a ControlLeft down.
state = static_cast<GdkModifierType>(0);
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_Control_L,
- kKeyCodeControlLeft, state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 102, kPress, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
invoke_record_callback_and_verify(record, TRUE, &user_data);
@@ -1113,11 +1055,10 @@
state = static_cast<GdkModifierType>(0);
// Send another ControlLeft down
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kPress, GDK_KEY_Control_L,
- kKeyCodeControlLeft, state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 103, kPress, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 2u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1141,11 +1082,10 @@
// Send a ControlLeft up to clear up state.
state = GDK_CONTROL_MASK;
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(104, kRelease, GDK_KEY_Control_L,
- kKeyCodeControlLeft, state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 = fl_key_event_new(
+ 104, kRelease, kKeyCodeControlLeft, GDK_KEY_Control_L, state, 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
invoke_record_callback_and_verify(record, TRUE, &user_data);
@@ -1157,11 +1097,10 @@
state = GDK_CONTROL_MASK;
// Send a ControlRight up.
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(105, kRelease, GDK_KEY_Control_R,
- kKeyCodeControlRight, state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event5 = fl_key_event_new(
+ 105, kRelease, kKeyCodeControlRight, GDK_KEY_Control_R, state, 0);
+ fl_key_responder_handle_event(responder, event5, verify_response_handled,
+ &user_data);
// A ControlLeft down is synthesized, with an empty event.
// Reason: The ControlLeft down is synthesized to synchronize the state
@@ -1198,11 +1137,10 @@
GdkModifierType state = GDK_CONTROL_MASK;
// Send a normal event (KeyA down)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 =
+ fl_key_event_new(101, kPress, kKeyCodeKeyA, GDK_KEY_a, state, 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 2u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1228,11 +1166,10 @@
state = static_cast<GdkModifierType>(0);
// Send a normal event (KeyA up)
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kRelease, GDK_KEY_A, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kRelease, kKeyCodeKeyA, GDK_KEY_A, state, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 2u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1259,11 +1196,10 @@
// Press a key with physical CapsLock and logical ControlLeft.
state = static_cast<GdkModifierType>(0);
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_Control_L, kKeyCodeCapsLock,
- state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(101, kPress, kKeyCodeCapsLock,
+ GDK_KEY_Control_L, state, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1281,11 +1217,10 @@
state = static_cast<GdkModifierType>(0);
// Send a normal event (KeyA down).
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event4 =
+ fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, state, 0);
+ fl_key_responder_handle_event(responder, event4, verify_response_handled,
+ &user_data);
// The synthesized event should have physical CapsLock and logical
// ControlLeft.
@@ -1328,11 +1263,10 @@
// Press a key with physical CapsLock and logical ControlLeft.
GdkModifierType state = static_cast<GdkModifierType>(0);
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_Control_L, kKeyCodeCapsLock,
- state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(101, kPress, kKeyCodeCapsLock,
+ GDK_KEY_Control_L, state, 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1350,11 +1284,10 @@
state = static_cast<GdkModifierType>(0);
// Send a normal event (KeyA down).
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_A, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kPress, kKeyCodeKeyA, GDK_KEY_A, state, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
// The synthesized event should have physical CapsLock and logical
// ControlLeft.
@@ -1397,11 +1330,10 @@
GdkModifierType state = GDK_MOD2_MASK;
// Send a normal event
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_a, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 =
+ fl_key_event_new(101, kPress, kKeyCodeKeyA, GDK_KEY_a, state, 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 2u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1427,11 +1359,10 @@
state = static_cast<GdkModifierType>(0);
// Release key A
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kRelease, GDK_KEY_A, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 =
+ fl_key_event_new(102, kRelease, kKeyCodeKeyA, GDK_KEY_A, state, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 4u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1472,11 +1403,10 @@
// Release NumLock. Since the previous event should have synthesized NumLock
// to be released, this should result in only an empty event.
g_expected_handled = true;
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(103, kRelease, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 103, kRelease, kKeyCodeNumLock, GDK_KEY_Num_Lock, state, 0);
+ fl_key_responder_handle_event(responder, event3, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 1u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1505,11 +1435,10 @@
GdkModifierType state = GDK_MOD2_MASK;
// NumLock down
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(101, kPress, kKeyCodeNumLock,
+ GDK_KEY_Num_Lock, state, 0);
+ fl_key_responder_handle_event(responder, event1, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 3u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1543,11 +1472,10 @@
state = GDK_MOD2_MASK;
// NumLock up
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(102, kPress, GDK_KEY_Num_Lock, kKeyCodeNumLock,
- state, kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(102, kPress, kKeyCodeNumLock,
+ GDK_KEY_Num_Lock, state, 0);
+ fl_key_responder_handle_event(responder, event2, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 4u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1606,11 +1534,10 @@
// Send a KeyA up event, which will be ignored.
g_expected_handled = true; // The ignored event is always handled.
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(101, kRelease, GDK_KEY_a, kKeyCodeKeyA, state,
- kIsNotModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event =
+ fl_key_event_new(101, kRelease, kKeyCodeKeyA, GDK_KEY_a, state, 0);
+ fl_key_responder_handle_event(responder, event, verify_response_handled,
+ &user_data);
EXPECT_EQ(g_call_records->len, 2u);
record = FL_KEY_EMBEDDER_CALL_RECORD(g_ptr_array_index(g_call_records, 0));
@@ -1659,11 +1586,10 @@
GdkModifierType state) {
now_time += 1;
int user_data = 123; // Arbitrary user data
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(now_time, is_press, keyval, keycode, state,
- kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event =
+ fl_key_event_new(now_time, is_press, keycode, keyval, state, 0);
+ fl_key_responder_handle_event(responder, event, verify_response_handled,
+ &user_data);
};
FlKeyEmbedderCallRecord* record;
@@ -1768,11 +1694,10 @@
GdkModifierType state) {
now_time += 1;
int user_data = 123; // Arbitrary user data
- fl_key_responder_handle_event(
- responder,
- fl_key_event_new_by_mock(now_time, is_press, keyval, keycode, state,
- kIsModifier),
- verify_response_handled, &user_data);
+ g_autoptr(FlKeyEvent) event =
+ fl_key_event_new(now_time, is_press, keycode, keyval, state, 0);
+ fl_key_responder_handle_event(responder, event, verify_response_handled,
+ &user_data);
};
FlKeyEmbedderCallRecord* record;
diff --git a/shell/platform/linux/fl_key_event.cc b/shell/platform/linux/fl_key_event.cc
index 230bd9c..b79e1b9 100644
--- a/shell/platform/linux/fl_key_event.cc
+++ b/shell/platform/linux/fl_key_event.cc
@@ -4,12 +4,59 @@
#include "flutter/shell/platform/linux/fl_key_event.h"
+struct _FlKeyEvent {
+ GObject parent_instance;
+
+ // Time in milliseconds.
+ guint32 time;
+
+ // True if is a press event, otherwise a release event.
+ gboolean is_press;
+
+ // Hardware keycode.
+ guint16 keycode;
+
+ // Keyval.
+ guint keyval;
+
+ // Modifier state.
+ GdkModifierType state;
+
+ // Keyboard group.
+ guint8 group;
+
+ // The original event.
+ GdkEvent* origin;
+};
+
+G_DEFINE_TYPE(FlKeyEvent, fl_key_event, G_TYPE_OBJECT)
+
+FlKeyEvent* fl_key_event_new(guint32 time,
+ gboolean is_press,
+ guint16 keycode,
+ guint keyval,
+ GdkModifierType state,
+ guint8 group) {
+ FlKeyEvent* self =
+ FL_KEY_EVENT(g_object_new(fl_key_event_get_type(), nullptr));
+
+ self->time = time;
+ self->is_press = is_press;
+ self->keycode = keycode;
+ self->keyval = keyval;
+ self->state = state;
+ self->group = group;
+
+ return self;
+}
+
FlKeyEvent* fl_key_event_new_from_gdk_event(GdkEvent* event) {
- g_return_val_if_fail(event != nullptr, nullptr);
+ FlKeyEvent* self =
+ FL_KEY_EVENT(g_object_new(fl_key_event_get_type(), nullptr));
+
GdkEventType type = gdk_event_get_event_type(event);
g_return_val_if_fail(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE,
nullptr);
- FlKeyEvent* result = g_new(FlKeyEvent, 1);
guint16 keycode = 0;
gdk_event_get_keycode(event, &keycode);
@@ -18,26 +65,76 @@
GdkModifierType state = static_cast<GdkModifierType>(0);
gdk_event_get_state(event, &state);
- result->time = gdk_event_get_time(event);
- result->is_press = type == GDK_KEY_PRESS;
- result->keycode = keycode;
- result->keyval = keyval;
- result->state = state;
- result->group = event->key.group;
- result->origin = event;
+ self->time = gdk_event_get_time(event);
+ self->is_press = type == GDK_KEY_PRESS;
+ self->keycode = keycode;
+ self->keyval = keyval;
+ self->state = state;
+ self->group = event->key.group;
+ self->origin = event;
- return result;
+ return self;
}
-void fl_key_event_dispose(FlKeyEvent* event) {
- if (event->origin != nullptr) {
- gdk_event_free(event->origin);
- }
- g_free(event);
+guint32 fl_key_event_get_time(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), 0);
+ return self->time;
}
-FlKeyEvent* fl_key_event_clone(const FlKeyEvent* event) {
- FlKeyEvent* new_event = g_new(FlKeyEvent, 1);
- *new_event = *event;
- return new_event;
+gboolean fl_key_event_get_is_press(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), FALSE);
+ return self->is_press;
}
+
+guint16 fl_key_event_get_keycode(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), 0);
+ return self->keycode;
+}
+
+guint fl_key_event_get_keyval(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), 0);
+ return self->keyval;
+}
+
+GdkModifierType fl_key_event_get_state(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), static_cast<GdkModifierType>(0));
+ return self->state;
+}
+
+guint8 fl_key_event_get_group(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), 0);
+ return self->group;
+}
+
+GdkEvent* fl_key_event_get_origin(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), nullptr);
+ return self->origin;
+}
+
+uint64_t fl_key_event_hash(FlKeyEvent* self) {
+ g_return_val_if_fail(FL_IS_KEY_EVENT(self), 0);
+
+ // Combine the event timestamp, the type of event, and the hardware keycode
+ // (scan code) of the event to come up with a unique id for this event that
+ // can be derived solely from the event data itself, so that we can identify
+ // whether or not we have seen this event already.
+ guint64 type =
+ static_cast<uint64_t>(self->is_press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
+ guint64 keycode = static_cast<uint64_t>(self->keycode);
+ return (self->time & 0xffffffff) | ((type & 0xffff) << 32) |
+ ((keycode & 0xffff) << 48);
+}
+
+static void fl_key_event_dispose(GObject* object) {
+ FlKeyEvent* self = FL_KEY_EVENT(object);
+
+ g_clear_pointer(&self->origin, gdk_event_free);
+
+ G_OBJECT_CLASS(fl_key_event_parent_class)->dispose(object);
+}
+
+static void fl_key_event_class_init(FlKeyEventClass* klass) {
+ G_OBJECT_CLASS(klass)->dispose = fl_key_event_dispose;
+}
+
+static void fl_key_event_init(FlKeyEvent* self) {}
diff --git a/shell/platform/linux/fl_key_event.h b/shell/platform/linux/fl_key_event.h
index 2a3a433..80b5675 100644
--- a/shell/platform/linux/fl_key_event.h
+++ b/shell/platform/linux/fl_key_event.h
@@ -5,8 +5,12 @@
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_H_
+#include <stdint.h>
+
#include <gdk/gdk.h>
+G_DECLARE_FINAL_TYPE(FlKeyEvent, fl_key_event, FL, KEY_EVENT, GObject);
+
/**
* FlKeyEvent:
* A struct that stores information from GdkEvent.
@@ -19,42 +23,47 @@
* object, so that Flutter can create an event object in unit tests even after
* migrating to GDK 4.0 which stops supporting creating GdkEvent.
*/
-typedef struct _FlKeyEvent {
- // Time in milliseconds.
- guint32 time;
- // True if is a press event, otherwise a release event.
- bool is_press;
- // Hardware keycode.
- guint16 keycode;
- // Keyval.
- guint keyval;
- // Modifier state.
- GdkModifierType state;
- // Keyboard group.
- guint8 group;
- // The original event.
- GdkEvent* origin;
-} FlKeyEvent;
+
+FlKeyEvent* fl_key_event_new(guint32 time,
+ gboolean is_press,
+ guint16 keycode,
+ guint keyval,
+ GdkModifierType state,
+ guint8 group);
/**
* fl_key_event_new_from_gdk_event:
- * @event: the #GdkEvent this #FlKeyEvent is based on. The #event must be a
- * #GdkEventKey, and will be destroyed by #fl_key_event_dispose.
+ * @event: the #GdkEvent this #FlKeyEvent is based on.
*
* Create a new #FlKeyEvent based on a #GdkEvent.
*
- * Returns: a new #FlKeyEvent. Must be freed with #fl_key_event_dispose.
+ * Returns: a new #FlKeyEvent.
*/
FlKeyEvent* fl_key_event_new_from_gdk_event(GdkEvent* event);
-/**
- * fl_key_event_dispose:
- * @event: the event to dispose.
- *
- * Properly disposes the content of #event and then the pointer.
- */
-void fl_key_event_dispose(FlKeyEvent* event);
+guint32 fl_key_event_get_time(FlKeyEvent* event);
-FlKeyEvent* fl_key_event_clone(const FlKeyEvent* source);
+gboolean fl_key_event_get_is_press(FlKeyEvent* event);
+
+guint16 fl_key_event_get_keycode(FlKeyEvent* event);
+
+guint fl_key_event_get_keyval(FlKeyEvent* event);
+
+GdkModifierType fl_key_event_get_state(FlKeyEvent* event);
+
+guint8 fl_key_event_get_group(FlKeyEvent* event);
+
+GdkEvent* fl_key_event_get_origin(FlKeyEvent* event);
+
+/**
+ * fl_key_event_hash:
+ * @event: an #FlKeyEvent.
+ *
+ * Calculates a unique ID for a given FlKeyEvent object to use for
+ * identification of responses from the framework.
+ *
+ * Returns: a hash code.
+ */
+uint64_t fl_key_event_hash(FlKeyEvent* event);
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEY_EVENT_H_
diff --git a/shell/platform/linux/fl_keyboard_handler.cc b/shell/platform/linux/fl_keyboard_handler.cc
index 7597213..46d4547 100644
--- a/shell/platform/linux/fl_keyboard_handler.cc
+++ b/shell/platform/linux/fl_keyboard_handler.cc
@@ -11,6 +11,7 @@
#include "flutter/shell/platform/linux/fl_key_channel_responder.h"
#include "flutter/shell/platform/linux/fl_key_embedder_responder.h"
+#include "flutter/shell/platform/linux/fl_keyboard_pending_event.h"
#include "flutter/shell/platform/linux/key_mapping.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
@@ -24,12 +25,6 @@
/* Declarations of private classes */
-G_DECLARE_FINAL_TYPE(FlKeyboardPendingEvent,
- fl_keyboard_pending_event,
- FL,
- KEYBOARD_PENDING_EVENT,
- GObject);
-
#define FL_TYPE_KEYBOARD_HANDLER_USER_DATA \
fl_keyboard_handler_user_data_get_type()
G_DECLARE_FINAL_TYPE(FlKeyboardHandlerUserData,
@@ -94,10 +89,10 @@
} // namespace
-static uint64_t get_logical_key_from_layout(const FlKeyEvent* event,
+static uint64_t get_logical_key_from_layout(FlKeyEvent* event,
const DerivedLayout& layout) {
- guint8 group = event->group;
- guint16 keycode = event->keycode;
+ guint8 group = fl_key_event_get_group(event);
+ guint16 keycode = fl_key_event_get_keycode(event);
if (keycode >= kLayoutSize) {
return 0;
}
@@ -109,93 +104,6 @@
return 0;
}
-/* Define FlKeyboardPendingEvent */
-
-/**
- * FlKeyboardPendingEvent:
- * A record for events that have been received by the handler, but
- * dispatched to other objects, whose results have yet to return.
- *
- * This object is used by both the "pending_responds" list and the
- * "pending_redispatches" list.
- */
-
-struct _FlKeyboardPendingEvent {
- GObject parent_instance;
-
- // The target event.
- //
- // This is freed by #FlKeyboardPendingEvent if not null.
- std::unique_ptr<FlKeyEvent> event;
-
- // Self-incrementing ID attached to an event sent to the framework.
- //
- // Used to identify pending responds.
- uint64_t sequence_id;
- // The number of responders that haven't replied.
- size_t unreplied;
- // Whether any replied responders reported true (handled).
- bool any_handled;
-
- // A value calculated out of critical event information that can be used
- // to identify redispatched events.
- uint64_t hash;
-};
-
-G_DEFINE_TYPE(FlKeyboardPendingEvent, fl_keyboard_pending_event, G_TYPE_OBJECT)
-
-static void fl_keyboard_pending_event_dispose(GObject* object) {
- // Redundant, but added so that we don't get a warning about unused function
- // for FL_IS_KEYBOARD_PENDING_EVENT.
- g_return_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(object));
-
- FlKeyboardPendingEvent* self = FL_KEYBOARD_PENDING_EVENT(object);
- if (self->event != nullptr) {
- fl_key_event_dispose(self->event.release());
- }
- G_OBJECT_CLASS(fl_keyboard_pending_event_parent_class)->dispose(object);
-}
-
-static void fl_keyboard_pending_event_class_init(
- FlKeyboardPendingEventClass* klass) {
- G_OBJECT_CLASS(klass)->dispose = fl_keyboard_pending_event_dispose;
-}
-
-static void fl_keyboard_pending_event_init(FlKeyboardPendingEvent* self) {}
-
-// Calculates a unique ID for a given FlKeyEvent object to use for
-// identification of responses from the framework.
-static uint64_t fl_keyboard_handler_get_event_hash(FlKeyEvent* event) {
- // Combine the event timestamp, the type of event, and the hardware keycode
- // (scan code) of the event to come up with a unique id for this event that
- // can be derived solely from the event data itself, so that we can identify
- // whether or not we have seen this event already.
- guint64 type =
- static_cast<uint64_t>(event->is_press ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
- guint64 keycode = static_cast<uint64_t>(event->keycode);
- return (event->time & 0xffffffff) | ((type & 0xffff) << 32) |
- ((keycode & 0xffff) << 48);
-}
-
-// Create a new FlKeyboardPendingEvent by providing the target event,
-// the sequence ID, and the number of responders that will reply.
-//
-// This will acquire the ownership of the event.
-static FlKeyboardPendingEvent* fl_keyboard_pending_event_new(
- std::unique_ptr<FlKeyEvent> event,
- uint64_t sequence_id,
- size_t to_reply) {
- FlKeyboardPendingEvent* self = FL_KEYBOARD_PENDING_EVENT(
- g_object_new(fl_keyboard_pending_event_get_type(), nullptr));
-
- self->event = std::move(event);
- self->sequence_id = sequence_id;
- self->unreplied = to_reply;
- self->any_handled = false;
- self->hash = fl_keyboard_handler_get_event_hash(self->event.get());
- return self;
-}
-
/* Define FlKeyboardHandlerUserData */
/**
@@ -299,60 +207,6 @@
G_DEFINE_TYPE(FlKeyboardHandler, fl_keyboard_handler, G_TYPE_OBJECT);
-static void fl_keyboard_handler_dispose(GObject* object);
-
-static void fl_keyboard_handler_class_init(FlKeyboardHandlerClass* klass) {
- G_OBJECT_CLASS(klass)->dispose = fl_keyboard_handler_dispose;
-}
-
-static void fl_keyboard_handler_init(FlKeyboardHandler* self) {
- self->derived_layout = std::make_unique<DerivedLayout>();
-
- self->keycode_to_goals =
- std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
- self->logical_to_mandatory_goals =
- std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
- for (const LayoutGoal& goal : layout_goals) {
- (*self->keycode_to_goals)[goal.keycode] = &goal;
- if (goal.mandatory) {
- (*self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
- }
- }
-
- self->responder_list = g_ptr_array_new_with_free_func(g_object_unref);
-
- self->pending_responds = g_ptr_array_new();
- self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
-
- self->last_sequence_id = 1;
-}
-
-static void fl_keyboard_handler_dispose(GObject* object) {
- FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(object);
-
- if (self->view_delegate != nullptr) {
- fl_keyboard_view_delegate_subscribe_to_layout_change(self->view_delegate,
- nullptr);
- g_object_remove_weak_pointer(
- G_OBJECT(self->view_delegate),
- reinterpret_cast<gpointer*>(&(self->view_delegate)));
- self->view_delegate = nullptr;
- }
-
- self->derived_layout.reset();
- self->keycode_to_goals.reset();
- self->logical_to_mandatory_goals.reset();
-
- g_ptr_array_free(self->responder_list, TRUE);
- g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
- g_ptr_array_free(self->pending_responds, TRUE);
- g_ptr_array_free(self->pending_redispatches, TRUE);
-
- G_OBJECT_CLASS(fl_keyboard_handler_parent_class)->dispose(object);
-}
-
-/* Implement FlKeyboardHandler */
-
// This is an exact copy of g_ptr_array_find_with_equal_func. Somehow CI
// reports that can not find symbol g_ptr_array_find_with_equal_func, despite
// the fact that it runs well locally.
@@ -377,22 +231,21 @@
return FALSE;
}
-// Compare a #FlKeyboardPendingEvent with the given sequence_id. The needle
-// should be a pointer to uint64_t sequence_id.
-static gboolean compare_pending_by_sequence_id(
- gconstpointer pending,
- gconstpointer needle_sequence_id) {
- uint64_t sequence_id = *reinterpret_cast<const uint64_t*>(needle_sequence_id);
- return static_cast<const FlKeyboardPendingEvent*>(pending)->sequence_id ==
- sequence_id;
+// Compare a #FlKeyboardPendingEvent with the given sequence_id.
+static gboolean compare_pending_by_sequence_id(gconstpointer a,
+ gconstpointer b) {
+ FlKeyboardPendingEvent* pending =
+ FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
+ uint64_t sequence_id = *reinterpret_cast<const uint64_t*>(b);
+ return fl_keyboard_pending_event_get_sequence_id(pending) == sequence_id;
}
-// Compare a #FlKeyboardPendingEvent with the given hash. The #needle should be
-// a pointer to uint64_t hash.
-static gboolean compare_pending_by_hash(gconstpointer pending,
- gconstpointer needle_hash) {
- uint64_t hash = *reinterpret_cast<const uint64_t*>(needle_hash);
- return static_cast<const FlKeyboardPendingEvent*>(pending)->hash == hash;
+// Compare a #FlKeyboardPendingEvent with the given hash.
+static gboolean compare_pending_by_hash(gconstpointer a, gconstpointer b) {
+ FlKeyboardPendingEvent* pending =
+ FL_KEYBOARD_PENDING_EVENT(const_cast<gpointer>(a));
+ uint64_t hash = *reinterpret_cast<const uint64_t*>(b);
+ return fl_keyboard_pending_event_get_hash(pending) == hash;
}
// Try to remove a pending event from `pending_redispatches` with the target
@@ -431,22 +284,22 @@
FlKeyboardPendingEvent* pending = FL_KEYBOARD_PENDING_EVENT(
g_ptr_array_index(self->pending_responds, result_index));
g_return_if_fail(pending != nullptr);
- g_return_if_fail(pending->unreplied > 0);
- pending->unreplied -= 1;
- pending->any_handled = pending->any_handled || handled;
+ fl_keyboard_pending_event_mark_replied(pending, handled);
// All responders have replied.
- if (pending->unreplied == 0) {
+ if (fl_keyboard_pending_event_is_complete(pending)) {
g_object_unref(user_data_ptr);
gpointer removed =
g_ptr_array_remove_index_fast(self->pending_responds, result_index);
g_return_if_fail(removed == pending);
- bool should_redispatch = !pending->any_handled &&
- !fl_keyboard_view_delegate_text_filter_key_press(
- self->view_delegate, pending->event.get());
+ bool should_redispatch =
+ !fl_keyboard_pending_event_get_any_handled(pending) &&
+ !fl_keyboard_view_delegate_text_filter_key_press(
+ self->view_delegate, fl_keyboard_pending_event_get_event(pending));
if (should_redispatch) {
g_ptr_array_add(self->pending_redispatches, pending);
- fl_keyboard_view_delegate_redispatch_event(self->view_delegate,
- std::move(pending->event));
+ fl_keyboard_view_delegate_redispatch_event(
+ self->view_delegate,
+ FL_KEY_EVENT(fl_keyboard_pending_event_get_event(pending)));
} else {
g_object_unref(pending);
}
@@ -466,11 +319,11 @@
// 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(FlKeyboardHandler* self, FlKeyEvent* event) {
- guint8 group = event->group;
+ guint8 group = fl_key_event_get_group(event);
if (self->derived_layout->find(group) != self->derived_layout->end()) {
return;
}
- if (self->keycode_to_goals->find(event->keycode) ==
+ if (self->keycode_to_goals->find(fl_key_event_get_keycode(event)) ==
self->keycode_to_goals->end()) {
return;
}
@@ -541,7 +394,7 @@
}
// Returns the keyboard pressed state.
-FlMethodResponse* get_keyboard_state(FlKeyboardHandler* self) {
+static FlMethodResponse* get_keyboard_state(FlKeyboardHandler* self) {
g_autoptr(FlValue) result = fl_value_new_map();
GHashTable* pressing_records =
@@ -582,6 +435,67 @@
}
}
+// The loop body to dispatch an event to a responder.
+static void dispatch_to_responder(gpointer responder_data,
+ gpointer foreach_data_ptr) {
+ DispatchToResponderLoopContext* context =
+ reinterpret_cast<DispatchToResponderLoopContext*>(foreach_data_ptr);
+ FlKeyResponder* responder = FL_KEY_RESPONDER(responder_data);
+ fl_key_responder_handle_event(
+ responder, context->event, responder_handle_event_callback,
+ context->user_data, context->specified_logical_key);
+}
+
+static void fl_keyboard_handler_dispose(GObject* object) {
+ FlKeyboardHandler* self = FL_KEYBOARD_HANDLER(object);
+
+ if (self->view_delegate != nullptr) {
+ fl_keyboard_view_delegate_subscribe_to_layout_change(self->view_delegate,
+ nullptr);
+ g_object_remove_weak_pointer(
+ G_OBJECT(self->view_delegate),
+ reinterpret_cast<gpointer*>(&(self->view_delegate)));
+ self->view_delegate = nullptr;
+ }
+
+ self->derived_layout.reset();
+ self->keycode_to_goals.reset();
+ self->logical_to_mandatory_goals.reset();
+
+ g_ptr_array_free(self->responder_list, TRUE);
+ g_ptr_array_set_free_func(self->pending_responds, g_object_unref);
+ g_ptr_array_free(self->pending_responds, TRUE);
+ g_ptr_array_free(self->pending_redispatches, TRUE);
+
+ G_OBJECT_CLASS(fl_keyboard_handler_parent_class)->dispose(object);
+}
+
+static void fl_keyboard_handler_class_init(FlKeyboardHandlerClass* klass) {
+ G_OBJECT_CLASS(klass)->dispose = fl_keyboard_handler_dispose;
+}
+
+static void fl_keyboard_handler_init(FlKeyboardHandler* self) {
+ self->derived_layout = std::make_unique<DerivedLayout>();
+
+ self->keycode_to_goals =
+ std::make_unique<std::map<uint16_t, const LayoutGoal*>>();
+ self->logical_to_mandatory_goals =
+ std::make_unique<std::map<uint64_t, const LayoutGoal*>>();
+ for (const LayoutGoal& goal : layout_goals) {
+ (*self->keycode_to_goals)[goal.keycode] = &goal;
+ if (goal.mandatory) {
+ (*self->logical_to_mandatory_goals)[goal.logical_key] = &goal;
+ }
+ }
+
+ self->responder_list = g_ptr_array_new_with_free_func(g_object_unref);
+
+ self->pending_responds = g_ptr_array_new();
+ self->pending_redispatches = g_ptr_array_new_with_free_func(g_object_unref);
+
+ self->last_sequence_id = 1;
+}
+
FlKeyboardHandler* fl_keyboard_handler_new(
FlBinaryMessenger* messenger,
FlKeyboardViewDelegate* view_delegate) {
@@ -624,17 +538,6 @@
return self;
}
-// The loop body to dispatch an event to a responder.
-static void dispatch_to_responder(gpointer responder_data,
- gpointer foreach_data_ptr) {
- DispatchToResponderLoopContext* context =
- reinterpret_cast<DispatchToResponderLoopContext*>(foreach_data_ptr);
- FlKeyResponder* responder = FL_KEY_RESPONDER(responder_data);
- fl_key_responder_handle_event(
- responder, context->event, responder_handle_event_callback,
- context->user_data, context->specified_logical_key);
-}
-
gboolean fl_keyboard_handler_handle_event(FlKeyboardHandler* self,
FlKeyEvent* event) {
g_return_val_if_fail(FL_IS_KEYBOARD_HANDLER(self), FALSE);
@@ -643,18 +546,17 @@
guarantee_layout(self, event);
- uint64_t incoming_hash = fl_keyboard_handler_get_event_hash(event);
+ uint64_t incoming_hash = fl_key_event_hash(event);
if (fl_keyboard_handler_remove_redispatched(self, incoming_hash)) {
return FALSE;
}
FlKeyboardPendingEvent* pending = fl_keyboard_pending_event_new(
- std::unique_ptr<FlKeyEvent>(event), ++self->last_sequence_id,
- self->responder_list->len);
+ event, ++self->last_sequence_id, self->responder_list->len);
g_ptr_array_add(self->pending_responds, pending);
- FlKeyboardHandlerUserData* user_data =
- fl_keyboard_handler_user_data_new(self, pending->sequence_id);
+ FlKeyboardHandlerUserData* user_data = fl_keyboard_handler_user_data_new(
+ self, fl_keyboard_pending_event_get_sequence_id(pending));
DispatchToResponderLoopContext data{
.event = event,
.specified_logical_key =
diff --git a/shell/platform/linux/fl_keyboard_handler_test.cc b/shell/platform/linux/fl_keyboard_handler_test.cc
index 6acb2ab..194df9b 100644
--- a/shell/platform/linux/fl_keyboard_handler_test.cc
+++ b/shell/platform/linux/fl_keyboard_handler_test.cc
@@ -71,7 +71,7 @@
typedef std::function<void(const FlutterKeyEvent* event,
AsyncKeyCallback callback)>
EmbedderCallHandler;
-typedef std::function<void(std::unique_ptr<FlKeyEvent>)> RedispatchHandler;
+typedef std::function<void(FlKeyEvent*)> RedispatchHandler;
// A type that can record all kinds of effects that the keyboard handler
// triggers.
@@ -377,11 +377,11 @@
static void fl_mock_view_keyboard_redispatch_event(
FlKeyboardViewDelegate* view_delegate,
- std::unique_ptr<FlKeyEvent> event) {
+ FlKeyEvent* event) {
FlMockViewDelegatePrivate* priv =
FL_MOCK_VIEW_DELEGATE_GET_PRIVATE(view_delegate);
if (priv->redispatch_handler) {
- priv->redispatch_handler(std::move(event));
+ priv->redispatch_handler(event);
}
}
@@ -467,23 +467,6 @@
/***** End FlMockViewDelegate *****/
-// Create a new #FlKeyEvent with the given information.
-static FlKeyEvent* fl_key_event_new_by_mock(bool is_press,
- guint keyval,
- guint16 keycode,
- GdkModifierType state,
- gboolean is_modifier,
- guint8 group = 0) {
- FlKeyEvent* event = g_new0(FlKeyEvent, 1);
- event->is_press = is_press;
- event->time = 0;
- event->state = state;
- event->keyval = keyval;
- event->group = group;
- event->keycode = keycode;
- return event;
-}
-
class KeyboardTester {
public:
KeyboardTester() {
@@ -502,6 +485,7 @@
~KeyboardTester() {
g_clear_object(&view_);
g_clear_object(&handler_);
+ g_clear_pointer(&redispatched_events_, g_ptr_array_unref);
}
FlKeyboardHandler* handler() { return handler_; }
@@ -520,21 +504,20 @@
// Returns the number of events redispatched. If any result is unexpected
// (handled), return a minus number `-x` instead, where `x` is the index of
// the first unexpected redispatch.
- int redispatchEventsAndClear(
- std::vector<std::unique_ptr<FlKeyEvent>>& events) {
- size_t event_count = events.size();
+ int redispatchEventsAndClear(GPtrArray* events) {
+ guint event_count = events->len;
int first_error = -1;
during_redispatch_ = true;
- for (size_t event_id = 0; event_id < event_count; event_id += 1) {
- bool handled = fl_keyboard_handler_handle_event(
- handler_, events[event_id].release());
+ for (guint event_id = 0; event_id < event_count; event_id += 1) {
+ FlKeyEvent* event = FL_KEY_EVENT(g_ptr_array_index(events, event_id));
+ bool handled = fl_keyboard_handler_handle_event(handler_, event);
EXPECT_FALSE(handled);
if (handled) {
first_error = first_error == -1 ? event_id : first_error;
}
}
during_redispatch_ = false;
- events.clear();
+ g_ptr_array_set_size(events, 0);
return first_error < 0 ? event_count : -first_error;
}
@@ -610,12 +593,11 @@
fl_mock_view_set_text_filter_result(view_, response);
}
- void recordRedispatchedEventsTo(
- std::vector<std::unique_ptr<FlKeyEvent>>& storage) {
- fl_mock_view_set_redispatch_handler(
- view_, [&storage](std::unique_ptr<FlKeyEvent> key) {
- storage.push_back(std::move(key));
- });
+ void recordRedispatchedEventsTo(GPtrArray* storage) {
+ redispatched_events_ = g_ptr_array_ref(storage);
+ fl_mock_view_set_redispatch_handler(view_, [this](FlKeyEvent* key) {
+ g_ptr_array_add(redispatched_events_, g_object_ref(key));
+ });
}
void setLayout(const MockLayoutData& layout) {
@@ -625,6 +607,7 @@
private:
FlMockViewDelegate* view_;
FlKeyboardHandler* handler_;
+ GPtrArray* redispatched_events_ = nullptr;
bool during_redispatch_ = false;
static gboolean _flushChannelMessagesCb(gpointer data) {
@@ -642,16 +625,14 @@
// Record calls so that they aren't responded.
tester.recordEmbedderCallsTo(call_records);
- fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ fl_keyboard_handler_handle_event(tester.handler(), event1);
tester.respondToEmbedderCallsWith(true);
- fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ fl_keyboard_handler_handle_event(tester.handler(), event2);
tester.flushChannelMessages();
@@ -661,7 +642,8 @@
TEST(FlKeyboardHandlerTest, SingleDelegateWithAsyncResponds) {
KeyboardTester tester;
std::vector<CallRecord> call_records;
- std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
+ g_autoptr(GPtrArray) redispatched =
+ g_ptr_array_new_with_free_func(g_object_unref);
gboolean handler_handled = false;
@@ -670,55 +652,56 @@
tester.recordRedispatchedEventsTo(redispatched);
// Dispatch a key event
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event1);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_EQ(call_records.size(), 1u);
EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeDown, kPhysicalKeyA,
kLogicalKeyA, "a", false);
call_records[0].callback(true);
tester.flushChannelMessages();
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_TRUE(fl_keyboard_handler_is_state_clear(tester.handler()));
call_records.clear();
/// Test 2: Two events that are unhandled by the framework
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event2);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_EQ(call_records.size(), 1u);
EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeUp, kPhysicalKeyA,
kLogicalKeyA, nullptr, false);
// Dispatch another key event
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_b, kKeyCodeKeyB,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event3 = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyB, GDK_KEY_b, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event3);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_EQ(call_records.size(), 2u);
EXPECT_KEY_EVENT(call_records[1], kFlutterKeyEventTypeDown, kPhysicalKeyB,
kLogicalKeyB, "b", false);
// Resolve the second event first to test out-of-order response
call_records[1].callback(false);
- EXPECT_EQ(redispatched.size(), 1u);
- EXPECT_EQ(redispatched[0]->keyval, 0x62u);
+ EXPECT_EQ(redispatched->len, 1u);
+ EXPECT_EQ(
+ fl_key_event_get_keyval(FL_KEY_EVENT(g_ptr_array_index(redispatched, 0))),
+ 0x62u);
call_records[0].callback(false);
tester.flushChannelMessages();
- EXPECT_EQ(redispatched.size(), 2u);
- EXPECT_EQ(redispatched[1]->keyval, 0x61u);
+ EXPECT_EQ(redispatched->len, 2u);
+ EXPECT_EQ(
+ fl_key_event_get_keyval(FL_KEY_EVENT(g_ptr_array_index(redispatched, 1))),
+ 0x61u);
EXPECT_FALSE(fl_keyboard_handler_is_state_clear(tester.handler()));
call_records.clear();
@@ -731,13 +714,12 @@
/// Test 3: Dispatch the same event again to ensure that prevention from
/// redispatching only works once.
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event4 = fl_key_event_new(
+ 0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event4);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_EQ(call_records.size(), 1u);
call_records[0].callback(true);
@@ -748,40 +730,39 @@
KeyboardTester tester;
gboolean handler_handled = false;
std::vector<CallRecord> call_records;
- std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
+ g_autoptr(GPtrArray) redispatched =
+ g_ptr_array_new_with_free_func(g_object_unref);
/// Test 1: One event that is handled by the framework
tester.respondToEmbedderCallsWithAndRecordsTo(true, call_records);
tester.recordRedispatchedEventsTo(redispatched);
// Dispatch a key event
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event1);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
EXPECT_EQ(call_records.size(), 1u);
EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeDown, kPhysicalKeyA,
kLogicalKeyA, "a", false);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
call_records.clear();
EXPECT_TRUE(fl_keyboard_handler_is_state_clear(tester.handler()));
- redispatched.clear();
+ g_ptr_array_set_size(redispatched, 0);
/// Test 2: An event unhandled by the framework
tester.respondToEmbedderCallsWithAndRecordsTo(false, call_records);
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event2);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
EXPECT_EQ(call_records.size(), 1u);
EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeUp, kPhysicalKeyA,
kLogicalKeyA, nullptr, false);
- EXPECT_EQ(redispatched.size(), 1u);
+ EXPECT_EQ(redispatched->len, 1u);
call_records.clear();
EXPECT_FALSE(fl_keyboard_handler_is_state_clear(tester.handler()));
@@ -795,7 +776,8 @@
TEST(FlKeyboardHandlerTest, WithTwoAsyncDelegates) {
KeyboardTester tester;
std::vector<CallRecord> call_records;
- std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
+ g_autoptr(GPtrArray) redispatched =
+ g_ptr_array_new_with_free_func(g_object_unref);
gboolean handler_handled = false;
@@ -805,13 +787,12 @@
/// Test 1: One delegate responds true, the other false
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event1);
EXPECT_EQ(handler_handled, true);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_EQ(call_records.size(), 2u);
EXPECT_EQ(call_records[0].type, CallRecord::kKeyCallEmbedder);
@@ -820,19 +801,18 @@
call_records[0].callback(true);
call_records[1].callback(false);
tester.flushChannelMessages();
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_TRUE(fl_keyboard_handler_is_state_clear(tester.handler()));
call_records.clear();
/// Test 2: All delegates respond false
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event2);
EXPECT_EQ(handler_handled, true);
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_EQ(call_records.size(), 2u);
EXPECT_EQ(call_records[0].type, CallRecord::kKeyCallEmbedder);
@@ -845,7 +825,7 @@
// Resolve redispatch
tester.flushChannelMessages();
- EXPECT_EQ(redispatched.size(), 1u);
+ EXPECT_EQ(redispatched->len, 1u);
EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
EXPECT_EQ(call_records.size(), 0u);
@@ -854,20 +834,20 @@
TEST(FlKeyboardHandlerTest, TextInputHandlerReturnsFalse) {
KeyboardTester tester;
- std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
+ g_autoptr(GPtrArray) redispatched =
+ g_ptr_array_new_with_free_func(g_object_unref);
gboolean handler_handled = false;
tester.recordRedispatchedEventsTo(redispatched);
tester.respondToTextInputWith(false);
// Dispatch a key event.
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
// The event was redispatched because no one handles it.
- EXPECT_EQ(redispatched.size(), 1u);
+ EXPECT_EQ(redispatched->len, 1u);
// Resolve redispatched event.
EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
@@ -877,20 +857,20 @@
TEST(FlKeyboardHandlerTest, TextInputHandlerReturnsTrue) {
KeyboardTester tester;
- std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
+ g_autoptr(GPtrArray) redispatched =
+ g_ptr_array_new_with_free_func(g_object_unref);
gboolean handler_handled = false;
tester.recordRedispatchedEventsTo(redispatched);
tester.respondToTextInputWith(true);
// Dispatch a key event.
- handler_handled = fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ handler_handled = fl_keyboard_handler_handle_event(tester.handler(), event);
tester.flushChannelMessages();
EXPECT_EQ(handler_handled, true);
// The event was not redispatched because handler handles it.
- EXPECT_EQ(redispatched.size(), 0u);
+ EXPECT_EQ(redispatched->len, 0u);
EXPECT_TRUE(fl_keyboard_handler_is_state_clear(tester.handler()));
}
@@ -902,14 +882,12 @@
tester.recordEmbedderCallsTo(call_records);
auto sendTap = [&](guint8 keycode, guint keyval, guint8 group) {
- fl_keyboard_handler_handle_event(
- tester.handler(), fl_key_event_new_by_mock(
- true, keyval, keycode,
- static_cast<GdkModifierType>(0), false, group));
- fl_keyboard_handler_handle_event(
- tester.handler(), fl_key_event_new_by_mock(
- false, keyval, keycode,
- static_cast<GdkModifierType>(0), false, group));
+ g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
+ 0, TRUE, keycode, keyval, static_cast<GdkModifierType>(0), group);
+ fl_keyboard_handler_handle_event(tester.handler(), event1);
+ g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
+ 0, FALSE, keycode, keyval, static_cast<GdkModifierType>(0), group);
+ fl_keyboard_handler_handle_event(tester.handler(), event2);
};
/* US keyboard layout */
@@ -1033,10 +1011,9 @@
tester.respondToTextInputWith(true);
// Dispatch a key event.
- fl_keyboard_handler_handle_event(
- tester.handler(),
- fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA,
- static_cast<GdkModifierType>(0), false));
+ g_autoptr(FlKeyEvent) event = fl_key_event_new(
+ 0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
+ fl_keyboard_handler_handle_event(tester.handler(), event);
GHashTable* pressedState =
fl_keyboard_handler_get_pressed_state(tester.handler());
diff --git a/shell/platform/linux/fl_keyboard_pending_event.cc b/shell/platform/linux/fl_keyboard_pending_event.cc
new file mode 100644
index 0000000..eb9b6c3
--- /dev/null
+++ b/shell/platform/linux/fl_keyboard_pending_event.cc
@@ -0,0 +1,105 @@
+// 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_pending_event.h"
+
+/**
+ * FlKeyboardPendingEvent:
+ * A record for events that have been received by the handler, but
+ * dispatched to other objects, whose results have yet to return.
+ *
+ * This object is used by both the "pending_responds" list and the
+ * "pending_redispatches" list.
+ */
+
+struct _FlKeyboardPendingEvent {
+ GObject parent_instance;
+
+ // The target event.
+ FlKeyEvent* event;
+
+ // Unique ID to identify pending responds.
+ uint64_t sequence_id;
+
+ // The number of responders that haven't replied.
+ size_t unreplied;
+
+ // Whether any replied responders reported true (handled).
+ bool any_handled;
+
+ // A value calculated out of critical event information that can be used
+ // to identify redispatched events.
+ uint64_t hash;
+};
+
+G_DEFINE_TYPE(FlKeyboardPendingEvent, fl_keyboard_pending_event, G_TYPE_OBJECT)
+
+static void fl_keyboard_pending_event_dispose(GObject* object) {
+ FlKeyboardPendingEvent* self = FL_KEYBOARD_PENDING_EVENT(object);
+
+ g_clear_object(&self->event);
+
+ G_OBJECT_CLASS(fl_keyboard_pending_event_parent_class)->dispose(object);
+}
+
+static void fl_keyboard_pending_event_class_init(
+ FlKeyboardPendingEventClass* klass) {
+ G_OBJECT_CLASS(klass)->dispose = fl_keyboard_pending_event_dispose;
+}
+
+static void fl_keyboard_pending_event_init(FlKeyboardPendingEvent* self) {}
+
+// Creates a new FlKeyboardPendingEvent by providing the target event,
+// the sequence ID, and the number of responders that will reply.
+FlKeyboardPendingEvent* fl_keyboard_pending_event_new(FlKeyEvent* event,
+ uint64_t sequence_id,
+ size_t to_reply) {
+ FlKeyboardPendingEvent* self = FL_KEYBOARD_PENDING_EVENT(
+ g_object_new(fl_keyboard_pending_event_get_type(), nullptr));
+
+ self->event = FL_KEY_EVENT(g_object_ref(event));
+ self->sequence_id = sequence_id;
+ self->unreplied = to_reply;
+ self->any_handled = false;
+ self->hash = fl_key_event_hash(self->event);
+
+ return self;
+}
+
+FlKeyEvent* fl_keyboard_pending_event_get_event(FlKeyboardPendingEvent* self) {
+ g_return_val_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(self), nullptr);
+ return self->event;
+}
+
+uint64_t fl_keyboard_pending_event_get_sequence_id(
+ FlKeyboardPendingEvent* self) {
+ g_return_val_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(self), 0);
+ return self->sequence_id;
+}
+
+uint64_t fl_keyboard_pending_event_get_hash(FlKeyboardPendingEvent* self) {
+ g_return_val_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(self), 0);
+ return self->hash;
+}
+
+void fl_keyboard_pending_event_mark_replied(FlKeyboardPendingEvent* self,
+ gboolean handled) {
+ g_return_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(self));
+ g_return_if_fail(self->unreplied > 0);
+ self->unreplied -= 1;
+ if (handled) {
+ self->any_handled = TRUE;
+ }
+}
+
+gboolean fl_keyboard_pending_event_get_any_handled(
+ FlKeyboardPendingEvent* self) {
+ g_return_val_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(self), FALSE);
+ return self->any_handled;
+}
+
+gboolean fl_keyboard_pending_event_is_complete(FlKeyboardPendingEvent* self) {
+ g_return_val_if_fail(FL_IS_KEYBOARD_PENDING_EVENT(self), FALSE);
+ return self->unreplied == 0;
+}
diff --git a/shell/platform/linux/fl_keyboard_pending_event.h b/shell/platform/linux/fl_keyboard_pending_event.h
new file mode 100644
index 0000000..50204d6
--- /dev/null
+++ b/shell/platform/linux/fl_keyboard_pending_event.h
@@ -0,0 +1,39 @@
+// 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_PENDING_EVENT_H_
+#define FLUTTER_SHELL_PLATFORM_LINUX_FL_KEYBOARD_PENDING_EVENT_H_
+
+#include "fl_key_event.h"
+
+G_BEGIN_DECLS
+
+G_DECLARE_FINAL_TYPE(FlKeyboardPendingEvent,
+ fl_keyboard_pending_event,
+ FL,
+ KEYBOARD_PENDING_EVENT,
+ GObject);
+
+FlKeyboardPendingEvent* fl_keyboard_pending_event_new(FlKeyEvent* event,
+ uint64_t sequence_id,
+ size_t to_reply);
+
+FlKeyEvent* fl_keyboard_pending_event_get_event(FlKeyboardPendingEvent* event);
+
+uint64_t fl_keyboard_pending_event_get_sequence_id(
+ FlKeyboardPendingEvent* event);
+
+uint64_t fl_keyboard_pending_event_get_hash(FlKeyboardPendingEvent* event);
+
+void fl_keyboard_pending_event_mark_replied(FlKeyboardPendingEvent* event,
+ gboolean handled);
+
+gboolean fl_keyboard_pending_event_get_any_handled(
+ FlKeyboardPendingEvent* event);
+
+gboolean fl_keyboard_pending_event_is_complete(FlKeyboardPendingEvent* event);
+
+G_END_DECLS
+
+#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEYBOARD_PENDING_EVENT_H_
diff --git a/shell/platform/linux/fl_keyboard_view_delegate.cc b/shell/platform/linux/fl_keyboard_view_delegate.cc
index 3c5fac9..e3c79c2 100644
--- a/shell/platform/linux/fl_keyboard_view_delegate.cc
+++ b/shell/platform/linux/fl_keyboard_view_delegate.cc
@@ -39,14 +39,13 @@
return FL_KEYBOARD_VIEW_DELEGATE_GET_IFACE(self)->get_messenger(self);
}
-void fl_keyboard_view_delegate_redispatch_event(
- FlKeyboardViewDelegate* self,
- std::unique_ptr<FlKeyEvent> event) {
+void fl_keyboard_view_delegate_redispatch_event(FlKeyboardViewDelegate* self,
+ FlKeyEvent* event) {
g_return_if_fail(FL_IS_KEYBOARD_VIEW_DELEGATE(self));
g_return_if_fail(event != nullptr);
- return FL_KEYBOARD_VIEW_DELEGATE_GET_IFACE(self)->redispatch_event(
- self, std::move(event));
+ return FL_KEYBOARD_VIEW_DELEGATE_GET_IFACE(self)->redispatch_event(self,
+ event);
}
void fl_keyboard_view_delegate_subscribe_to_layout_change(
diff --git a/shell/platform/linux/fl_keyboard_view_delegate.h b/shell/platform/linux/fl_keyboard_view_delegate.h
index 59fdc3f..a84cc58 100644
--- a/shell/platform/linux/fl_keyboard_view_delegate.h
+++ b/shell/platform/linux/fl_keyboard_view_delegate.h
@@ -46,8 +46,7 @@
FlBinaryMessenger* (*get_messenger)(FlKeyboardViewDelegate* delegate);
- void (*redispatch_event)(FlKeyboardViewDelegate* delegate,
- std::unique_ptr<FlKeyEvent> event);
+ void (*redispatch_event)(FlKeyboardViewDelegate* delegate, FlKeyEvent* event);
void (*subscribe_to_layout_change)(FlKeyboardViewDelegate* delegate,
KeyboardLayoutNotifier notifier);
@@ -103,13 +102,10 @@
*
* Handles `FlKeyboardHandler`'s request to insert a GDK event to the system for
* redispatching.
- *
- * The ownership of event will be transferred to the view delegate. The view
- * delegate is responsible to call fl_key_event_dispose.
*/
void fl_keyboard_view_delegate_redispatch_event(
FlKeyboardViewDelegate* delegate,
- std::unique_ptr<FlKeyEvent> event);
+ FlKeyEvent* event);
void fl_keyboard_view_delegate_subscribe_to_layout_change(
FlKeyboardViewDelegate* delegate,
diff --git a/shell/platform/linux/fl_text_input_handler.cc b/shell/platform/linux/fl_text_input_handler.cc
index afc8afc..f4d3eb7 100644
--- a/shell/platform/linux/fl_text_input_handler.cc
+++ b/shell/platform/linux/fl_text_input_handler.cc
@@ -627,7 +627,8 @@
}
if (gtk_im_context_filter_keypress(
- priv->im_context, reinterpret_cast<GdkEventKey*>(event->origin))) {
+ priv->im_context,
+ reinterpret_cast<GdkEventKey*>(fl_key_event_get_origin(event)))) {
return TRUE;
}
@@ -639,11 +640,11 @@
gboolean do_action = FALSE;
// Handle navigation keys.
gboolean changed = FALSE;
- if (event->is_press) {
- switch (event->keyval) {
+ if (fl_key_event_get_is_press(event)) {
+ switch (fl_key_event_get_keyval(event)) {
case GDK_KEY_End:
case GDK_KEY_KP_End:
- if (event->state & GDK_SHIFT_MASK) {
+ if (fl_key_event_get_state(event) & GDK_SHIFT_MASK) {
changed = priv->text_model->SelectToEnd();
} else {
changed = priv->text_model->MoveCursorToEnd();
@@ -662,7 +663,7 @@
break;
case GDK_KEY_Home:
case GDK_KEY_KP_Home:
- if (event->state & GDK_SHIFT_MASK) {
+ if (fl_key_event_get_state(event) & GDK_SHIFT_MASK) {
changed = priv->text_model->SelectToBeginning();
} else {
changed = priv->text_model->MoveCursorToBeginning();
diff --git a/shell/platform/linux/fl_text_input_handler_test.cc b/shell/platform/linux/fl_text_input_handler_test.cc
index 4c4606a..7787b42 100644
--- a/shell/platform/linux/fl_text_input_handler_test.cc
+++ b/shell/platform/linux/fl_text_input_handler_test.cc
@@ -184,9 +184,8 @@
GdkEvent* gdk_event = gdk_event_new(GDK_KEY_PRESS);
gdk_event->key.keyval = keyval;
gdk_event->key.state = state;
- FlKeyEvent* key_event = fl_key_event_new_from_gdk_event(gdk_event);
+ g_autoptr(FlKeyEvent) key_event = fl_key_event_new_from_gdk_event(gdk_event);
fl_text_input_handler_filter_keypress(handler, key_event);
- fl_key_event_dispose(key_event);
}
TEST(FlTextInputHandlerTest, MessageHandler) {
diff --git a/shell/platform/linux/fl_view.cc b/shell/platform/linux/fl_view.cc
index bfaedc5..e84b144 100644
--- a/shell/platform/linux/fl_view.cc
+++ b/shell/platform/linux/fl_view.cc
@@ -357,13 +357,12 @@
};
iface->redispatch_event = [](FlKeyboardViewDelegate* view_delegate,
- std::unique_ptr<FlKeyEvent> in_event) {
- FlKeyEvent* event = in_event.release();
- GdkEventType event_type = gdk_event_get_event_type(event->origin);
+ FlKeyEvent* event) {
+ GdkEventType event_type =
+ gdk_event_get_event_type(fl_key_event_get_origin(event));
g_return_if_fail(event_type == GDK_KEY_PRESS ||
event_type == GDK_KEY_RELEASE);
- gdk_event_put(event->origin);
- fl_key_event_dispose(event);
+ gdk_event_put(fl_key_event_get_origin(event));
};
iface->subscribe_to_layout_change = [](FlKeyboardViewDelegate* view_delegate,