mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[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:
parent
6f415b64c5
commit
5ced18fed0
@ -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
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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_
|
||||
@ -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,
|
||||
|
||||
@ -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) {}
|
||||
@ -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_
|
||||
Loading…
x
Reference in New Issue
Block a user