Keyboard tidy ups (#162054)
Make async calls use standard GLib async API. Remove test specific methods. Smaller cleanups.
This commit is contained in:
parent
2919003513
commit
b56b5b6a23
@ -545,6 +545,15 @@ G_MODULE_EXPORT FlEngine* fl_engine_new(FlDartProject* project) {
|
||||
return fl_engine_new_with_renderer(project, FL_RENDERER(renderer));
|
||||
}
|
||||
|
||||
FlEngine* fl_engine_new_with_binary_messenger(
|
||||
FlBinaryMessenger* binary_messenger) {
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
FlEngine* self = fl_engine_new(project);
|
||||
g_object_unref(self->binary_messenger);
|
||||
self->binary_messenger = FL_BINARY_MESSENGER(g_object_ref(binary_messenger));
|
||||
return self;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT FlEngine* fl_engine_new_headless(FlDartProject* project) {
|
||||
g_autoptr(FlRendererHeadless) renderer = fl_renderer_headless_new();
|
||||
return fl_engine_new_with_renderer(project, FL_RENDERER(renderer));
|
||||
|
@ -61,6 +61,17 @@ typedef void (*FlEngineUpdateSemanticsHandler)(
|
||||
const FlutterSemanticsUpdate2* update,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* fl_engine_new_with_binary_messenger:
|
||||
* @binary_messenger: an #FlBinaryMessenger.
|
||||
*
|
||||
* Creates a new engine with a custom binary messenger. Used for testing.
|
||||
*
|
||||
* Returns: a new #FlEngine.
|
||||
*/
|
||||
FlEngine* fl_engine_new_with_binary_messenger(
|
||||
FlBinaryMessenger* binary_messenger);
|
||||
|
||||
/**
|
||||
* fl_engine_new_with_renderer:
|
||||
* @project: an #FlDartProject.
|
||||
|
@ -73,55 +73,6 @@ static uint64_t to_lower(uint64_t n) {
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* FlKeyEmbedderUserData:
|
||||
* The user_data used when #FlKeyEmbedderResponder sends message through the
|
||||
* embedder.SendKeyEvent API.
|
||||
*/
|
||||
G_DECLARE_FINAL_TYPE(FlKeyEmbedderUserData,
|
||||
fl_key_embedder_user_data,
|
||||
FL,
|
||||
KEY_EMBEDDER_USER_DATA,
|
||||
GObject);
|
||||
|
||||
struct _FlKeyEmbedderUserData {
|
||||
GObject parent_instance;
|
||||
|
||||
FlKeyEmbedderResponderAsyncCallback callback;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(FlKeyEmbedderUserData, fl_key_embedder_user_data, G_TYPE_OBJECT)
|
||||
|
||||
static void fl_key_embedder_user_data_dispose(GObject* object);
|
||||
|
||||
static void fl_key_embedder_user_data_class_init(
|
||||
FlKeyEmbedderUserDataClass* klass) {
|
||||
G_OBJECT_CLASS(klass)->dispose = fl_key_embedder_user_data_dispose;
|
||||
}
|
||||
|
||||
static void fl_key_embedder_user_data_init(FlKeyEmbedderUserData* self) {}
|
||||
|
||||
static void fl_key_embedder_user_data_dispose(GObject* object) {
|
||||
// The following line suppresses a warning for unused function
|
||||
// FL_IS_KEY_EMBEDDER_USER_DATA.
|
||||
g_return_if_fail(FL_IS_KEY_EMBEDDER_USER_DATA(object));
|
||||
}
|
||||
|
||||
// Creates a new FlKeyChannelUserData private class with all information.
|
||||
//
|
||||
// The callback and the user_data might be nullptr.
|
||||
static FlKeyEmbedderUserData* fl_key_embedder_user_data_new(
|
||||
FlKeyEmbedderResponderAsyncCallback callback,
|
||||
gpointer user_data) {
|
||||
FlKeyEmbedderUserData* self = FL_KEY_EMBEDDER_USER_DATA(
|
||||
g_object_new(fl_key_embedder_user_data_get_type(), nullptr));
|
||||
|
||||
self->callback = callback;
|
||||
self->user_data = user_data;
|
||||
return self;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
typedef enum {
|
||||
@ -135,8 +86,8 @@ typedef enum {
|
||||
struct _FlKeyEmbedderResponder {
|
||||
GObject parent_instance;
|
||||
|
||||
EmbedderSendKeyEvent send_key_event;
|
||||
void* send_key_event_user_data;
|
||||
// Engine sending key events to.
|
||||
GWeakRef engine;
|
||||
|
||||
// Internal record for states of whether a key is pressed.
|
||||
//
|
||||
@ -190,6 +141,8 @@ struct _FlKeyEmbedderResponder {
|
||||
// It is a map from primary physical keys to lock bits. Both keys and values
|
||||
// are directly stored uint64s. This table is freed by the responder.
|
||||
GHashTable* logical_key_to_lock_bit;
|
||||
|
||||
GCancellable* cancellable;
|
||||
};
|
||||
|
||||
static void fl_key_embedder_responder_dispose(GObject* object);
|
||||
@ -203,17 +156,23 @@ static void fl_key_embedder_responder_class_init(
|
||||
}
|
||||
|
||||
// Initializes an FlKeyEmbedderResponder instance.
|
||||
static void fl_key_embedder_responder_init(FlKeyEmbedderResponder* self) {}
|
||||
static void fl_key_embedder_responder_init(FlKeyEmbedderResponder* self) {
|
||||
self->cancellable = g_cancellable_new();
|
||||
}
|
||||
|
||||
// Disposes of an FlKeyEmbedderResponder instance.
|
||||
static void fl_key_embedder_responder_dispose(GObject* object) {
|
||||
FlKeyEmbedderResponder* self = FL_KEY_EMBEDDER_RESPONDER(object);
|
||||
|
||||
g_cancellable_cancel(self->cancellable);
|
||||
|
||||
g_weak_ref_clear(&self->engine);
|
||||
g_clear_pointer(&self->pressing_records, g_hash_table_unref);
|
||||
g_clear_pointer(&self->mapping_records, g_hash_table_unref);
|
||||
g_clear_pointer(&self->modifier_bit_to_checked_keys, g_hash_table_unref);
|
||||
g_clear_pointer(&self->lock_bit_to_checked_keys, g_hash_table_unref);
|
||||
g_clear_pointer(&self->logical_key_to_lock_bit, g_hash_table_unref);
|
||||
g_clear_object(&self->cancellable);
|
||||
|
||||
G_OBJECT_CLASS(fl_key_embedder_responder_parent_class)->dispose(object);
|
||||
}
|
||||
@ -234,14 +193,11 @@ static void initialize_logical_key_to_lock_bit_loop_body(gpointer lock_bit,
|
||||
}
|
||||
|
||||
// Creates a new FlKeyEmbedderResponder instance.
|
||||
FlKeyEmbedderResponder* fl_key_embedder_responder_new(
|
||||
EmbedderSendKeyEvent send_key_event,
|
||||
void* send_key_event_user_data) {
|
||||
FlKeyEmbedderResponder* fl_key_embedder_responder_new(FlEngine* engine) {
|
||||
FlKeyEmbedderResponder* self = FL_KEY_EMBEDDER_RESPONDER(
|
||||
g_object_new(fl_key_embedder_responder_get_type(), nullptr));
|
||||
|
||||
self->send_key_event = send_key_event;
|
||||
self->send_key_event_user_data = send_key_event_user_data;
|
||||
g_weak_ref_init(&self->engine, engine);
|
||||
|
||||
self->pressing_records = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
self->mapping_records = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
@ -311,16 +267,6 @@ static char* event_to_character(FlKeyEvent* event) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Handles a response from the embedder API to a key event sent to the framework
|
||||
// earlier.
|
||||
static void handle_response(bool handled, gpointer user_data) {
|
||||
g_autoptr(FlKeyEmbedderUserData) data = FL_KEY_EMBEDDER_USER_DATA(user_data);
|
||||
|
||||
g_return_if_fail(data->callback != nullptr);
|
||||
|
||||
data->callback(handled, data->user_data);
|
||||
}
|
||||
|
||||
// Sends a synthesized event to the framework with no demand for callback.
|
||||
static void synthesize_simple_event(FlKeyEmbedderResponder* self,
|
||||
FlutterKeyEventType type,
|
||||
@ -336,8 +282,11 @@ static void synthesize_simple_event(FlKeyEmbedderResponder* self,
|
||||
out_event.character = nullptr;
|
||||
out_event.synthesized = true;
|
||||
self->sent_any_events = true;
|
||||
self->send_key_event(&out_event, nullptr, nullptr,
|
||||
self->send_key_event_user_data);
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine != nullptr) {
|
||||
fl_engine_send_key_event(engine, &out_event, self->cancellable, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -750,13 +699,9 @@ static void fl_key_embedder_responder_handle_event_impl(
|
||||
FlKeyEmbedderResponder* responder,
|
||||
FlKeyEvent* event,
|
||||
uint64_t specified_logical_key,
|
||||
FlKeyEmbedderResponderAsyncCallback callback,
|
||||
gpointer user_data) {
|
||||
GTask* task) {
|
||||
FlKeyEmbedderResponder* self = FL_KEY_EMBEDDER_RESPONDER(responder);
|
||||
|
||||
g_return_if_fail(event != nullptr);
|
||||
g_return_if_fail(callback != nullptr);
|
||||
|
||||
const uint64_t logical_key = specified_logical_key != 0
|
||||
? specified_logical_key
|
||||
: event_to_logical_key(event);
|
||||
@ -811,7 +756,9 @@ static void fl_key_embedder_responder_handle_event_impl(
|
||||
// The physical key has been released before. It might indicate a missed
|
||||
// event due to loss of focus, or multiple keyboards pressed keys with the
|
||||
// same physical key. Ignore the up event.
|
||||
callback(true, user_data);
|
||||
gboolean* return_value = g_new0(gboolean, 1);
|
||||
*return_value = TRUE;
|
||||
g_task_return_pointer(task, return_value, g_free);
|
||||
return;
|
||||
} else {
|
||||
out_event.type = kFlutterKeyEventTypeUp;
|
||||
@ -825,41 +772,85 @@ static void fl_key_embedder_responder_handle_event_impl(
|
||||
if (is_down_event) {
|
||||
update_mapping_record(self, physical_key, logical_key);
|
||||
}
|
||||
FlKeyEmbedderUserData* response_data =
|
||||
fl_key_embedder_user_data_new(callback, user_data);
|
||||
self->sent_any_events = true;
|
||||
self->send_key_event(&out_event, handle_response, response_data,
|
||||
self->send_key_event_user_data);
|
||||
}
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine != nullptr) {
|
||||
fl_engine_send_key_event(
|
||||
engine, &out_event, self->cancellable,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
g_autoptr(GTask) task = G_TASK(user_data);
|
||||
|
||||
void fl_key_embedder_responder_handle_event(
|
||||
FlKeyEmbedderResponder* self,
|
||||
FlKeyEvent* event,
|
||||
uint64_t specified_logical_key,
|
||||
FlKeyEmbedderResponderAsyncCallback callback,
|
||||
gpointer user_data) {
|
||||
self->sent_any_events = false;
|
||||
fl_key_embedder_responder_handle_event_impl(
|
||||
self, event, specified_logical_key, callback, user_data);
|
||||
if (!self->sent_any_events) {
|
||||
self->send_key_event(&kEmptyEvent, nullptr, nullptr,
|
||||
self->send_key_event_user_data);
|
||||
gboolean handled;
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!fl_engine_send_key_event_finish(FL_ENGINE(object), result,
|
||||
&handled, &error)) {
|
||||
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
return;
|
||||
}
|
||||
g_warning("Failed to handle key event: %s", error->message);
|
||||
handled = FALSE;
|
||||
}
|
||||
|
||||
gboolean* return_value = g_new0(gboolean, 1);
|
||||
*return_value = handled;
|
||||
g_task_return_pointer(task, return_value, g_free);
|
||||
},
|
||||
g_object_ref(task));
|
||||
}
|
||||
}
|
||||
|
||||
void fl_key_embedder_responder_handle_event(FlKeyEmbedderResponder* self,
|
||||
FlKeyEvent* event,
|
||||
uint64_t specified_logical_key,
|
||||
GCancellable* cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data) {
|
||||
g_autoptr(GTask) task = g_task_new(self, cancellable, callback, user_data);
|
||||
|
||||
self->sent_any_events = false;
|
||||
fl_key_embedder_responder_handle_event_impl(self, event,
|
||||
specified_logical_key, task);
|
||||
if (!self->sent_any_events) {
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine != nullptr) {
|
||||
fl_engine_send_key_event(engine, &kEmptyEvent, self->cancellable, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean fl_key_embedder_responder_handle_event_finish(
|
||||
FlKeyEmbedderResponder* self,
|
||||
GAsyncResult* result,
|
||||
gboolean* handled,
|
||||
GError** error) {
|
||||
g_return_val_if_fail(g_task_is_valid(result, self), FALSE);
|
||||
|
||||
g_autofree gboolean* return_value =
|
||||
static_cast<gboolean*>(g_task_propagate_pointer(G_TASK(result), error));
|
||||
if (return_value == nullptr) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*handled = *return_value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void fl_key_embedder_responder_sync_modifiers_if_needed(
|
||||
FlKeyEmbedderResponder* responder,
|
||||
FlKeyEmbedderResponder* self,
|
||||
guint state,
|
||||
double event_time) {
|
||||
g_return_if_fail(FL_IS_KEY_EMBEDDER_RESPONDER(self));
|
||||
|
||||
const double timestamp = event_time * kMicrosecondsPerMillisecond;
|
||||
|
||||
SyncStateLoopContext sync_state_context;
|
||||
sync_state_context.self = responder;
|
||||
sync_state_context.self = self;
|
||||
sync_state_context.state = state;
|
||||
sync_state_context.timestamp = timestamp;
|
||||
|
||||
// Update pressing states.
|
||||
g_hash_table_foreach(responder->modifier_bit_to_checked_keys,
|
||||
g_hash_table_foreach(self->modifier_bit_to_checked_keys,
|
||||
synchronize_pressed_states_loop_body,
|
||||
&sync_state_context);
|
||||
}
|
||||
|
@ -8,34 +8,6 @@
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_key_event.h"
|
||||
|
||||
// The signature of a function that FlKeyEmbedderResponder calls on every key
|
||||
// event.
|
||||
//
|
||||
// The `user_data` is opaque data managed by the object that creates
|
||||
// FlKeyEmbedderResponder, and is registered along with this callback
|
||||
// via `fl_key_embedder_responder_new`.
|
||||
//
|
||||
// The `callback_user_data` is opaque data managed by FlKeyEmbedderResponder.
|
||||
// Instances of the EmbedderSendKeyEvent callback are required to invoke
|
||||
// `callback` with the `callback_user_data` parameter after the `event` has been
|
||||
// processed.
|
||||
typedef void (*EmbedderSendKeyEvent)(const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
void* send_key_event_user_data);
|
||||
|
||||
/**
|
||||
* FlKeyEmbedderResponderAsyncCallback:
|
||||
* @event: whether the event has been handled.
|
||||
* @user_data: the same value as user_data sent by
|
||||
* #fl_key_responder_handle_event.
|
||||
*
|
||||
* The signature for a callback with which a #FlKeyEmbedderResponder
|
||||
*asynchronously reports whether the responder handles the event.
|
||||
**/
|
||||
typedef void (*FlKeyEmbedderResponderAsyncCallback)(bool handled,
|
||||
gpointer user_data);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(FlKeyEmbedderResponder,
|
||||
@ -59,16 +31,10 @@ G_DECLARE_FINAL_TYPE(FlKeyEmbedderResponder,
|
||||
* the event.
|
||||
*
|
||||
* Creates a new #FlKeyEmbedderResponder.
|
||||
* @send_key_event: a function that is called on every key event.
|
||||
* @send_key_event_user_data: an opaque pointer that will be sent back as the
|
||||
* last argument of send_key_event, created and managed by the object that holds
|
||||
* FlKeyEmbedderResponder.
|
||||
*
|
||||
* Returns: a new #FlKeyEmbedderResponder.
|
||||
*/
|
||||
FlKeyEmbedderResponder* fl_key_embedder_responder_new(
|
||||
EmbedderSendKeyEvent send_key_event,
|
||||
void* send_key_event_user_data);
|
||||
FlKeyEmbedderResponder* fl_key_embedder_responder_new(FlEngine* engine);
|
||||
|
||||
/**
|
||||
* fl_key_embedder_responder_handle_event:
|
||||
@ -76,21 +42,38 @@ FlKeyEmbedderResponder* fl_key_embedder_responder_new(
|
||||
* @event: the event to be handled. Must not be null. The object is managed by
|
||||
* callee and must not be assumed available after this function.
|
||||
* @specified_logical_key:
|
||||
* @callback: the callback to report the result. It should be called exactly
|
||||
* once. Must not be null.
|
||||
* @user_data: a value that will be sent back in the callback. Can be null.
|
||||
* @cancellable: (allow-none): a #GCancellable or %NULL.
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the view is
|
||||
* added.
|
||||
* @user_data: (closure): user data to pass to @callback.
|
||||
*
|
||||
* Let the responder handle an event, expecting the responder to report
|
||||
* whether to handle the event. The result will be reported by invoking
|
||||
* `callback` exactly once, which might happen after
|
||||
* `fl_key_embedder_responder_handle_event` or during it.
|
||||
* Let the responder handle an event, expecting the responder to report whether
|
||||
* to handle the event.
|
||||
*/
|
||||
void fl_key_embedder_responder_handle_event(
|
||||
void fl_key_embedder_responder_handle_event(FlKeyEmbedderResponder* responder,
|
||||
FlKeyEvent* event,
|
||||
uint64_t specified_logical_key,
|
||||
GCancellable* cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* fl_key_embedder_responder_handle_event_finish:
|
||||
* @responder: an #FlKeyEmbedderResponder.
|
||||
* @result: a #GAsyncResult.
|
||||
* @handled: location to write if this event was handled by the embedder.
|
||||
* @error: (allow-none): #GError location to store the error occurring, or %NULL
|
||||
* to ignore.
|
||||
*
|
||||
* Completes request started with fl_key_embedder_responder_handle_event().
|
||||
*
|
||||
* Returns %TRUE on success.
|
||||
*/
|
||||
gboolean fl_key_embedder_responder_handle_event_finish(
|
||||
FlKeyEmbedderResponder* responder,
|
||||
FlKeyEvent* event,
|
||||
uint64_t specified_logical_key,
|
||||
FlKeyEmbedderResponderAsyncCallback callback,
|
||||
gpointer user_data);
|
||||
GAsyncResult* result,
|
||||
gboolean* handled,
|
||||
GError** error);
|
||||
|
||||
/**
|
||||
* fl_key_embedder_responder_sync_modifiers_if_needed:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
||||
#include "flutter/shell/platform/linux/fl_keyboard_handler.h"
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_keyboard_channel.h"
|
||||
#include "flutter/shell/platform/linux/key_mapping.h"
|
||||
|
||||
struct _FlKeyboardHandler {
|
||||
GObject parent_instance;
|
||||
@ -29,8 +30,8 @@ static FlValue* get_keyboard_state(gpointer user_data) {
|
||||
g_hash_table_foreach(
|
||||
pressing_records,
|
||||
[](gpointer key, gpointer value, gpointer user_data) {
|
||||
int64_t physical_key = reinterpret_cast<int64_t>(key);
|
||||
int64_t logical_key = reinterpret_cast<int64_t>(value);
|
||||
int64_t physical_key = gpointer_to_uint64(key);
|
||||
int64_t logical_key = gpointer_to_uint64(value);
|
||||
FlValue* fl_value_map = reinterpret_cast<FlValue*>(user_data);
|
||||
|
||||
fl_value_set_take(fl_value_map, fl_value_new_int(physical_key),
|
||||
@ -66,9 +67,8 @@ FlKeyboardHandler* fl_keyboard_handler_new(
|
||||
g_object_new(fl_keyboard_handler_get_type(), nullptr));
|
||||
|
||||
self->keyboard_manager = FL_KEYBOARD_MANAGER(g_object_ref(keyboard_manager));
|
||||
|
||||
// Setup the flutter/keyboard channel.
|
||||
self->channel =
|
||||
fl_keyboard_channel_new(messenger, &keyboard_channel_vtable, self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -4,40 +4,69 @@
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_keyboard_handler.h"
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
|
||||
#include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
|
||||
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/fl_method_codec_private.h"
|
||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
|
||||
#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
|
||||
#include "flutter/shell/platform/linux/testing/mock_keymap.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
static constexpr char kKeyboardChannelName[] = "flutter/keyboard";
|
||||
static constexpr char kGetKeyboardStateMethod[] = "getKeyboardState";
|
||||
static constexpr uint64_t kMockPhysicalKey = 42;
|
||||
static constexpr uint64_t kMockLogicalKey = 42;
|
||||
|
||||
using ::flutter::testing::keycodes::kLogicalKeyA;
|
||||
using ::flutter::testing::keycodes::kPhysicalKeyA;
|
||||
|
||||
constexpr guint16 kKeyCodeKeyA = 0x26u;
|
||||
|
||||
TEST(FlKeyboardHandlerTest, KeyboardChannelGetPressedState) {
|
||||
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
|
||||
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_get_pressed_state_handler(
|
||||
manager,
|
||||
[](gpointer user_data) {
|
||||
GHashTable* result = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
g_hash_table_insert(result,
|
||||
reinterpret_cast<gpointer>(kMockPhysicalKey),
|
||||
reinterpret_cast<gpointer>(kMockLogicalKey));
|
||||
|
||||
return result;
|
||||
},
|
||||
nullptr);
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
g_autoptr(FlKeyboardHandler) handler =
|
||||
fl_keyboard_handler_new(FL_BINARY_MESSENGER(messenger), manager);
|
||||
EXPECT_NE(handler, nullptr);
|
||||
|
||||
// Send key event to set pressed state.
|
||||
fl_mock_binary_messenger_set_json_message_channel(
|
||||
messenger, "flutter/keyevent",
|
||||
[](FlMockBinaryMessenger* messenger, GTask* task, FlValue* message,
|
||||
gpointer user_data) {
|
||||
FlValue* response = fl_value_new_map();
|
||||
fl_value_set_string_take(response, "handled", fl_value_new_bool(FALSE));
|
||||
return response;
|
||||
},
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(false, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
g_autoptr(FlKeyEvent) redispatched_event = nullptr;
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, &redispatched_event, nullptr));
|
||||
g_main_loop_quit(static_cast<GMainLoop*>(user_data));
|
||||
},
|
||||
loop);
|
||||
g_main_loop_run(loop);
|
||||
|
||||
gboolean called = FALSE;
|
||||
fl_mock_binary_messenger_invoke_standard_method(
|
||||
messenger, kKeyboardChannelName, kGetKeyboardStateMethod, nullptr,
|
||||
@ -49,14 +78,13 @@ TEST(FlKeyboardHandlerTest, KeyboardChannelGetPressedState) {
|
||||
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
|
||||
|
||||
g_autoptr(FlValue) expected_result = fl_value_new_map();
|
||||
fl_value_set_take(expected_result, fl_value_new_int(kMockPhysicalKey),
|
||||
fl_value_new_int(kMockLogicalKey));
|
||||
fl_value_set_take(expected_result, fl_value_new_int(kPhysicalKeyA),
|
||||
fl_value_new_int(kLogicalKeyA));
|
||||
EXPECT_TRUE(fl_value_equal(fl_method_success_response_get_result(
|
||||
FL_METHOD_SUCCESS_RESPONSE(response)),
|
||||
expected_result));
|
||||
},
|
||||
&called);
|
||||
EXPECT_TRUE(called);
|
||||
|
||||
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
||||
EXPECT_TRUE(called);
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#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_layout.h"
|
||||
@ -84,17 +83,9 @@ static void handle_event_data_free(HandleEventData* data) {
|
||||
struct _FlKeyboardManager {
|
||||
GObject parent_instance;
|
||||
|
||||
GWeakRef engine;
|
||||
|
||||
FlKeyboardManagerSendKeyEventHandler send_key_event_handler;
|
||||
gpointer send_key_event_handler_user_data;
|
||||
|
||||
FlKeyboardManagerLookupKeyHandler lookup_key_handler;
|
||||
gpointer lookup_key_handler_user_data;
|
||||
|
||||
FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler;
|
||||
gpointer get_pressed_state_handler_user_data;
|
||||
|
||||
// Key events that have been redispatched.
|
||||
GPtrArray* redispatched_key_events;
|
||||
|
||||
@ -166,14 +157,25 @@ static void complete_handle_event(FlKeyboardManager* self, GTask* task) {
|
||||
g_task_return_boolean(task, TRUE);
|
||||
}
|
||||
|
||||
static void responder_handle_embedder_event_callback(bool handled,
|
||||
gpointer user_data) {
|
||||
static void responder_handle_embedder_event_cb(GObject* object,
|
||||
GAsyncResult* result,
|
||||
gpointer user_data) {
|
||||
g_autoptr(GTask) task = G_TASK(user_data);
|
||||
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(g_task_get_source_object(task));
|
||||
|
||||
HandleEventData* data =
|
||||
static_cast<HandleEventData*>(g_task_get_task_data(G_TASK(task)));
|
||||
data->embedder_responded = TRUE;
|
||||
|
||||
g_autoptr(GError) error = nullptr;
|
||||
gboolean handled;
|
||||
if (!fl_key_embedder_responder_handle_event_finish(
|
||||
FL_KEY_EMBEDDER_RESPONDER(object), result, &handled, &error)) {
|
||||
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
g_warning("Failed to handle key event in embedder: %s", error->message);
|
||||
}
|
||||
handled = FALSE;
|
||||
}
|
||||
if (handled) {
|
||||
data->handled = TRUE;
|
||||
}
|
||||
@ -309,8 +311,6 @@ static void fl_keyboard_manager_dispose(GObject* object) {
|
||||
|
||||
g_cancellable_cancel(self->cancellable);
|
||||
|
||||
g_weak_ref_clear(&self->engine);
|
||||
|
||||
self->keycode_to_goals.reset();
|
||||
self->logical_to_mandatory_goals.reset();
|
||||
|
||||
@ -357,51 +357,7 @@ FlKeyboardManager* fl_keyboard_manager_new(FlEngine* engine) {
|
||||
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(
|
||||
g_object_new(fl_keyboard_manager_get_type(), nullptr));
|
||||
|
||||
g_weak_ref_init(&self->engine, engine);
|
||||
|
||||
self->key_embedder_responder = fl_key_embedder_responder_new(
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, void* send_key_event_user_data) {
|
||||
FlKeyboardManager* self = FL_KEYBOARD_MANAGER(send_key_event_user_data);
|
||||
if (self->send_key_event_handler != nullptr) {
|
||||
self->send_key_event_handler(event, callback, callback_user_data,
|
||||
self->send_key_event_handler_user_data);
|
||||
} else {
|
||||
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
|
||||
if (engine != nullptr) {
|
||||
typedef struct {
|
||||
FlutterKeyEventCallback callback;
|
||||
void* callback_user_data;
|
||||
} SendKeyEventData;
|
||||
SendKeyEventData* data = g_new0(SendKeyEventData, 1);
|
||||
data->callback = callback;
|
||||
data->callback_user_data = callback_user_data;
|
||||
fl_engine_send_key_event(
|
||||
engine, event, self->cancellable,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
g_autofree SendKeyEventData* data =
|
||||
static_cast<SendKeyEventData*>(user_data);
|
||||
gboolean handled = FALSE;
|
||||
g_autoptr(GError) error = nullptr;
|
||||
if (!fl_engine_send_key_event_finish(
|
||||
FL_ENGINE(object), result, &handled, &error)) {
|
||||
if (g_error_matches(error, G_IO_ERROR,
|
||||
G_IO_ERROR_CANCELLED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_warning("Failed to send key event: %s", error->message);
|
||||
}
|
||||
|
||||
if (data->callback != nullptr) {
|
||||
data->callback(handled, data->callback_user_data);
|
||||
}
|
||||
},
|
||||
data);
|
||||
}
|
||||
}
|
||||
},
|
||||
self);
|
||||
self->key_embedder_responder = fl_key_embedder_responder_new(engine);
|
||||
self->key_channel_responder =
|
||||
fl_key_channel_responder_new(fl_engine_get_binary_messenger(engine));
|
||||
|
||||
@ -444,7 +400,8 @@ void fl_keyboard_manager_handle_event(FlKeyboardManager* self,
|
||||
fl_key_event_get_keycode(event));
|
||||
fl_key_embedder_responder_handle_event(
|
||||
self->key_embedder_responder, event, specified_logical_key,
|
||||
responder_handle_embedder_event_callback, g_object_ref(task));
|
||||
self->cancellable, responder_handle_embedder_event_cb,
|
||||
g_object_ref(task));
|
||||
fl_key_channel_responder_handle_event(
|
||||
self->key_channel_responder, event, specified_logical_key,
|
||||
self->cancellable, responder_handle_channel_event_cb, g_object_ref(task));
|
||||
@ -477,22 +434,8 @@ void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager* self,
|
||||
|
||||
GHashTable* fl_keyboard_manager_get_pressed_state(FlKeyboardManager* self) {
|
||||
g_return_val_if_fail(FL_IS_KEYBOARD_MANAGER(self), nullptr);
|
||||
if (self->get_pressed_state_handler != nullptr) {
|
||||
return self->get_pressed_state_handler(
|
||||
self->get_pressed_state_handler_user_data);
|
||||
} else {
|
||||
return fl_key_embedder_responder_get_pressed_state(
|
||||
self->key_embedder_responder);
|
||||
}
|
||||
}
|
||||
|
||||
void fl_keyboard_manager_set_send_key_event_handler(
|
||||
FlKeyboardManager* self,
|
||||
FlKeyboardManagerSendKeyEventHandler send_key_event_handler,
|
||||
gpointer user_data) {
|
||||
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
|
||||
self->send_key_event_handler = send_key_event_handler;
|
||||
self->send_key_event_handler_user_data = user_data;
|
||||
return fl_key_embedder_responder_get_pressed_state(
|
||||
self->key_embedder_responder);
|
||||
}
|
||||
|
||||
void fl_keyboard_manager_set_lookup_key_handler(
|
||||
@ -503,12 +446,3 @@ void fl_keyboard_manager_set_lookup_key_handler(
|
||||
self->lookup_key_handler = lookup_key_handler;
|
||||
self->lookup_key_handler_user_data = user_data;
|
||||
}
|
||||
|
||||
void fl_keyboard_manager_set_get_pressed_state_handler(
|
||||
FlKeyboardManager* self,
|
||||
FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler,
|
||||
gpointer user_data) {
|
||||
g_return_if_fail(FL_IS_KEYBOARD_MANAGER(self));
|
||||
self->get_pressed_state_handler = get_pressed_state_handler;
|
||||
self->get_pressed_state_handler_user_data = user_data;
|
||||
}
|
||||
|
@ -115,23 +115,6 @@ void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager* manager,
|
||||
*/
|
||||
GHashTable* fl_keyboard_manager_get_pressed_state(FlKeyboardManager* manager);
|
||||
|
||||
typedef void (*FlKeyboardManagerSendKeyEventHandler)(
|
||||
const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* fl_keyboard_manager_set_send_key_event_handler:
|
||||
* @manager: the #FlKeyboardManager self.
|
||||
*
|
||||
* Set the handler for sending events, for testing purposes only.
|
||||
*/
|
||||
void fl_keyboard_manager_set_send_key_event_handler(
|
||||
FlKeyboardManager* manager,
|
||||
FlKeyboardManagerSendKeyEventHandler send_key_event_handler,
|
||||
gpointer user_data);
|
||||
|
||||
typedef guint (*FlKeyboardManagerLookupKeyHandler)(const GdkKeymapKey* key,
|
||||
gpointer user_data);
|
||||
|
||||
@ -146,20 +129,6 @@ void fl_keyboard_manager_set_lookup_key_handler(
|
||||
FlKeyboardManagerLookupKeyHandler lookup_key_handler,
|
||||
gpointer user_data);
|
||||
|
||||
typedef GHashTable* (*FlKeyboardManagerGetPressedStateHandler)(
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* fl_keyboard_manager_set_get_pressed_state_handler:
|
||||
* @manager: the #FlKeyboardManager self.
|
||||
*
|
||||
* Set the handler for gettting the keyboard state, for testing purposes only.
|
||||
*/
|
||||
void fl_keyboard_manager_set_get_pressed_state_handler(
|
||||
FlKeyboardManager* manager,
|
||||
FlKeyboardManagerGetPressedStateHandler get_pressed_state_handler,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_KEYBOARD_MANAGER_H_
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
|
||||
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
|
||||
#include "flutter/shell/platform/linux/fl_engine_private.h"
|
||||
#include "flutter/shell/platform/linux/key_mapping.h"
|
||||
#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
|
||||
@ -15,16 +16,6 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// Define compound `expect` in macros. If they were defined in functions, the
|
||||
// stacktrace wouldn't print where the function is called in the unit tests.
|
||||
|
||||
#define EXPECT_KEY_EVENT(RECORD, TYPE, PHYSICAL, LOGICAL, CHAR, SYNTHESIZED) \
|
||||
EXPECT_EQ((RECORD)->event_type, (TYPE)); \
|
||||
EXPECT_EQ((RECORD)->event_physical, (PHYSICAL)); \
|
||||
EXPECT_EQ((RECORD)->event_logical, (LOGICAL)); \
|
||||
EXPECT_STREQ((RECORD)->event_character, (CHAR)); \
|
||||
EXPECT_EQ((RECORD)->event_synthesized, (SYNTHESIZED));
|
||||
|
||||
#define VERIFY_DOWN(OUT_LOGICAL, OUT_CHAR) \
|
||||
EXPECT_EQ(static_cast<CallRecord*>(g_ptr_array_index(call_records, 0)) \
|
||||
->event_type, \
|
||||
@ -134,16 +125,16 @@ TEST(FlKeyboardManagerTest, EngineNoResponseChannelHandled) {
|
||||
nullptr);
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Don't handle first event - async call never completes.
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {},
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback,
|
||||
void* user_data) { return kSuccess; }));
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
gboolean first_event_completed = FALSE;
|
||||
@ -156,12 +147,12 @@ TEST(FlKeyboardManagerTest, EngineNoResponseChannelHandled) {
|
||||
&first_event_completed);
|
||||
|
||||
// Handle second event.
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
gpointer user_data) { callback(true, callback_user_data); },
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(true, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
g_autoptr(FlKeyEvent) event2 = fl_key_event_new(
|
||||
0, FALSE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
|
||||
@ -188,12 +179,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledSync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls synchronously.
|
||||
fl_mock_binary_messenger_set_json_message_channel(
|
||||
@ -206,12 +195,12 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledSync) {
|
||||
return fl_value_ref(return_value);
|
||||
},
|
||||
nullptr);
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
gpointer user_data) { callback(true, callback_user_data); },
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(true, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -235,12 +224,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledSync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls synchronously.
|
||||
fl_mock_binary_messenger_set_json_message_channel(
|
||||
@ -253,12 +240,12 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledSync) {
|
||||
return fl_value_ref(return_value);
|
||||
},
|
||||
nullptr);
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
gpointer user_data) { callback(false, callback_user_data); },
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(false, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -282,12 +269,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledSync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls synchronously.
|
||||
fl_mock_binary_messenger_set_json_message_channel(
|
||||
@ -300,12 +285,12 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledSync) {
|
||||
return fl_value_ref(return_value);
|
||||
},
|
||||
nullptr);
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
gpointer user_data) { callback(true, callback_user_data); },
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(true, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -329,12 +314,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledSync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls synchronously.
|
||||
fl_mock_binary_messenger_set_json_message_channel(
|
||||
@ -347,12 +330,12 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledSync) {
|
||||
return fl_value_ref(return_value);
|
||||
},
|
||||
nullptr);
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data,
|
||||
gpointer user_data) { callback(false, callback_user_data); },
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(false, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -384,12 +367,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledAsync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls asynchronously.
|
||||
g_autoptr(GPtrArray) channel_calls =
|
||||
@ -406,15 +387,14 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelNotHandledAsync) {
|
||||
channel_calls);
|
||||
g_autoptr(GPtrArray) embedder_call_records = g_ptr_array_new_with_free_func(
|
||||
reinterpret_cast<GDestroyNotify>(call_record_free));
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {
|
||||
GPtrArray* call_records = static_cast<GPtrArray*>(user_data);
|
||||
g_ptr_array_add(call_records,
|
||||
call_record_new(event, callback, callback_user_data));
|
||||
},
|
||||
embedder_call_records);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([&embedder_call_records](
|
||||
auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
g_ptr_array_add(embedder_call_records,
|
||||
call_record_new(event, callback, user_data));
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -448,12 +428,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledAsync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls asynchronously.
|
||||
g_autoptr(GPtrArray) channel_calls =
|
||||
@ -470,15 +448,14 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelHandledAsync) {
|
||||
channel_calls);
|
||||
g_autoptr(GPtrArray) embedder_call_records = g_ptr_array_new_with_free_func(
|
||||
reinterpret_cast<GDestroyNotify>(call_record_free));
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {
|
||||
GPtrArray* call_records = static_cast<GPtrArray*>(user_data);
|
||||
g_ptr_array_add(call_records,
|
||||
call_record_new(event, callback, callback_user_data));
|
||||
},
|
||||
embedder_call_records);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([&embedder_call_records](
|
||||
auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
g_ptr_array_add(embedder_call_records,
|
||||
call_record_new(event, callback, user_data));
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -512,12 +489,10 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledAsync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls asynchronously.
|
||||
g_autoptr(GPtrArray) channel_calls =
|
||||
@ -534,15 +509,14 @@ TEST(FlKeyboardManagerTest, EngineHandledChannelHandledAsync) {
|
||||
channel_calls);
|
||||
g_autoptr(GPtrArray) embedder_call_records = g_ptr_array_new_with_free_func(
|
||||
reinterpret_cast<GDestroyNotify>(call_record_free));
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {
|
||||
GPtrArray* call_records = static_cast<GPtrArray*>(user_data);
|
||||
g_ptr_array_add(call_records,
|
||||
call_record_new(event, callback, callback_user_data));
|
||||
},
|
||||
embedder_call_records);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([&embedder_call_records](
|
||||
auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
g_ptr_array_add(embedder_call_records,
|
||||
call_record_new(event, callback, user_data));
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -576,12 +550,10 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledAsync) {
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Handle channel and embedder calls asynchronously.
|
||||
g_autoptr(GPtrArray) channel_calls =
|
||||
@ -598,15 +570,14 @@ TEST(FlKeyboardManagerTest, EngineNotHandledChannelNotHandledAsync) {
|
||||
channel_calls);
|
||||
g_autoptr(GPtrArray) embedder_call_records = g_ptr_array_new_with_free_func(
|
||||
reinterpret_cast<GDestroyNotify>(call_record_free));
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {
|
||||
GPtrArray* call_records = static_cast<GPtrArray*>(user_data);
|
||||
g_ptr_array_add(call_records,
|
||||
call_record_new(event, callback, callback_user_data));
|
||||
},
|
||||
embedder_call_records);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([&embedder_call_records](
|
||||
auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
g_ptr_array_add(embedder_call_records,
|
||||
call_record_new(event, callback, user_data));
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
@ -641,20 +612,18 @@ TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
|
||||
g_autoptr(FlEngine) engine = fl_engine_new(project);
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
g_autoptr(GPtrArray) call_records = g_ptr_array_new_with_free_func(
|
||||
reinterpret_cast<GDestroyNotify>(call_record_free));
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {
|
||||
GPtrArray* call_records = static_cast<GPtrArray*>(user_data);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent,
|
||||
([&call_records](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
g_ptr_array_add(call_records,
|
||||
call_record_new(event, callback, callback_user_data));
|
||||
},
|
||||
call_records);
|
||||
fl_keyboard_manager_set_lookup_key_handler(
|
||||
manager, [](const GdkKeymapKey* key, gpointer user_data) { return 0u; },
|
||||
nullptr);
|
||||
call_record_new(event, callback, user_data));
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
auto sendTap = [&](guint8 keycode, guint keyval, guint8 group) {
|
||||
g_autoptr(FlKeyEvent) event1 = fl_key_event_new(
|
||||
@ -776,17 +745,18 @@ TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
|
||||
g_autoptr(FlEngine) engine = fl_engine_new(project);
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
g_autoptr(GPtrArray) call_records = g_ptr_array_new_with_free_func(
|
||||
reinterpret_cast<GDestroyNotify>(call_record_free));
|
||||
fl_keyboard_manager_set_send_key_event_handler(
|
||||
manager,
|
||||
[](const FlutterKeyEvent* event, FlutterKeyEventCallback callback,
|
||||
void* callback_user_data, gpointer user_data) {
|
||||
GPtrArray* call_records = static_cast<GPtrArray*>(user_data);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent,
|
||||
([&call_records](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
g_ptr_array_add(call_records,
|
||||
call_record_new(event, callback, callback_user_data));
|
||||
},
|
||||
call_records);
|
||||
call_record_new(event, callback, user_data));
|
||||
return kSuccess;
|
||||
}));
|
||||
|
||||
auto verifyModifierIsSynthesized = [&](GdkModifierType mask,
|
||||
uint64_t physical, uint64_t logical) {
|
||||
@ -794,16 +764,23 @@ TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
|
||||
guint state = mask;
|
||||
fl_keyboard_manager_sync_modifier_if_needed(manager, state, 1000);
|
||||
EXPECT_EQ(call_records->len, 1u);
|
||||
EXPECT_KEY_EVENT(
|
||||
static_cast<CallRecord*>(g_ptr_array_index(call_records, 0)),
|
||||
kFlutterKeyEventTypeDown, physical, logical, NULL, true);
|
||||
CallRecord* record =
|
||||
static_cast<CallRecord*>(g_ptr_array_index(call_records, 0));
|
||||
EXPECT_EQ(record->event_type, kFlutterKeyEventTypeDown);
|
||||
EXPECT_EQ(record->event_physical, physical);
|
||||
EXPECT_EQ(record->event_logical, logical);
|
||||
EXPECT_STREQ(record->event_character, NULL);
|
||||
EXPECT_EQ(record->event_synthesized, true);
|
||||
// Modifier is released.
|
||||
state = state ^ mask;
|
||||
fl_keyboard_manager_sync_modifier_if_needed(manager, state, 1001);
|
||||
EXPECT_EQ(call_records->len, 2u);
|
||||
EXPECT_KEY_EVENT(
|
||||
static_cast<CallRecord*>(g_ptr_array_index(call_records, 1)),
|
||||
kFlutterKeyEventTypeUp, physical, logical, NULL, true);
|
||||
record = static_cast<CallRecord*>(g_ptr_array_index(call_records, 1));
|
||||
EXPECT_EQ(record->event_type, kFlutterKeyEventTypeUp);
|
||||
EXPECT_EQ(record->event_physical, physical);
|
||||
EXPECT_EQ(record->event_logical, logical);
|
||||
EXPECT_STREQ(record->event_character, NULL);
|
||||
EXPECT_EQ(record->event_synthesized, true);
|
||||
g_ptr_array_set_size(call_records, 0);
|
||||
};
|
||||
|
||||
@ -826,27 +803,49 @@ TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
|
||||
TEST(FlKeyboardManagerTest, GetPressedState) {
|
||||
::testing::NiceMock<flutter::testing::MockKeymap> mock_keymap;
|
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||
g_autoptr(FlEngine) engine = fl_engine_new(project);
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
g_autoptr(FlEngine) engine =
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(engine);
|
||||
|
||||
EXPECT_TRUE(fl_engine_start(engine, nullptr));
|
||||
|
||||
// Dispatch a key event.
|
||||
fl_mock_binary_messenger_set_json_message_channel(
|
||||
messenger, "flutter/keyevent",
|
||||
[](FlMockBinaryMessenger* messenger, GTask* task, FlValue* message,
|
||||
gpointer user_data) {
|
||||
FlValue* response = fl_value_new_map();
|
||||
fl_value_set_string_take(response, "handled", fl_value_new_bool(FALSE));
|
||||
return response;
|
||||
},
|
||||
nullptr);
|
||||
fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
|
||||
SendKeyEvent, ([](auto engine, const FlutterKeyEvent* event,
|
||||
FlutterKeyEventCallback callback, void* user_data) {
|
||||
callback(false, user_data);
|
||||
return kSuccess;
|
||||
}));
|
||||
g_autoptr(FlKeyEvent) event = fl_key_event_new(
|
||||
0, TRUE, kKeyCodeKeyA, GDK_KEY_a, static_cast<GdkModifierType>(0), 0);
|
||||
g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
|
||||
fl_keyboard_manager_handle_event(
|
||||
manager, event, nullptr,
|
||||
[](GObject* object, GAsyncResult* result, gpointer user_data) {
|
||||
g_autoptr(FlKeyEvent) redispatched_event = nullptr;
|
||||
EXPECT_TRUE(fl_keyboard_manager_handle_event_finish(
|
||||
FL_KEYBOARD_MANAGER(object), result, &redispatched_event, nullptr));
|
||||
EXPECT_NE(redispatched_event, nullptr);
|
||||
g_main_loop_quit(static_cast<GMainLoop*>(user_data));
|
||||
},
|
||||
nullptr);
|
||||
loop);
|
||||
g_main_loop_run(loop);
|
||||
|
||||
GHashTable* pressedState = fl_keyboard_manager_get_pressed_state(manager);
|
||||
EXPECT_EQ(g_hash_table_size(pressedState), 1u);
|
||||
GHashTable* pressed_state = fl_keyboard_manager_get_pressed_state(manager);
|
||||
EXPECT_EQ(g_hash_table_size(pressed_state), 1u);
|
||||
|
||||
gpointer physical_key =
|
||||
g_hash_table_lookup(pressedState, uint64_to_gpointer(kPhysicalKeyA));
|
||||
g_hash_table_lookup(pressed_state, uint64_to_gpointer(kPhysicalKeyA));
|
||||
EXPECT_EQ(gpointer_to_uint64(physical_key), kLogicalKeyA);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,7 @@ TEST(FlSettingsHandlerTest, AlwaysUse24HourFormat) {
|
||||
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlSettingsHandler) handler = fl_settings_handler_new(engine);
|
||||
|
||||
EXPECT_CALL(settings, fl_settings_get_clock_format(
|
||||
@ -78,8 +77,7 @@ TEST(FlSettingsHandlerTest, PlatformBrightness) {
|
||||
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlSettingsHandler) handler = fl_settings_handler_new(engine);
|
||||
|
||||
EXPECT_CALL(settings, fl_settings_get_color_scheme(
|
||||
@ -135,8 +133,7 @@ TEST(FlSettingsHandlerTest, TextScaleFactor) {
|
||||
|
||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||
g_autoptr(FlEngine) engine =
|
||||
FL_ENGINE(g_object_new(fl_engine_get_type(), "binary-messenger",
|
||||
FL_BINARY_MESSENGER(messenger), nullptr));
|
||||
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
|
||||
g_autoptr(FlSettingsHandler) handler = fl_settings_handler_new(engine);
|
||||
|
||||
EXPECT_CALL(settings, fl_settings_get_text_scaling_factor(
|
||||
|
Loading…
x
Reference in New Issue
Block a user