[Linux] use top-level GTK IM client window (flutter/engine#35272)

This PR takes a step back and changes the GTK IM client window back from FlView to GtkApplicationWindow as it was before #33111. The window was originally changed to FlView to make the code testable by cutting a dependency to gtk_widget_translate_coordinates(). The change was hard to revert because there were several conflicting changes on top. Therefore, this PR introduces an FlTextInputViewDelegate to be able to provide coordinate mapping in a testable way.

Fixes: flutter/flutter#108832
This commit is contained in:
J-P Nurmi 2022-08-10 01:55:41 +02:00 committed by GitHub
parent 6f415b64c5
commit 5ced18fed0
10 changed files with 279 additions and 24 deletions

View File

@ -2321,6 +2321,8 @@ FILE: ../../../flutter/shell/platform/linux/fl_task_runner.h
FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.cc
FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin.h
FILE: ../../../flutter/shell/platform/linux/fl_text_input_plugin_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_gl.cc
FILE: ../../../flutter/shell/platform/linux/fl_texture_gl_private.h

View File

@ -141,6 +141,7 @@ source_set("flutter_linux_sources") {
"fl_task_runner.cc",
"fl_task_runner.h",
"fl_text_input_plugin.cc",
"fl_text_input_view_delegate.cc",
"fl_texture.cc",
"fl_texture_gl.cc",
"fl_texture_registrar.cc",
@ -234,6 +235,7 @@ executable("flutter_linux_unittests") {
"testing/mock_settings.cc",
"testing/mock_signal_handler.cc",
"testing/mock_text_input_plugin.cc",
"testing/mock_text_input_view_delegate.cc",
"testing/mock_texture_registrar.cc",
]

View File

@ -80,6 +80,8 @@ struct FlTextInputPluginPrivate {
// Input method.
GtkIMContext* im_context;
FlTextInputViewDelegate* view_delegate;
flutter::TextInputModel* text_model;
// A 4x4 matrix that maps from `EditableText` local coordinates to the
@ -487,9 +489,13 @@ static void update_im_cursor_position(FlTextInputPlugin* self) {
priv->composing_rect.y * priv->editabletext_transform[1][1] +
priv->editabletext_transform[3][1] + priv->composing_rect.height;
// Transform from Flutter view coordinates to GTK window coordinates.
GdkRectangle preedit_rect = {};
fl_text_input_view_delegate_translate_coordinates(
priv->view_delegate, x, y, &preedit_rect.x, &preedit_rect.y);
// Set the cursor location in window coordinates so that GTK can position any
// system input method windows.
GdkRectangle preedit_rect = {x, y, 0, 0};
gtk_im_context_set_cursor_location(priv->im_context, &preedit_rect);
}
@ -587,6 +593,12 @@ static void fl_text_input_plugin_dispose(GObject* object) {
delete priv->text_model;
priv->text_model = nullptr;
}
if (priv->view_delegate != nullptr) {
g_object_remove_weak_pointer(
G_OBJECT(priv->view_delegate),
reinterpret_cast<gpointer*>(&(priv->view_delegate)));
priv->view_delegate = nullptr;
}
G_OBJECT_CLASS(fl_text_input_plugin_parent_class)->dispose(object);
}
@ -719,10 +731,13 @@ static void init_im_context(FlTextInputPlugin* self, GtkIMContext* im_context) {
G_CONNECT_SWAPPED);
}
FlTextInputPlugin* fl_text_input_plugin_new(FlBinaryMessenger* messenger,
GtkIMContext* im_context) {
FlTextInputPlugin* fl_text_input_plugin_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);
FlTextInputPlugin* self = FL_TEXT_INPUT_PLUGIN(
g_object_new(fl_text_input_plugin_get_type(), nullptr));
@ -737,6 +752,11 @@ FlTextInputPlugin* fl_text_input_plugin_new(FlBinaryMessenger* messenger,
init_im_context(self, im_context);
priv->view_delegate = view_delegate;
g_object_add_weak_pointer(
G_OBJECT(view_delegate),
reinterpret_cast<gpointer*>(&(priv->view_delegate)));
return self;
}

View File

@ -8,6 +8,7 @@
#include <gtk/gtk.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"
G_BEGIN_DECLS
@ -38,14 +39,17 @@ struct _FlTextInputPluginClass {
* fl_text_input_plugin_new:
* @messenger: an #FlBinaryMessenger.
* @im_context: (allow-none): a #GtkIMContext.
* @view_delegate: an #FlTextInputViewDelegate.
*
* Creates a new plugin that implements SystemChannels.textInput from the
* Flutter services library.
*
* Returns: a new #FlTextInputPlugin.
*/
FlTextInputPlugin* fl_text_input_plugin_new(FlBinaryMessenger* messenger,
GtkIMContext* im_context);
FlTextInputPlugin* fl_text_input_plugin_new(
FlBinaryMessenger* messenger,
GtkIMContext* im_context,
FlTextInputViewDelegate* view_delegate);
/**
* fl_text_input_plugin_filter_keypress

View File

@ -11,6 +11,7 @@
#include "flutter/shell/platform/linux/testing/mock_binary_messenger.h"
#include "flutter/shell/platform/linux/testing/mock_binary_messenger_response_handle.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 "gmock/gmock.h"
@ -189,9 +190,10 @@ static void send_key_event(FlTextInputPlugin* plugin,
TEST(FlTextInputPluginTest, MessageHandler) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
EXPECT_TRUE(messenger.HasMessageHandler("flutter/textinput"));
@ -200,9 +202,10 @@ TEST(FlTextInputPluginTest, MessageHandler) {
TEST(FlTextInputPluginTest, SetClient) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
g_autoptr(FlValue) args = build_input_config({.client_id = 1});
@ -222,9 +225,10 @@ TEST(FlTextInputPluginTest, SetClient) {
TEST(FlTextInputPluginTest, Show) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
EXPECT_CALL(context,
@ -246,9 +250,10 @@ TEST(FlTextInputPluginTest, Show) {
TEST(FlTextInputPluginTest, Hide) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
EXPECT_CALL(context,
@ -270,9 +275,10 @@ TEST(FlTextInputPluginTest, Hide) {
TEST(FlTextInputPluginTest, ClearClient) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
g_autoptr(FlValue) null = fl_value_new_null();
@ -291,9 +297,10 @@ TEST(FlTextInputPluginTest, ClearClient) {
TEST(FlTextInputPluginTest, PerformAction) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
// set input config
@ -366,9 +373,10 @@ TEST(FlTextInputPluginTest, PerformAction) {
TEST(FlTextInputPluginTest, MoveCursor) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
// set input config
@ -443,9 +451,10 @@ TEST(FlTextInputPluginTest, MoveCursor) {
TEST(FlTextInputPluginTest, Select) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
// set input config
@ -520,9 +529,10 @@ TEST(FlTextInputPluginTest, Select) {
TEST(FlTextInputPluginTest, Composing) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
g_signal_emit_by_name(context, "preedit-start", nullptr);
@ -589,9 +599,10 @@ TEST(FlTextInputPluginTest, Composing) {
TEST(FlTextInputPluginTest, SurroundingText) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
// set input config
@ -658,9 +669,10 @@ TEST(FlTextInputPluginTest, SurroundingText) {
TEST(FlTextInputPluginTest, SetMarkedTextRect) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
g_signal_emit_by_name(context, "preedit-start", nullptr);
@ -719,11 +731,18 @@ TEST(FlTextInputPluginTest, SetMarkedTextRect) {
::testing::_, SuccessResponse(null), ::testing::_))
.WillOnce(::testing::Return(true));
EXPECT_CALL(delegate, fl_text_input_view_delegate_translate_coordinates(
::testing::Eq<FlTextInputViewDelegate*>(delegate),
::testing::Eq(27), ::testing::Eq(32), ::testing::_,
::testing::_))
.WillOnce(::testing::DoAll(::testing::SetArgPointee<3>(123),
::testing::SetArgPointee<4>(456)));
EXPECT_CALL(context, gtk_im_context_set_cursor_location(
::testing::Eq<GtkIMContext*>(context),
::testing::Pointee(::testing::AllOf(
::testing::Field(&GdkRectangle::x, 27),
::testing::Field(&GdkRectangle::y, 32),
::testing::Field(&GdkRectangle::x, 123),
::testing::Field(&GdkRectangle::y, 456),
::testing::Field(&GdkRectangle::width, 0),
::testing::Field(&GdkRectangle::height, 0)))));
@ -733,9 +752,10 @@ TEST(FlTextInputPluginTest, SetMarkedTextRect) {
TEST(FlTextInputPluginTest, TextInputTypeNone) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
g_autoptr(FlValue) args = build_input_config({
@ -775,9 +795,10 @@ TEST(FlTextInputPluginTest, TextInputTypeNone) {
TEST(FlTextInputPluginTest, TextEditingDelta) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
// set config
@ -846,9 +867,10 @@ TEST(FlTextInputPluginTest, TextEditingDelta) {
TEST(FlTextInputPluginTest, ComposingDelta) {
::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
::testing::NiceMock<flutter::testing::MockIMContext> context;
::testing::NiceMock<flutter::testing::MockTextInputViewDelegate> delegate;
g_autoptr(FlTextInputPlugin) plugin =
fl_text_input_plugin_new(messenger, context);
fl_text_input_plugin_new(messenger, context, delegate);
EXPECT_NE(plugin, nullptr);
// set config

View File

@ -0,0 +1,24 @@
// 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);
}

View File

@ -0,0 +1,48 @@
// 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 `FlTextInputPlugin` 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_

View File

@ -20,6 +20,7 @@
#include "flutter/shell/platform/linux/fl_scrolling_manager.h"
#include "flutter/shell/platform/linux/fl_scrolling_view_delegate.h"
#include "flutter/shell/platform/linux/fl_text_input_plugin.h"
#include "flutter/shell/platform/linux/fl_text_input_view_delegate.h"
#include "flutter/shell/platform/linux/fl_view_accessible.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h"
@ -82,6 +83,9 @@ static void fl_view_keyboard_delegate_iface_init(
static void fl_view_scrolling_delegate_iface_init(
FlScrollingViewDelegateInterface* iface);
static void fl_view_text_input_delegate_iface_init(
FlTextInputViewDelegateInterface* iface);
G_DEFINE_TYPE_WITH_CODE(
FlView,
fl_view,
@ -91,18 +95,22 @@ G_DEFINE_TYPE_WITH_CODE(
G_IMPLEMENT_INTERFACE(fl_keyboard_view_delegate_get_type(),
fl_view_keyboard_delegate_iface_init)
G_IMPLEMENT_INTERFACE(fl_scrolling_view_delegate_get_type(),
fl_view_scrolling_delegate_iface_init))
fl_view_scrolling_delegate_iface_init)
G_IMPLEMENT_INTERFACE(fl_text_input_view_delegate_get_type(),
fl_view_text_input_delegate_iface_init))
// Initialize keyboard manager.
static void init_keyboard(FlView* self) {
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(self->engine);
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(self));
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);
self->text_input_plugin = fl_text_input_plugin_new(messenger, im_context);
self->text_input_plugin = fl_text_input_plugin_new(
messenger, im_context, FL_TEXT_INPUT_VIEW_DELEGATE(self));
self->keyboard_manager =
fl_keyboard_manager_new(FL_KEYBOARD_VIEW_DELEGATE(self));
}
@ -333,6 +341,18 @@ static void fl_view_scrolling_delegate_iface_init(
};
}
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);
};
}
// Signal handler for GtkWidget::button-press-event
static gboolean button_press_event_cb(GtkWidget* widget,
GdkEventButton* event,

View File

@ -0,0 +1,74 @@
// 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) {}

View File

@ -0,0 +1,39 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_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();
operator FlTextInputViewDelegate*();
MOCK_METHOD5(fl_text_input_view_delegate_translate_coordinates,
void(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_