Move FlTextInputHandler from FlView (#162131)
This moves the final part of the keyboard handling from FlView to the FlEngine and means keyboard should work correctly with multiple views.
This commit is contained in:
parent
a7c6cc19a3
commit
4cc9db4125
@ -43908,8 +43908,6 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_channel.h + ../../..
|
|||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_handler.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_handler.cc + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_handler.h + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_handler.h + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_handler_test.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_handler_test.cc + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_view_delegate.cc + ../../../flutter/LICENSE
|
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_text_input_view_delegate.h + ../../../flutter/LICENSE
|
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_texture.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/linux/fl_texture.cc + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_texture_gl.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/linux/fl_texture_gl.cc + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h + ../../../flutter/LICENSE
|
||||||
@ -46910,8 +46908,6 @@ FILE: ../../../flutter/shell/platform/linux/fl_text_input_channel.h
|
|||||||
FILE: ../../../flutter/shell/platform/linux/fl_text_input_handler.cc
|
FILE: ../../../flutter/shell/platform/linux/fl_text_input_handler.cc
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_text_input_handler.h
|
FILE: ../../../flutter/shell/platform/linux/fl_text_input_handler.h
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_text_input_handler_test.cc
|
FILE: ../../../flutter/shell/platform/linux/fl_text_input_handler_test.cc
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_text_input_view_delegate.cc
|
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_text_input_view_delegate.h
|
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_texture.cc
|
FILE: ../../../flutter/shell/platform/linux/fl_texture.cc
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl.cc
|
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl.cc
|
||||||
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h
|
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h
|
||||||
|
@ -150,7 +150,6 @@ source_set("flutter_linux_sources") {
|
|||||||
"fl_task_runner.h",
|
"fl_task_runner.h",
|
||||||
"fl_text_input_channel.cc",
|
"fl_text_input_channel.cc",
|
||||||
"fl_text_input_handler.cc",
|
"fl_text_input_handler.cc",
|
||||||
"fl_text_input_view_delegate.cc",
|
|
||||||
"fl_texture.cc",
|
"fl_texture.cc",
|
||||||
"fl_texture_gl.cc",
|
"fl_texture_gl.cc",
|
||||||
"fl_texture_registrar.cc",
|
"fl_texture_registrar.cc",
|
||||||
@ -262,7 +261,6 @@ executable("flutter_linux_unittests") {
|
|||||||
"testing/mock_renderer.cc",
|
"testing/mock_renderer.cc",
|
||||||
"testing/mock_settings.cc",
|
"testing/mock_settings.cc",
|
||||||
"testing/mock_signal_handler.cc",
|
"testing/mock_signal_handler.cc",
|
||||||
"testing/mock_text_input_view_delegate.cc",
|
|
||||||
"testing/mock_texture_registrar.cc",
|
"testing/mock_texture_registrar.cc",
|
||||||
"testing/mock_window.cc",
|
"testing/mock_window.cc",
|
||||||
]
|
]
|
||||||
|
@ -61,6 +61,9 @@ struct _FlEngine {
|
|||||||
// Process keyboard events.
|
// Process keyboard events.
|
||||||
FlKeyboardManager* keyboard_manager;
|
FlKeyboardManager* keyboard_manager;
|
||||||
|
|
||||||
|
// Implements the flutter/textinput channel.
|
||||||
|
FlTextInputHandler* text_input_handler;
|
||||||
|
|
||||||
// Implements the flutter/keyboard channel.
|
// Implements the flutter/keyboard channel.
|
||||||
FlKeyboardHandler* keyboard_handler;
|
FlKeyboardHandler* keyboard_handler;
|
||||||
|
|
||||||
@ -391,9 +394,20 @@ static void fl_engine_update_semantics_cb(const FlutterSemanticsUpdate2* update,
|
|||||||
static void setup_keyboard(FlEngine* self) {
|
static void setup_keyboard(FlEngine* self) {
|
||||||
g_clear_object(&self->keyboard_manager);
|
g_clear_object(&self->keyboard_manager);
|
||||||
self->keyboard_manager = fl_keyboard_manager_new(self);
|
self->keyboard_manager = fl_keyboard_manager_new(self);
|
||||||
|
|
||||||
g_clear_object(&self->keyboard_handler);
|
g_clear_object(&self->keyboard_handler);
|
||||||
self->keyboard_handler =
|
self->keyboard_handler =
|
||||||
fl_keyboard_handler_new(self->binary_messenger, self->keyboard_manager);
|
fl_keyboard_handler_new(self->binary_messenger, self->keyboard_manager);
|
||||||
|
|
||||||
|
GtkWidget* widget =
|
||||||
|
self->text_input_handler != nullptr
|
||||||
|
? fl_text_input_handler_get_widget(self->text_input_handler)
|
||||||
|
: nullptr;
|
||||||
|
g_clear_object(&self->text_input_handler);
|
||||||
|
self->text_input_handler = fl_text_input_handler_new(self->binary_messenger);
|
||||||
|
if (widget != nullptr) {
|
||||||
|
fl_text_input_handler_set_widget(self->text_input_handler, widget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called right before the engine is restarted.
|
// Called right before the engine is restarted.
|
||||||
@ -474,6 +488,7 @@ static void fl_engine_dispose(GObject* object) {
|
|||||||
g_clear_object(&self->settings_handler);
|
g_clear_object(&self->settings_handler);
|
||||||
g_clear_object(&self->platform_handler);
|
g_clear_object(&self->platform_handler);
|
||||||
g_clear_object(&self->keyboard_manager);
|
g_clear_object(&self->keyboard_manager);
|
||||||
|
g_clear_object(&self->text_input_handler);
|
||||||
g_clear_object(&self->keyboard_handler);
|
g_clear_object(&self->keyboard_handler);
|
||||||
g_clear_object(&self->mouse_cursor_handler);
|
g_clear_object(&self->mouse_cursor_handler);
|
||||||
g_clear_object(&self->task_runner);
|
g_clear_object(&self->task_runner);
|
||||||
@ -1285,6 +1300,11 @@ FlKeyboardManager* fl_engine_get_keyboard_manager(FlEngine* self) {
|
|||||||
return self->keyboard_manager;
|
return self->keyboard_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlTextInputHandler* fl_engine_get_text_input_handler(FlEngine* self) {
|
||||||
|
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
|
||||||
|
return self->text_input_handler;
|
||||||
|
}
|
||||||
|
|
||||||
FlMouseCursorHandler* fl_engine_get_mouse_cursor_handler(FlEngine* self) {
|
FlMouseCursorHandler* fl_engine_get_mouse_cursor_handler(FlEngine* self) {
|
||||||
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
|
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
|
||||||
return self->mouse_cursor_handler;
|
return self->mouse_cursor_handler;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h"
|
#include "flutter/shell/platform/linux/fl_mouse_cursor_handler.h"
|
||||||
#include "flutter/shell/platform/linux/fl_renderer.h"
|
#include "flutter/shell/platform/linux/fl_renderer.h"
|
||||||
#include "flutter/shell/platform/linux/fl_task_runner.h"
|
#include "flutter/shell/platform/linux/fl_task_runner.h"
|
||||||
|
#include "flutter/shell/platform/linux/fl_text_input_handler.h"
|
||||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h"
|
#include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h"
|
||||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
|
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
|
||||||
|
|
||||||
@ -585,6 +586,16 @@ void fl_engine_request_app_exit(FlEngine* engine);
|
|||||||
*/
|
*/
|
||||||
FlKeyboardManager* fl_engine_get_keyboard_manager(FlEngine* engine);
|
FlKeyboardManager* fl_engine_get_keyboard_manager(FlEngine* engine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fl_engine_get_text_input_handler:
|
||||||
|
* @engine: an #FlEngine.
|
||||||
|
*
|
||||||
|
* Gets the text input handler used by this engine.
|
||||||
|
*
|
||||||
|
* Returns: a #FlTextInputHandler.
|
||||||
|
*/
|
||||||
|
FlTextInputHandler* fl_engine_get_text_input_handler(FlEngine* engine);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fl_engine_get_mouse_cursor_handler:
|
* fl_engine_get_mouse_cursor_handler:
|
||||||
* @engine: an #FlEngine.
|
* @engine: an #FlEngine.
|
||||||
|
@ -19,6 +19,9 @@ struct _FlTextInputHandler {
|
|||||||
|
|
||||||
FlTextInputChannel* channel;
|
FlTextInputChannel* channel;
|
||||||
|
|
||||||
|
// The widget with input focus.
|
||||||
|
GtkWidget* widget;
|
||||||
|
|
||||||
// Client ID provided by Flutter to report events with.
|
// Client ID provided by Flutter to report events with.
|
||||||
int64_t client_id;
|
int64_t client_id;
|
||||||
|
|
||||||
@ -37,8 +40,6 @@ struct _FlTextInputHandler {
|
|||||||
// Input method.
|
// Input method.
|
||||||
GtkIMContext* im_context;
|
GtkIMContext* im_context;
|
||||||
|
|
||||||
GWeakRef view_delegate;
|
|
||||||
|
|
||||||
flutter::TextInputModel* text_model;
|
flutter::TextInputModel* text_model;
|
||||||
|
|
||||||
// A 4x4 matrix that maps from `EditableText` local coordinates to the
|
// A 4x4 matrix that maps from `EditableText` local coordinates to the
|
||||||
@ -316,12 +317,6 @@ static void clear_client(gpointer user_data) {
|
|||||||
// after each of these updates. It transforms the composing rect to GDK window
|
// after each of these updates. It transforms the composing rect to GDK window
|
||||||
// coordinates and notifies GTK of the updated cursor position.
|
// coordinates and notifies GTK of the updated cursor position.
|
||||||
static void update_im_cursor_position(FlTextInputHandler* self) {
|
static void update_im_cursor_position(FlTextInputHandler* self) {
|
||||||
g_autoptr(FlTextInputViewDelegate) view_delegate =
|
|
||||||
FL_TEXT_INPUT_VIEW_DELEGATE(g_weak_ref_get(&self->view_delegate));
|
|
||||||
if (view_delegate == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip update if not composing to avoid setting to position 0.
|
// Skip update if not composing to avoid setting to position 0.
|
||||||
if (!self->text_model->composing()) {
|
if (!self->text_model->composing()) {
|
||||||
return;
|
return;
|
||||||
@ -338,8 +333,9 @@ static void update_im_cursor_position(FlTextInputHandler* self) {
|
|||||||
|
|
||||||
// Transform from Flutter view coordinates to GTK window coordinates.
|
// Transform from Flutter view coordinates to GTK window coordinates.
|
||||||
GdkRectangle preedit_rect = {};
|
GdkRectangle preedit_rect = {};
|
||||||
fl_text_input_view_delegate_translate_coordinates(
|
gtk_widget_translate_coordinates(self->widget,
|
||||||
view_delegate, x, y, &preedit_rect.x, &preedit_rect.y);
|
gtk_widget_get_toplevel(self->widget), x, y,
|
||||||
|
&preedit_rect.x, &preedit_rect.y);
|
||||||
|
|
||||||
// Set the cursor location in window coordinates so that GTK can position
|
// Set the cursor location in window coordinates so that GTK can position
|
||||||
// any system input method windows.
|
// any system input method windows.
|
||||||
@ -395,7 +391,6 @@ static void fl_text_input_handler_dispose(GObject* object) {
|
|||||||
delete self->text_model;
|
delete self->text_model;
|
||||||
self->text_model = nullptr;
|
self->text_model = nullptr;
|
||||||
}
|
}
|
||||||
g_weak_ref_clear(&self->view_delegate);
|
|
||||||
g_clear_object(&self->cancellable);
|
g_clear_object(&self->cancellable);
|
||||||
|
|
||||||
G_OBJECT_CLASS(fl_text_input_handler_parent_class)->dispose(object);
|
G_OBJECT_CLASS(fl_text_input_handler_parent_class)->dispose(object);
|
||||||
@ -414,9 +409,26 @@ static void fl_text_input_handler_init(FlTextInputHandler* self) {
|
|||||||
self->cancellable = g_cancellable_new();
|
self->cancellable = g_cancellable_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_im_context(FlTextInputHandler* self,
|
static FlTextInputChannelVTable text_input_vtable = {
|
||||||
GtkIMContext* im_context) {
|
.set_client = set_client,
|
||||||
self->im_context = GTK_IM_CONTEXT(g_object_ref(im_context));
|
.hide = hide,
|
||||||
|
.show = show,
|
||||||
|
.set_editing_state = set_editing_state,
|
||||||
|
.clear_client = clear_client,
|
||||||
|
.set_editable_size_and_transform = set_editable_size_and_transform,
|
||||||
|
.set_marked_text_rect = set_marked_text_rect,
|
||||||
|
};
|
||||||
|
|
||||||
|
FlTextInputHandler* fl_text_input_handler_new(FlBinaryMessenger* messenger) {
|
||||||
|
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
|
||||||
|
|
||||||
|
FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(
|
||||||
|
g_object_new(fl_text_input_handler_get_type(), nullptr));
|
||||||
|
|
||||||
|
self->channel =
|
||||||
|
fl_text_input_channel_new(messenger, &text_input_vtable, self);
|
||||||
|
|
||||||
|
self->im_context = GTK_IM_CONTEXT(gtk_im_multicontext_new());
|
||||||
|
|
||||||
// On Wayland, this call sets up the input method so it can be enabled
|
// On Wayland, this call sets up the input method so it can be enabled
|
||||||
// immediately when required. Without it, on-screen keyboard's don't come up
|
// immediately when required. Without it, on-screen keyboard's don't come up
|
||||||
@ -440,39 +452,28 @@ static void init_im_context(FlTextInputHandler* self,
|
|||||||
g_signal_connect_object(self->im_context, "delete-surrounding",
|
g_signal_connect_object(self->im_context, "delete-surrounding",
|
||||||
G_CALLBACK(im_delete_surrounding_cb), self,
|
G_CALLBACK(im_delete_surrounding_cb), self,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
}
|
|
||||||
|
|
||||||
static FlTextInputChannelVTable text_input_vtable = {
|
|
||||||
.set_client = set_client,
|
|
||||||
.hide = hide,
|
|
||||||
.show = show,
|
|
||||||
.set_editing_state = set_editing_state,
|
|
||||||
.clear_client = clear_client,
|
|
||||||
.set_editable_size_and_transform = set_editable_size_and_transform,
|
|
||||||
.set_marked_text_rect = set_marked_text_rect,
|
|
||||||
};
|
|
||||||
|
|
||||||
FlTextInputHandler* fl_text_input_handler_new(
|
|
||||||
FlBinaryMessenger* messenger,
|
|
||||||
GtkIMContext* im_context,
|
|
||||||
FlTextInputViewDelegate* view_delegate) {
|
|
||||||
g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
|
|
||||||
g_return_val_if_fail(GTK_IS_IM_CONTEXT(im_context), nullptr);
|
|
||||||
g_return_val_if_fail(FL_IS_TEXT_INPUT_VIEW_DELEGATE(view_delegate), nullptr);
|
|
||||||
|
|
||||||
FlTextInputHandler* self = FL_TEXT_INPUT_HANDLER(
|
|
||||||
g_object_new(fl_text_input_handler_get_type(), nullptr));
|
|
||||||
|
|
||||||
self->channel =
|
|
||||||
fl_text_input_channel_new(messenger, &text_input_vtable, self);
|
|
||||||
|
|
||||||
init_im_context(self, im_context);
|
|
||||||
|
|
||||||
g_weak_ref_init(&self->view_delegate, view_delegate);
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkIMContext* fl_text_input_handler_get_im_context(FlTextInputHandler* self) {
|
||||||
|
g_return_val_if_fail(FL_IS_TEXT_INPUT_HANDLER(self), nullptr);
|
||||||
|
return self->im_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fl_text_input_handler_set_widget(FlTextInputHandler* self,
|
||||||
|
GtkWidget* widget) {
|
||||||
|
g_return_if_fail(FL_IS_TEXT_INPUT_HANDLER(self));
|
||||||
|
self->widget = widget;
|
||||||
|
gtk_im_context_set_client_window(self->im_context,
|
||||||
|
gtk_widget_get_window(self->widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget* fl_text_input_handler_get_widget(FlTextInputHandler* self) {
|
||||||
|
g_return_val_if_fail(FL_IS_TEXT_INPUT_HANDLER(self), nullptr);
|
||||||
|
return self->widget;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean fl_text_input_handler_filter_keypress(FlTextInputHandler* self,
|
gboolean fl_text_input_handler_filter_keypress(FlTextInputHandler* self,
|
||||||
FlKeyEvent* event) {
|
FlKeyEvent* event) {
|
||||||
g_return_val_if_fail(FL_IS_TEXT_INPUT_HANDLER(self), FALSE);
|
g_return_val_if_fail(FL_IS_TEXT_INPUT_HANDLER(self), FALSE);
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#include "flutter/shell/platform/linux/fl_key_event.h"
|
#include "flutter/shell/platform/linux/fl_key_event.h"
|
||||||
#include "flutter/shell/platform/linux/fl_text_input_view_delegate.h"
|
|
||||||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
|
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@ -29,25 +28,50 @@ G_DECLARE_FINAL_TYPE(FlTextInputHandler,
|
|||||||
/**
|
/**
|
||||||
* fl_text_input_handler_new:
|
* fl_text_input_handler_new:
|
||||||
* @messenger: an #FlBinaryMessenger.
|
* @messenger: an #FlBinaryMessenger.
|
||||||
* @im_context: (allow-none): a #GtkIMContext.
|
|
||||||
* @view_delegate: an #FlTextInputViewDelegate.
|
|
||||||
*
|
*
|
||||||
* Creates a new handler that implements SystemChannels.textInput from the
|
* Creates a new handler that implements SystemChannels.textInput from the
|
||||||
* Flutter services library.
|
* Flutter services library.
|
||||||
*
|
*
|
||||||
* Returns: a new #FlTextInputHandler.
|
* Returns: a new #FlTextInputHandler.
|
||||||
*/
|
*/
|
||||||
FlTextInputHandler* fl_text_input_handler_new(
|
FlTextInputHandler* fl_text_input_handler_new(FlBinaryMessenger* messenger);
|
||||||
FlBinaryMessenger* messenger,
|
|
||||||
GtkIMContext* im_context,
|
/**
|
||||||
FlTextInputViewDelegate* view_delegate);
|
* fl_text_input_handler_get_im_context:
|
||||||
|
* @handler: an #FlTextInputHandler.
|
||||||
|
*
|
||||||
|
* Get the IM context that is being used. Provided for testing purposes.
|
||||||
|
*
|
||||||
|
* Returns: a #GtkIMContext.
|
||||||
|
*/
|
||||||
|
GtkIMContext* fl_text_input_handler_get_im_context(FlTextInputHandler* handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fl_text_input_handler_set_widget:
|
||||||
|
* @handler: an #FlTextInputHandler.
|
||||||
|
* @widget: the widget with keyboard focus.
|
||||||
|
*
|
||||||
|
* Set the widget that has input focus.
|
||||||
|
*/
|
||||||
|
void fl_text_input_handler_set_widget(FlTextInputHandler* handler,
|
||||||
|
GtkWidget* widget);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fl_text_input_handler_get_widget:
|
||||||
|
* @handler: an #FlTextInputHandler.
|
||||||
|
*
|
||||||
|
* Get the widget that has input focus.
|
||||||
|
*
|
||||||
|
* Returns: a #GtkWidget or %NULL if none active.
|
||||||
|
*/
|
||||||
|
GtkWidget* fl_text_input_handler_get_widget(FlTextInputHandler* handler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fl_text_input_handler_filter_keypress
|
* fl_text_input_handler_filter_keypress
|
||||||
* @handler: an #FlTextInputHandler.
|
* @handler: an #FlTextInputHandler.
|
||||||
* @event: a #FlKeyEvent
|
* @event: a #FlKeyEvent
|
||||||
*
|
*
|
||||||
* Process a Gdk key event.
|
* Process a key event.
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if the event was used.
|
* Returns: %TRUE if the event was used.
|
||||||
*/
|
*/
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
|
#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
|
||||||
#include "flutter/shell/platform/linux/testing/fl_test.h"
|
#include "flutter/shell/platform/linux/testing/fl_test.h"
|
||||||
#include "flutter/shell/platform/linux/testing/mock_im_context.h"
|
#include "flutter/shell/platform/linux/testing/mock_im_context.h"
|
||||||
#include "flutter/shell/platform/linux/testing/mock_text_input_view_delegate.h"
|
|
||||||
#include "flutter/testing/testing.h"
|
#include "flutter/testing/testing.h"
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
@ -154,10 +153,9 @@ static void send_key_event(FlTextInputHandler* handler,
|
|||||||
TEST(FlTextInputHandlerTest, MessageHandler) {
|
TEST(FlTextInputHandlerTest, MessageHandler) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
EXPECT_TRUE(
|
EXPECT_TRUE(
|
||||||
@ -169,10 +167,9 @@ TEST(FlTextInputHandlerTest, MessageHandler) {
|
|||||||
TEST(FlTextInputHandlerTest, SetClient) {
|
TEST(FlTextInputHandlerTest, SetClient) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {.client_id = 1});
|
set_client(messenger, {.client_id = 1});
|
||||||
@ -183,14 +180,12 @@ TEST(FlTextInputHandlerTest, SetClient) {
|
|||||||
TEST(FlTextInputHandlerTest, Show) {
|
TEST(FlTextInputHandlerTest, Show) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(context,
|
EXPECT_CALL(context, gtk_im_context_focus_in);
|
||||||
gtk_im_context_focus_in(::testing::Eq<GtkIMContext*>(context)));
|
|
||||||
|
|
||||||
gboolean called = FALSE;
|
gboolean called = FALSE;
|
||||||
fl_mock_binary_messenger_invoke_json_method(
|
fl_mock_binary_messenger_invoke_json_method(
|
||||||
@ -216,14 +211,12 @@ TEST(FlTextInputHandlerTest, Show) {
|
|||||||
TEST(FlTextInputHandlerTest, Hide) {
|
TEST(FlTextInputHandlerTest, Hide) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
EXPECT_CALL(context,
|
EXPECT_CALL(context, gtk_im_context_focus_out);
|
||||||
gtk_im_context_focus_out(::testing::Eq<GtkIMContext*>(context)));
|
|
||||||
|
|
||||||
gboolean called = FALSE;
|
gboolean called = FALSE;
|
||||||
fl_mock_binary_messenger_invoke_json_method(
|
fl_mock_binary_messenger_invoke_json_method(
|
||||||
@ -249,10 +242,9 @@ TEST(FlTextInputHandlerTest, Hide) {
|
|||||||
TEST(FlTextInputHandlerTest, ClearClient) {
|
TEST(FlTextInputHandlerTest, ClearClient) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
gboolean called = FALSE;
|
gboolean called = FALSE;
|
||||||
@ -279,10 +271,9 @@ TEST(FlTextInputHandlerTest, ClearClient) {
|
|||||||
TEST(FlTextInputHandlerTest, PerformAction) {
|
TEST(FlTextInputHandlerTest, PerformAction) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {
|
set_client(messenger, {
|
||||||
@ -340,10 +331,9 @@ TEST(FlTextInputHandlerTest, PerformAction) {
|
|||||||
TEST(FlTextInputHandlerTest, MultilineWithSendAction) {
|
TEST(FlTextInputHandlerTest, MultilineWithSendAction) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {
|
set_client(messenger, {
|
||||||
@ -399,10 +389,9 @@ TEST(FlTextInputHandlerTest, MultilineWithSendAction) {
|
|||||||
TEST(FlTextInputHandlerTest, MoveCursor) {
|
TEST(FlTextInputHandlerTest, MoveCursor) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {.client_id = 1});
|
set_client(messenger, {.client_id = 1});
|
||||||
@ -465,10 +454,9 @@ TEST(FlTextInputHandlerTest, MoveCursor) {
|
|||||||
TEST(FlTextInputHandlerTest, Select) {
|
TEST(FlTextInputHandlerTest, Select) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {.client_id = 1});
|
set_client(messenger, {.client_id = 1});
|
||||||
@ -531,17 +519,15 @@ TEST(FlTextInputHandlerTest, Select) {
|
|||||||
TEST(FlTextInputHandlerTest, Composing) {
|
TEST(FlTextInputHandlerTest, Composing) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
EXPECT_CALL(context,
|
EXPECT_CALL(context, gtk_im_context_get_preedit_string(
|
||||||
gtk_im_context_get_preedit_string(
|
::testing::_, ::testing::A<gchar**>(), ::testing::_,
|
||||||
::testing::Eq<GtkIMContext*>(context),
|
::testing::A<gint*>()))
|
||||||
::testing::A<gchar**>(), ::testing::_, ::testing::A<gint*>()))
|
|
||||||
.WillOnce(
|
.WillOnce(
|
||||||
::testing::DoAll(::testing::SetArgPointee<1>(g_strdup("Flutter")),
|
::testing::DoAll(::testing::SetArgPointee<1>(g_strdup("Flutter")),
|
||||||
::testing::SetArgPointee<3>(0)));
|
::testing::SetArgPointee<3>(0)));
|
||||||
@ -601,10 +587,14 @@ TEST(FlTextInputHandlerTest, Composing) {
|
|||||||
},
|
},
|
||||||
&call_count);
|
&call_count);
|
||||||
|
|
||||||
g_signal_emit_by_name(context, "preedit-start", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
g_signal_emit_by_name(context, "preedit-changed", nullptr);
|
"preedit-start", nullptr);
|
||||||
g_signal_emit_by_name(context, "commit", "engine", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
g_signal_emit_by_name(context, "preedit-end", nullptr);
|
"preedit-changed", nullptr);
|
||||||
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
|
"engine", nullptr);
|
||||||
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
|
"preedit-end", nullptr);
|
||||||
EXPECT_EQ(call_count, 3);
|
EXPECT_EQ(call_count, 3);
|
||||||
|
|
||||||
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
||||||
@ -613,10 +603,9 @@ TEST(FlTextInputHandlerTest, Composing) {
|
|||||||
TEST(FlTextInputHandlerTest, SurroundingText) {
|
TEST(FlTextInputHandlerTest, SurroundingText) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {.client_id = 1});
|
set_client(messenger, {.client_id = 1});
|
||||||
@ -628,11 +617,11 @@ TEST(FlTextInputHandlerTest, SurroundingText) {
|
|||||||
|
|
||||||
// retrieve
|
// retrieve
|
||||||
EXPECT_CALL(context, gtk_im_context_set_surrounding(
|
EXPECT_CALL(context, gtk_im_context_set_surrounding(
|
||||||
::testing::Eq<GtkIMContext*>(context),
|
::testing::_, ::testing::StrEq("Flutter"), -1, 3));
|
||||||
::testing::StrEq("Flutter"), 7, 3));
|
|
||||||
|
|
||||||
gboolean retrieved = false;
|
gboolean retrieved = false;
|
||||||
g_signal_emit_by_name(context, "retrieve-surrounding", &retrieved, nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
|
"retrieve-surrounding", &retrieved, nullptr);
|
||||||
EXPECT_TRUE(retrieved);
|
EXPECT_TRUE(retrieved);
|
||||||
|
|
||||||
int call_count = 0;
|
int call_count = 0;
|
||||||
@ -668,7 +657,8 @@ TEST(FlTextInputHandlerTest, SurroundingText) {
|
|||||||
&call_count);
|
&call_count);
|
||||||
|
|
||||||
gboolean deleted = false;
|
gboolean deleted = false;
|
||||||
g_signal_emit_by_name(context, "delete-surrounding", 1, 2, &deleted, nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
|
"delete-surrounding", 1, 2, &deleted, nullptr);
|
||||||
EXPECT_TRUE(deleted);
|
EXPECT_TRUE(deleted);
|
||||||
EXPECT_EQ(call_count, 1);
|
EXPECT_EQ(call_count, 1);
|
||||||
|
|
||||||
@ -678,13 +668,13 @@ TEST(FlTextInputHandlerTest, SurroundingText) {
|
|||||||
TEST(FlTextInputHandlerTest, SetMarkedTextRect) {
|
TEST(FlTextInputHandlerTest, SetMarkedTextRect) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
g_signal_emit_by_name(context, "preedit-start", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
|
"preedit-start", nullptr);
|
||||||
|
|
||||||
// set editable size and transform
|
// set editable size and transform
|
||||||
g_autoptr(FlValue) size_and_transform = build_map({
|
g_autoptr(FlValue) size_and_transform = build_map({
|
||||||
@ -729,15 +719,15 @@ TEST(FlTextInputHandlerTest, SetMarkedTextRect) {
|
|||||||
&called);
|
&called);
|
||||||
EXPECT_TRUE(called);
|
EXPECT_TRUE(called);
|
||||||
|
|
||||||
EXPECT_CALL(delegate, fl_text_input_view_delegate_translate_coordinates(
|
EXPECT_CALL(context, gtk_widget_translate_coordinates(
|
||||||
::testing::Eq<FlTextInputViewDelegate*>(delegate),
|
::testing::_, ::testing::_, ::testing::Eq(27),
|
||||||
::testing::Eq(27), ::testing::Eq(32), ::testing::_,
|
::testing::Eq(32), ::testing::_, ::testing::_))
|
||||||
::testing::_))
|
.WillOnce(::testing::DoAll(::testing::SetArgPointee<4>(123),
|
||||||
.WillOnce(::testing::DoAll(::testing::SetArgPointee<3>(123),
|
::testing::SetArgPointee<5>(456),
|
||||||
::testing::SetArgPointee<4>(456)));
|
::testing::Return(true)));
|
||||||
|
|
||||||
EXPECT_CALL(context, gtk_im_context_set_cursor_location(
|
EXPECT_CALL(context, gtk_im_context_set_cursor_location(
|
||||||
::testing::Eq<GtkIMContext*>(context),
|
::testing::_,
|
||||||
::testing::Pointee(::testing::AllOf(
|
::testing::Pointee(::testing::AllOf(
|
||||||
::testing::Field(&GdkRectangle::x, 123),
|
::testing::Field(&GdkRectangle::x, 123),
|
||||||
::testing::Field(&GdkRectangle::y, 456),
|
::testing::Field(&GdkRectangle::y, 456),
|
||||||
@ -775,10 +765,9 @@ TEST(FlTextInputHandlerTest, SetMarkedTextRect) {
|
|||||||
TEST(FlTextInputHandlerTest, TextInputTypeNone) {
|
TEST(FlTextInputHandlerTest, TextInputTypeNone) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {
|
set_client(messenger, {
|
||||||
@ -786,11 +775,8 @@ TEST(FlTextInputHandlerTest, TextInputTypeNone) {
|
|||||||
.input_type = "TextInputType.none",
|
.input_type = "TextInputType.none",
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_CALL(context,
|
EXPECT_CALL(context, gtk_im_context_focus_in).Times(0);
|
||||||
gtk_im_context_focus_in(::testing::Eq<GtkIMContext*>(context)))
|
EXPECT_CALL(context, gtk_im_context_focus_out);
|
||||||
.Times(0);
|
|
||||||
EXPECT_CALL(context,
|
|
||||||
gtk_im_context_focus_out(::testing::Eq<GtkIMContext*>(context)));
|
|
||||||
|
|
||||||
gboolean called = FALSE;
|
gboolean called = FALSE;
|
||||||
fl_mock_binary_messenger_invoke_json_method(
|
fl_mock_binary_messenger_invoke_json_method(
|
||||||
@ -816,10 +802,9 @@ TEST(FlTextInputHandlerTest, TextInputTypeNone) {
|
|||||||
TEST(FlTextInputHandlerTest, TextEditingDelta) {
|
TEST(FlTextInputHandlerTest, TextEditingDelta) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
set_client(messenger, {
|
set_client(messenger, {
|
||||||
@ -881,10 +866,9 @@ TEST(FlTextInputHandlerTest, TextEditingDelta) {
|
|||||||
TEST(FlTextInputHandlerTest, ComposingDelta) {
|
TEST(FlTextInputHandlerTest, ComposingDelta) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
// set config
|
// set config
|
||||||
@ -893,13 +877,13 @@ TEST(FlTextInputHandlerTest, ComposingDelta) {
|
|||||||
.enable_delta_model = true,
|
.enable_delta_model = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
g_signal_emit_by_name(context, "preedit-start", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
|
"preedit-start", nullptr);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
EXPECT_CALL(context,
|
EXPECT_CALL(context, gtk_im_context_get_preedit_string(
|
||||||
gtk_im_context_get_preedit_string(
|
::testing::_, ::testing::A<gchar**>(), ::testing::_,
|
||||||
::testing::Eq<GtkIMContext*>(context),
|
::testing::A<gint*>()))
|
||||||
::testing::A<gchar**>(), ::testing::_, ::testing::A<gint*>()))
|
|
||||||
.WillOnce(
|
.WillOnce(
|
||||||
::testing::DoAll(::testing::SetArgPointee<1>(g_strdup("Flutter ")),
|
::testing::DoAll(::testing::SetArgPointee<1>(g_strdup("Flutter ")),
|
||||||
::testing::SetArgPointee<3>(8)));
|
::testing::SetArgPointee<3>(8)));
|
||||||
@ -982,9 +966,12 @@ TEST(FlTextInputHandlerTest, ComposingDelta) {
|
|||||||
},
|
},
|
||||||
&call_count);
|
&call_count);
|
||||||
|
|
||||||
g_signal_emit_by_name(context, "preedit-changed", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
g_signal_emit_by_name(context, "commit", "Flutter engine", nullptr);
|
"preedit-changed", nullptr);
|
||||||
g_signal_emit_by_name(context, "preedit-end", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
|
"Flutter engine", nullptr);
|
||||||
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler),
|
||||||
|
"preedit-end", nullptr);
|
||||||
EXPECT_EQ(call_count, 3);
|
EXPECT_EQ(call_count, 3);
|
||||||
|
|
||||||
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
||||||
@ -993,10 +980,9 @@ TEST(FlTextInputHandlerTest, ComposingDelta) {
|
|||||||
TEST(FlTextInputHandlerTest, NonComposingDelta) {
|
TEST(FlTextInputHandlerTest, NonComposingDelta) {
|
||||||
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
|
||||||
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
::testing::NiceMock<flutter::testing::MockIMContext> context;
|
||||||
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
|
|
||||||
|
|
||||||
g_autoptr(FlTextInputHandler) handler = fl_text_input_handler_new(
|
g_autoptr(FlTextInputHandler) handler =
|
||||||
FL_BINARY_MESSENGER(messenger), context, delegate);
|
fl_text_input_handler_new(FL_BINARY_MESSENGER(messenger));
|
||||||
EXPECT_NE(handler, nullptr);
|
EXPECT_NE(handler, nullptr);
|
||||||
|
|
||||||
// set config
|
// set config
|
||||||
@ -1173,13 +1159,20 @@ TEST(FlTextInputHandlerTest, NonComposingDelta) {
|
|||||||
},
|
},
|
||||||
&call_count);
|
&call_count);
|
||||||
|
|
||||||
g_signal_emit_by_name(context, "commit", "F", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
g_signal_emit_by_name(context, "commit", "l", nullptr);
|
"F", nullptr);
|
||||||
g_signal_emit_by_name(context, "commit", "u", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
g_signal_emit_by_name(context, "commit", "t", nullptr);
|
"l", nullptr);
|
||||||
g_signal_emit_by_name(context, "commit", "t", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
g_signal_emit_by_name(context, "commit", "e", nullptr);
|
"u", nullptr);
|
||||||
g_signal_emit_by_name(context, "commit", "r", nullptr);
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
|
"t", nullptr);
|
||||||
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
|
"t", nullptr);
|
||||||
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
|
"e", nullptr);
|
||||||
|
g_signal_emit_by_name(fl_text_input_handler_get_im_context(handler), "commit",
|
||||||
|
"r", nullptr);
|
||||||
EXPECT_EQ(call_count, 7);
|
EXPECT_EQ(call_count, 7);
|
||||||
|
|
||||||
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "flutter/shell/platform/linux/fl_text_input_view_delegate.h"
|
|
||||||
|
|
||||||
G_DEFINE_INTERFACE(FlTextInputViewDelegate,
|
|
||||||
fl_text_input_view_delegate,
|
|
||||||
G_TYPE_OBJECT)
|
|
||||||
|
|
||||||
static void fl_text_input_view_delegate_default_init(
|
|
||||||
FlTextInputViewDelegateInterface* iface) {}
|
|
||||||
|
|
||||||
void fl_text_input_view_delegate_translate_coordinates(
|
|
||||||
FlTextInputViewDelegate* self,
|
|
||||||
gint view_x,
|
|
||||||
gint view_y,
|
|
||||||
gint* window_x,
|
|
||||||
gint* window_y) {
|
|
||||||
g_return_if_fail(FL_IS_TEXT_INPUT_VIEW_DELEGATE(self));
|
|
||||||
|
|
||||||
FL_TEXT_INPUT_VIEW_DELEGATE_GET_IFACE(self)->translate_coordinates(
|
|
||||||
self, view_x, view_y, window_x, window_y);
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXT_INPUT_VIEW_DELEGATE_H_
|
|
||||||
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXT_INPUT_VIEW_DELEGATE_H_
|
|
||||||
|
|
||||||
#include <gdk/gdk.h>
|
|
||||||
|
|
||||||
#include "flutter/shell/platform/embedder/embedder.h"
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
G_DECLARE_INTERFACE(FlTextInputViewDelegate,
|
|
||||||
fl_text_input_view_delegate,
|
|
||||||
FL,
|
|
||||||
TEXT_INPUT_VIEW_DELEGATE,
|
|
||||||
GObject);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FlTextInputViewDelegate:
|
|
||||||
*
|
|
||||||
* An interface for a class that provides `FlTextInputHandler` with
|
|
||||||
* view-related features.
|
|
||||||
*
|
|
||||||
* This interface is typically implemented by `FlView`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct _FlTextInputViewDelegateInterface {
|
|
||||||
GTypeInterface g_iface;
|
|
||||||
|
|
||||||
void (*translate_coordinates)(FlTextInputViewDelegate* delegate,
|
|
||||||
gint view_x,
|
|
||||||
gint view_y,
|
|
||||||
gint* window_x,
|
|
||||||
gint* window_y);
|
|
||||||
};
|
|
||||||
|
|
||||||
void fl_text_input_view_delegate_translate_coordinates(
|
|
||||||
FlTextInputViewDelegate* delegate,
|
|
||||||
gint view_x,
|
|
||||||
gint view_y,
|
|
||||||
gint* window_x,
|
|
||||||
gint* window_y);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEXT_INPUT_VIEW_DELEGATE_H_
|
|
@ -18,8 +18,6 @@
|
|||||||
#include "flutter/shell/platform/linux/fl_renderer_gdk.h"
|
#include "flutter/shell/platform/linux/fl_renderer_gdk.h"
|
||||||
#include "flutter/shell/platform/linux/fl_scrolling_manager.h"
|
#include "flutter/shell/platform/linux/fl_scrolling_manager.h"
|
||||||
#include "flutter/shell/platform/linux/fl_socket_accessible.h"
|
#include "flutter/shell/platform/linux/fl_socket_accessible.h"
|
||||||
#include "flutter/shell/platform/linux/fl_text_input_handler.h"
|
|
||||||
#include "flutter/shell/platform/linux/fl_text_input_view_delegate.h"
|
|
||||||
#include "flutter/shell/platform/linux/fl_touch_manager.h"
|
#include "flutter/shell/platform/linux/fl_touch_manager.h"
|
||||||
#include "flutter/shell/platform/linux/fl_view_accessible.h"
|
#include "flutter/shell/platform/linux/fl_view_accessible.h"
|
||||||
#include "flutter/shell/platform/linux/fl_window_state_monitor.h"
|
#include "flutter/shell/platform/linux/fl_window_state_monitor.h"
|
||||||
@ -62,9 +60,6 @@ struct _FlView {
|
|||||||
// Manages touch events.
|
// Manages touch events.
|
||||||
FlTouchManager* touch_manager;
|
FlTouchManager* touch_manager;
|
||||||
|
|
||||||
// Flutter system channel handlers.
|
|
||||||
FlTextInputHandler* text_input_handler;
|
|
||||||
|
|
||||||
// Accessible tree from Flutter, exposed as an AtkPlug.
|
// Accessible tree from Flutter, exposed as an AtkPlug.
|
||||||
FlViewAccessible* view_accessible;
|
FlViewAccessible* view_accessible;
|
||||||
|
|
||||||
@ -83,18 +78,13 @@ static void fl_renderable_iface_init(FlRenderableInterface* iface);
|
|||||||
static void fl_view_plugin_registry_iface_init(
|
static void fl_view_plugin_registry_iface_init(
|
||||||
FlPluginRegistryInterface* iface);
|
FlPluginRegistryInterface* iface);
|
||||||
|
|
||||||
static void fl_view_text_input_delegate_iface_init(
|
|
||||||
FlTextInputViewDelegateInterface* iface);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE(
|
G_DEFINE_TYPE_WITH_CODE(
|
||||||
FlView,
|
FlView,
|
||||||
fl_view,
|
fl_view,
|
||||||
GTK_TYPE_BOX,
|
GTK_TYPE_BOX,
|
||||||
G_IMPLEMENT_INTERFACE(fl_renderable_get_type(), fl_renderable_iface_init)
|
G_IMPLEMENT_INTERFACE(fl_renderable_get_type(), fl_renderable_iface_init)
|
||||||
G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(),
|
G_IMPLEMENT_INTERFACE(fl_plugin_registry_get_type(),
|
||||||
fl_view_plugin_registry_iface_init)
|
fl_view_plugin_registry_iface_init))
|
||||||
G_IMPLEMENT_INTERFACE(fl_text_input_view_delegate_get_type(),
|
|
||||||
fl_view_text_input_delegate_iface_init))
|
|
||||||
|
|
||||||
// Emit the first frame signal in the main thread.
|
// Emit the first frame signal in the main thread.
|
||||||
static gboolean first_frame_idle_cb(gpointer user_data) {
|
static gboolean first_frame_idle_cb(gpointer user_data) {
|
||||||
@ -112,21 +102,6 @@ static gboolean window_delete_event_cb(FlView* self) {
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize keyboard.
|
|
||||||
static void init_keyboard(FlView* self) {
|
|
||||||
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
|
|
||||||
|
|
||||||
GdkWindow* window =
|
|
||||||
gtk_widget_get_window(gtk_widget_get_toplevel(GTK_WIDGET(self)));
|
|
||||||
g_return_if_fail(GDK_IS_WINDOW(window));
|
|
||||||
g_autoptr(GtkIMContext) im_context = gtk_im_multicontext_new();
|
|
||||||
gtk_im_context_set_client_window(im_context, window);
|
|
||||||
|
|
||||||
g_clear_object(&self->text_input_handler);
|
|
||||||
self->text_input_handler = fl_text_input_handler_new(
|
|
||||||
messenger, im_context, FL_TEXT_INPUT_VIEW_DELEGATE(self));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_scrolling(FlView* self) {
|
static void init_scrolling(FlView* self) {
|
||||||
g_clear_object(&self->scrolling_manager);
|
g_clear_object(&self->scrolling_manager);
|
||||||
self->scrolling_manager =
|
self->scrolling_manager =
|
||||||
@ -277,7 +252,6 @@ static void update_semantics_cb(FlEngine* engine,
|
|||||||
// which usually indicates the user has requested a hot restart (Shift-R in the
|
// which usually indicates the user has requested a hot restart (Shift-R in the
|
||||||
// Flutter CLI.)
|
// Flutter CLI.)
|
||||||
static void on_pre_engine_restart_cb(FlView* self) {
|
static void on_pre_engine_restart_cb(FlView* self) {
|
||||||
init_keyboard(self);
|
|
||||||
init_scrolling(self);
|
init_scrolling(self);
|
||||||
init_touch(self);
|
init_touch(self);
|
||||||
}
|
}
|
||||||
@ -323,18 +297,6 @@ static void fl_view_plugin_registry_iface_init(
|
|||||||
iface->get_registrar_for_plugin = fl_view_get_registrar_for_plugin;
|
iface->get_registrar_for_plugin = fl_view_get_registrar_for_plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fl_view_text_input_delegate_iface_init(
|
|
||||||
FlTextInputViewDelegateInterface* iface) {
|
|
||||||
iface->translate_coordinates = [](FlTextInputViewDelegate* delegate,
|
|
||||||
gint view_x, gint view_y, gint* window_x,
|
|
||||||
gint* window_y) {
|
|
||||||
FlView* self = FL_VIEW(delegate);
|
|
||||||
gtk_widget_translate_coordinates(GTK_WIDGET(self),
|
|
||||||
gtk_widget_get_toplevel(GTK_WIDGET(self)),
|
|
||||||
view_x, view_y, window_x, window_y);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sync_modifier_if_needed(FlView* self, GdkEvent* event) {
|
static void sync_modifier_if_needed(FlView* self, GdkEvent* event) {
|
||||||
guint event_time = gdk_event_get_time(event);
|
guint event_time = gdk_event_get_time(event);
|
||||||
GdkModifierType event_state = static_cast<GdkModifierType>(0);
|
GdkModifierType event_state = static_cast<GdkModifierType>(0);
|
||||||
@ -534,8 +496,6 @@ static void realize_cb(FlView* self) {
|
|||||||
g_signal_connect_swapped(toplevel_window, "delete-event",
|
g_signal_connect_swapped(toplevel_window, "delete-event",
|
||||||
G_CALLBACK(window_delete_event_cb), self);
|
G_CALLBACK(window_delete_event_cb), self);
|
||||||
|
|
||||||
init_keyboard(self);
|
|
||||||
|
|
||||||
fl_renderer_add_renderable(FL_RENDERER(self->renderer), self->view_id,
|
fl_renderer_add_renderable(FL_RENDERER(self->renderer), self->view_id,
|
||||||
FL_RENDERABLE(self));
|
FL_RENDERABLE(self));
|
||||||
|
|
||||||
@ -674,7 +634,8 @@ static gboolean handle_key_event(FlView* self, GdkEventKey* key_event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (redispatch_event != nullptr) {
|
if (redispatch_event != nullptr) {
|
||||||
if (!fl_text_input_handler_filter_keypress(self->text_input_handler,
|
if (!fl_text_input_handler_filter_keypress(
|
||||||
|
fl_engine_get_text_input_handler(self->engine),
|
||||||
redispatch_event)) {
|
redispatch_event)) {
|
||||||
fl_keyboard_manager_add_redispatched_event(
|
fl_keyboard_manager_add_redispatched_event(
|
||||||
fl_engine_get_keyboard_manager(self->engine), redispatch_event);
|
fl_engine_get_keyboard_manager(self->engine), redispatch_event);
|
||||||
@ -687,6 +648,15 @@ static gboolean handle_key_event(FlView* self, GdkEventKey* key_event) {
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implements GtkWidget::key_press_event.
|
||||||
|
static gboolean fl_view_focus_in_event(GtkWidget* widget,
|
||||||
|
GdkEventFocus* event) {
|
||||||
|
FlView* self = FL_VIEW(widget);
|
||||||
|
fl_text_input_handler_set_widget(
|
||||||
|
fl_engine_get_text_input_handler(self->engine), widget);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// Implements GtkWidget::key_press_event.
|
// Implements GtkWidget::key_press_event.
|
||||||
static gboolean fl_view_key_press_event(GtkWidget* widget,
|
static gboolean fl_view_key_press_event(GtkWidget* widget,
|
||||||
GdkEventKey* key_event) {
|
GdkEventKey* key_event) {
|
||||||
@ -708,6 +678,7 @@ static void fl_view_class_init(FlViewClass* klass) {
|
|||||||
|
|
||||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
||||||
widget_class->realize = fl_view_realize;
|
widget_class->realize = fl_view_realize;
|
||||||
|
widget_class->focus_in_event = fl_view_focus_in_event;
|
||||||
widget_class->key_press_event = fl_view_key_press_event;
|
widget_class->key_press_event = fl_view_key_press_event;
|
||||||
widget_class->key_release_event = fl_view_key_release_event;
|
widget_class->key_release_event = fl_view_key_release_event;
|
||||||
|
|
||||||
|
@ -60,6 +60,12 @@ MockEpoxy::MockEpoxy() {
|
|||||||
mock = this;
|
mock = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockEpoxy::~MockEpoxy() {
|
||||||
|
if (mock == this) {
|
||||||
|
mock = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool check_display(EGLDisplay dpy) {
|
static bool check_display(EGLDisplay dpy) {
|
||||||
if (dpy == nullptr) {
|
if (dpy == nullptr) {
|
||||||
mock_error = EGL_BAD_DISPLAY;
|
mock_error = EGL_BAD_DISPLAY;
|
||||||
|
@ -16,6 +16,7 @@ namespace testing {
|
|||||||
class MockEpoxy {
|
class MockEpoxy {
|
||||||
public:
|
public:
|
||||||
MockEpoxy();
|
MockEpoxy();
|
||||||
|
~MockEpoxy();
|
||||||
|
|
||||||
MOCK_METHOD(bool, epoxy_has_gl_extension, (const char* extension));
|
MOCK_METHOD(bool, epoxy_has_gl_extension, (const char* extension));
|
||||||
MOCK_METHOD(bool, epoxy_is_desktop_gl, ());
|
MOCK_METHOD(bool, epoxy_is_desktop_gl, ());
|
||||||
|
@ -6,116 +6,87 @@
|
|||||||
|
|
||||||
using namespace flutter::testing;
|
using namespace flutter::testing;
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(FlMockIMContext,
|
static MockIMContext* mock = nullptr;
|
||||||
fl_mock_im_context,
|
|
||||||
FL,
|
|
||||||
MOCK_IM_CONTEXT,
|
|
||||||
GtkIMContext)
|
|
||||||
|
|
||||||
struct _FlMockIMContext {
|
MockIMContext::MockIMContext() {
|
||||||
GtkIMContext parent_instance;
|
mock = this;
|
||||||
MockIMContext* mock;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(FlMockIMContext, fl_mock_im_context, GTK_TYPE_IM_CONTEXT)
|
|
||||||
|
|
||||||
static void fl_mock_im_context_set_client_window(GtkIMContext* context,
|
|
||||||
GdkWindow* window) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_set_client_window(context, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_get_preedit_string(GtkIMContext* context,
|
|
||||||
gchar** str,
|
|
||||||
PangoAttrList** attrs,
|
|
||||||
gint* cursor_pos) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_get_preedit_string(context, str, attrs,
|
|
||||||
cursor_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean fl_mock_im_context_filter_keypress(GtkIMContext* context,
|
|
||||||
GdkEventKey* event) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
return self->mock->gtk_im_context_filter_keypress(context, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_focus_in(GtkIMContext* context) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_focus_in(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_focus_out(GtkIMContext* context) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_focus_out(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_reset(GtkIMContext* context) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_reset(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_set_cursor_location(GtkIMContext* context,
|
|
||||||
GdkRectangle* area) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_set_cursor_location(context, area);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_set_use_preedit(GtkIMContext* context,
|
|
||||||
gboolean use_preedit) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_set_use_preedit(context, use_preedit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_set_surrounding(GtkIMContext* context,
|
|
||||||
const gchar* text,
|
|
||||||
gint len,
|
|
||||||
gint cursor_index) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
self->mock->gtk_im_context_set_surrounding(context, text, len, cursor_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean fl_mock_im_context_get_surrounding(GtkIMContext* context,
|
|
||||||
gchar** text,
|
|
||||||
gint* cursor_index) {
|
|
||||||
FlMockIMContext* self = FL_MOCK_IM_CONTEXT(context);
|
|
||||||
return self->mock->gtk_im_context_get_surrounding(context, text,
|
|
||||||
cursor_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_class_init(FlMockIMContextClass* klass) {
|
|
||||||
GtkIMContextClass* im_context_class = GTK_IM_CONTEXT_CLASS(klass);
|
|
||||||
im_context_class->set_client_window = fl_mock_im_context_set_client_window;
|
|
||||||
im_context_class->get_preedit_string = fl_mock_im_context_get_preedit_string;
|
|
||||||
im_context_class->filter_keypress = fl_mock_im_context_filter_keypress;
|
|
||||||
im_context_class->focus_in = fl_mock_im_context_focus_in;
|
|
||||||
im_context_class->focus_out = fl_mock_im_context_focus_out;
|
|
||||||
im_context_class->reset = fl_mock_im_context_reset;
|
|
||||||
im_context_class->set_cursor_location =
|
|
||||||
fl_mock_im_context_set_cursor_location;
|
|
||||||
im_context_class->set_use_preedit = fl_mock_im_context_set_use_preedit;
|
|
||||||
im_context_class->set_surrounding = fl_mock_im_context_set_surrounding;
|
|
||||||
im_context_class->get_surrounding = fl_mock_im_context_get_surrounding;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_im_context_init(FlMockIMContext* self) {}
|
|
||||||
|
|
||||||
static GtkIMContext* fl_mock_im_context_new(MockIMContext* mock) {
|
|
||||||
FlMockIMContext* self =
|
|
||||||
FL_MOCK_IM_CONTEXT(g_object_new(fl_mock_im_context_get_type(), nullptr));
|
|
||||||
self->mock = mock;
|
|
||||||
return GTK_IM_CONTEXT(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MockIMContext::~MockIMContext() {
|
MockIMContext::~MockIMContext() {
|
||||||
if (FL_IS_MOCK_IM_CONTEXT(instance_)) {
|
if (mock == this) {
|
||||||
g_clear_object(&instance_);
|
mock = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MockIMContext::operator GtkIMContext*() {
|
void gtk_im_context_set_client_window(GtkIMContext* context,
|
||||||
if (instance_ == nullptr) {
|
GdkWindow* window) {
|
||||||
instance_ = fl_mock_im_context_new(this);
|
if (mock != nullptr) {
|
||||||
|
mock->gtk_im_context_set_client_window(context, window);
|
||||||
}
|
}
|
||||||
return instance_;
|
}
|
||||||
|
|
||||||
|
void gtk_im_context_get_preedit_string(GtkIMContext* context,
|
||||||
|
gchar** str,
|
||||||
|
PangoAttrList** attrs,
|
||||||
|
gint* cursor_pos) {
|
||||||
|
if (mock != nullptr) {
|
||||||
|
mock->gtk_im_context_get_preedit_string(context, str, attrs, cursor_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean gtk_im_context_filter_keypress(GtkIMContext* context,
|
||||||
|
GdkEventKey* event) {
|
||||||
|
if (mock == nullptr) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mock->gtk_im_context_filter_keypress(context, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gtk_im_context_focus_in(GtkIMContext* context) {
|
||||||
|
if (mock != nullptr) {
|
||||||
|
mock->gtk_im_context_focus_in(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gtk_im_context_focus_out(GtkIMContext* context) {
|
||||||
|
if (mock != nullptr) {
|
||||||
|
mock->gtk_im_context_focus_out(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gtk_im_context_set_cursor_location(GtkIMContext* context,
|
||||||
|
const GdkRectangle* area) {
|
||||||
|
if (mock != nullptr) {
|
||||||
|
mock->gtk_im_context_set_cursor_location(context, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gtk_im_context_set_surrounding(GtkIMContext* context,
|
||||||
|
const gchar* text,
|
||||||
|
gint len,
|
||||||
|
gint cursor_index) {
|
||||||
|
if (mock != nullptr) {
|
||||||
|
mock->gtk_im_context_set_surrounding(context, text, len, cursor_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean gtk_widget_translate_coordinates(GtkWidget* src_widget,
|
||||||
|
GtkWidget* dest_widget,
|
||||||
|
gint src_x,
|
||||||
|
gint src_y,
|
||||||
|
gint* dest_x,
|
||||||
|
gint* dest_y) {
|
||||||
|
if (mock == nullptr) {
|
||||||
|
*dest_x = src_x;
|
||||||
|
*dest_y = src_y;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mock->gtk_widget_translate_coordinates(src_widget, dest_widget, src_x,
|
||||||
|
src_y, dest_x, dest_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget* gtk_widget_get_toplevel(GtkWidget* widget) {
|
||||||
|
return widget;
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,9 @@ namespace testing {
|
|||||||
|
|
||||||
class MockIMContext {
|
class MockIMContext {
|
||||||
public:
|
public:
|
||||||
|
MockIMContext();
|
||||||
~MockIMContext();
|
~MockIMContext();
|
||||||
|
|
||||||
// This was an existing use of operator overloading. It's against our style
|
|
||||||
// guide but enabling clang tidy on header files is a higher priority than
|
|
||||||
// fixing this.
|
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
||||||
operator GtkIMContext*();
|
|
||||||
|
|
||||||
MOCK_METHOD(void,
|
MOCK_METHOD(void,
|
||||||
gtk_im_context_set_client_window,
|
gtk_im_context_set_client_window,
|
||||||
(GtkIMContext * context, GdkWindow* window));
|
(GtkIMContext * context, GdkWindow* window));
|
||||||
@ -36,23 +31,22 @@ class MockIMContext {
|
|||||||
(GtkIMContext * context, GdkEventKey* event));
|
(GtkIMContext * context, GdkEventKey* event));
|
||||||
MOCK_METHOD(gboolean, gtk_im_context_focus_in, (GtkIMContext * context));
|
MOCK_METHOD(gboolean, gtk_im_context_focus_in, (GtkIMContext * context));
|
||||||
MOCK_METHOD(void, gtk_im_context_focus_out, (GtkIMContext * context));
|
MOCK_METHOD(void, gtk_im_context_focus_out, (GtkIMContext * context));
|
||||||
MOCK_METHOD(void, gtk_im_context_reset, (GtkIMContext * context));
|
|
||||||
MOCK_METHOD(void,
|
MOCK_METHOD(void,
|
||||||
gtk_im_context_set_cursor_location,
|
gtk_im_context_set_cursor_location,
|
||||||
(GtkIMContext * context, GdkRectangle* area));
|
(GtkIMContext * context, const GdkRectangle* area));
|
||||||
MOCK_METHOD(void,
|
|
||||||
gtk_im_context_set_use_preedit,
|
|
||||||
(GtkIMContext * context, gboolean use_preedit));
|
|
||||||
MOCK_METHOD(
|
MOCK_METHOD(
|
||||||
void,
|
void,
|
||||||
gtk_im_context_set_surrounding,
|
gtk_im_context_set_surrounding,
|
||||||
(GtkIMContext * context, const gchar* text, gint len, gint cursor_index));
|
(GtkIMContext * context, const gchar* text, gint len, gint cursor_index));
|
||||||
MOCK_METHOD(gboolean,
|
MOCK_METHOD(gboolean,
|
||||||
gtk_im_context_get_surrounding,
|
gtk_widget_translate_coordinates,
|
||||||
(GtkIMContext * context, gchar** text, gint* cursor_index));
|
(GtkWidget * src_widget,
|
||||||
|
GtkWidget* dest_widget,
|
||||||
private:
|
gint src_x,
|
||||||
GtkIMContext* instance_ = nullptr;
|
gint src_y,
|
||||||
|
gint* dest_x,
|
||||||
|
gint* dest_y));
|
||||||
|
MOCK_METHOD(GtkWidget*, gtk_widget_get_toplevel, (GtkWidget * widget));
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
@ -28,6 +28,12 @@ MockKeymap::MockKeymap() {
|
|||||||
mock = this;
|
mock = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockKeymap::~MockKeymap() {
|
||||||
|
if (mock == this) {
|
||||||
|
mock = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GdkKeymap* gdk_keymap_get_for_display(GdkDisplay* display) {
|
GdkKeymap* gdk_keymap_get_for_display(GdkDisplay* display) {
|
||||||
FlMockKeymap* keymap =
|
FlMockKeymap* keymap =
|
||||||
FL_MOCK_KEYMAP(g_object_new(fl_mock_keymap_get_type(), nullptr));
|
FL_MOCK_KEYMAP(g_object_new(fl_mock_keymap_get_type(), nullptr));
|
||||||
|
@ -15,6 +15,7 @@ namespace testing {
|
|||||||
class MockKeymap {
|
class MockKeymap {
|
||||||
public:
|
public:
|
||||||
MockKeymap();
|
MockKeymap();
|
||||||
|
~MockKeymap();
|
||||||
|
|
||||||
MOCK_METHOD(GdkKeymap*, gdk_keymap_get_for_display, (GdkDisplay * display));
|
MOCK_METHOD(GdkKeymap*, gdk_keymap_get_for_display, (GdkDisplay * display));
|
||||||
MOCK_METHOD(guint,
|
MOCK_METHOD(guint,
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "flutter/shell/platform/linux/testing/mock_text_input_view_delegate.h"
|
|
||||||
|
|
||||||
using namespace flutter::testing;
|
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(FlMockTextInputViewDelegate,
|
|
||||||
fl_mock_text_input_view_delegate,
|
|
||||||
FL,
|
|
||||||
MOCK_TEXT_INPUT_VIEW_DELEGATE,
|
|
||||||
GObject)
|
|
||||||
|
|
||||||
struct _FlMockTextInputViewDelegate {
|
|
||||||
GObject parent_instance;
|
|
||||||
MockTextInputViewDelegate* mock;
|
|
||||||
};
|
|
||||||
|
|
||||||
static FlTextInputViewDelegate* fl_mock_text_input_view_delegate_new(
|
|
||||||
MockTextInputViewDelegate* mock) {
|
|
||||||
FlMockTextInputViewDelegate* self = FL_MOCK_TEXT_INPUT_VIEW_DELEGATE(
|
|
||||||
g_object_new(fl_mock_text_input_view_delegate_get_type(), nullptr));
|
|
||||||
self->mock = mock;
|
|
||||||
return FL_TEXT_INPUT_VIEW_DELEGATE(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
MockTextInputViewDelegate::MockTextInputViewDelegate()
|
|
||||||
: instance_(fl_mock_text_input_view_delegate_new(this)) {}
|
|
||||||
|
|
||||||
MockTextInputViewDelegate::~MockTextInputViewDelegate() {
|
|
||||||
if (FL_IS_TEXT_INPUT_VIEW_DELEGATE(instance_)) {
|
|
||||||
g_clear_object(&instance_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MockTextInputViewDelegate::operator FlTextInputViewDelegate*() {
|
|
||||||
return instance_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_text_input_view_delegate_iface_init(
|
|
||||||
FlTextInputViewDelegateInterface* iface);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE(
|
|
||||||
FlMockTextInputViewDelegate,
|
|
||||||
fl_mock_text_input_view_delegate,
|
|
||||||
G_TYPE_OBJECT,
|
|
||||||
G_IMPLEMENT_INTERFACE(fl_text_input_view_delegate_get_type(),
|
|
||||||
fl_mock_text_input_view_delegate_iface_init))
|
|
||||||
|
|
||||||
static void fl_mock_text_input_view_delegate_class_init(
|
|
||||||
FlMockTextInputViewDelegateClass* klass) {}
|
|
||||||
|
|
||||||
static void fl_mock_text_input_view_delegate_translate_coordinates(
|
|
||||||
FlTextInputViewDelegate* view_delegate,
|
|
||||||
gint view_x,
|
|
||||||
gint view_y,
|
|
||||||
gint* window_x,
|
|
||||||
gint* window_y) {
|
|
||||||
g_return_if_fail(FL_IS_MOCK_TEXT_INPUT_VIEW_DELEGATE(view_delegate));
|
|
||||||
FlMockTextInputViewDelegate* self =
|
|
||||||
FL_MOCK_TEXT_INPUT_VIEW_DELEGATE(view_delegate);
|
|
||||||
self->mock->fl_text_input_view_delegate_translate_coordinates(
|
|
||||||
view_delegate, view_x, view_y, window_x, window_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_text_input_view_delegate_iface_init(
|
|
||||||
FlTextInputViewDelegateInterface* iface) {
|
|
||||||
iface->translate_coordinates =
|
|
||||||
fl_mock_text_input_view_delegate_translate_coordinates;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fl_mock_text_input_view_delegate_init(
|
|
||||||
FlMockTextInputViewDelegate* self) {}
|
|
@ -1,41 +0,0 @@
|
|||||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_TEXT_INPUT_VIEW_DELEGATE_H_
|
|
||||||
#define FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_TEXT_INPUT_VIEW_DELEGATE_H_
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "flutter/shell/platform/linux/fl_text_input_view_delegate.h"
|
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
|
||||||
|
|
||||||
namespace flutter {
|
|
||||||
namespace testing {
|
|
||||||
|
|
||||||
// Mock for FlTextInputVuewDelegate.
|
|
||||||
class MockTextInputViewDelegate {
|
|
||||||
public:
|
|
||||||
MockTextInputViewDelegate();
|
|
||||||
~MockTextInputViewDelegate();
|
|
||||||
|
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
||||||
operator FlTextInputViewDelegate*();
|
|
||||||
|
|
||||||
MOCK_METHOD(void,
|
|
||||||
fl_text_input_view_delegate_translate_coordinates,
|
|
||||||
(FlTextInputViewDelegate * delegate,
|
|
||||||
gint view_x,
|
|
||||||
gint view_y,
|
|
||||||
gint* window_x,
|
|
||||||
gint* window_y));
|
|
||||||
|
|
||||||
private:
|
|
||||||
FlTextInputViewDelegate* instance_ = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace testing
|
|
||||||
} // namespace flutter
|
|
||||||
|
|
||||||
#endif // FLUTTER_SHELL_PLATFORM_LINUX_TESTING_MOCK_TEXT_INPUT_VIEW_DELEGATE_H_
|
|
@ -12,6 +12,12 @@ MockWindow::MockWindow() {
|
|||||||
mock = this;
|
mock = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockWindow::~MockWindow() {
|
||||||
|
if (mock == this) {
|
||||||
|
mock = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GdkDisplay* gdk_display_get_default() {
|
GdkDisplay* gdk_display_get_default() {
|
||||||
return GDK_DISPLAY(g_object_new(gdk_display_get_type(), nullptr));
|
return GDK_DISPLAY(g_object_new(gdk_display_get_type(), nullptr));
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ namespace testing {
|
|||||||
class MockWindow {
|
class MockWindow {
|
||||||
public:
|
public:
|
||||||
MockWindow();
|
MockWindow();
|
||||||
|
~MockWindow();
|
||||||
|
|
||||||
MOCK_METHOD(GdkWindowState, gdk_window_get_state, (GdkWindow * window));
|
MOCK_METHOD(GdkWindowState, gdk_window_get_state, (GdkWindow * window));
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user