Remove obsolete windowing channel (#179718)

This was an older method used for multi-window and has since been
replaced with FFI.
This commit is contained in:
Robert Ancell 2025-12-15 09:21:26 +13:00 committed by GitHub
parent c9ddf161d7
commit 331cdce7b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 0 additions and 1378 deletions

View File

@ -172,8 +172,6 @@ source_set("flutter_linux_sources") {
"fl_view_accessible.cc",
"fl_window_monitor.cc",
"fl_window_state_monitor.cc",
"fl_windowing_channel.cc",
"fl_windowing_handler.cc",
"key_mapping.g.cc",
]
@ -268,7 +266,6 @@ executable("flutter_linux_unittests") {
"fl_view_accessible_test.cc",
"fl_view_test.cc",
"fl_window_state_monitor_test.cc",
"fl_windowing_handler_test.cc",
"key_mapping_test.cc",
"testing/fl_mock_binary_messenger.cc",
"testing/fl_test.cc",

View File

@ -32,15 +32,6 @@ G_DEFINE_TYPE_WITH_CODE(FlApplication,
GTK_TYPE_APPLICATION,
G_ADD_PRIVATE(FlApplication))
// Called when the platform creates a window.
static GtkWindow* create_window_cb(FlApplication* self, FlView* view) {
GtkWindow* window;
g_signal_emit(self, fl_application_signals[SIGNAL_CREATE_WINDOW], 0, view,
&window);
return window;
}
// Called when the first frame is received.
static void first_frame_cb(FlApplication* self, FlView* view) {
GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(view));
@ -104,11 +95,6 @@ static void fl_application_activate(GApplication* application) {
self);
gtk_widget_show(GTK_WIDGET(view));
FlWindowingHandler* windowing_handler =
fl_engine_get_windowing_handler(fl_view_get_engine(view));
g_signal_connect_swapped(windowing_handler, "create_window",
G_CALLBACK(create_window_cb), self);
GtkWindow* window;
g_signal_emit(self, fl_application_signals[SIGNAL_CREATE_WINDOW], 0, view,
&window);

View File

@ -26,7 +26,6 @@
#include "flutter/shell/platform/linux/fl_settings_handler.h"
#include "flutter/shell/platform/linux/fl_texture_gl_private.h"
#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"
#include "flutter/shell/platform/linux/fl_windowing_handler.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_plugin_registry.h"
// Unique number associated with platform tasks.
@ -64,9 +63,6 @@ struct _FlEngine {
// Implements the flutter/platform channel.
FlPlatformHandler* platform_handler;
// Implements the flutter/windowing channel.
FlWindowingHandler* windowing_handler;
// Implements the flutter/accessibility channel.
FlAccessibilityHandler* accessibility_handler;
@ -591,7 +587,6 @@ static void fl_engine_dispose(GObject* object) {
g_clear_object(&self->binary_messenger);
g_clear_object(&self->settings_handler);
g_clear_object(&self->platform_handler);
g_clear_object(&self->windowing_handler);
g_clear_object(&self->accessibility_handler);
g_clear_object(&self->keyboard_manager);
g_clear_object(&self->text_input_handler);
@ -688,7 +683,6 @@ static FlEngine* fl_engine_new_full(FlDartProject* project,
self->keyboard_manager = fl_keyboard_manager_new(self);
self->mouse_cursor_handler =
fl_mouse_cursor_handler_new(self->binary_messenger);
self->windowing_handler = fl_windowing_handler_new(self);
self->accessibility_handler = fl_accessibility_handler_new(self);
return self;
@ -1497,11 +1491,6 @@ void fl_engine_request_app_exit(FlEngine* self) {
fl_platform_handler_request_app_exit(self->platform_handler);
}
FlWindowingHandler* fl_engine_get_windowing_handler(FlEngine* self) {
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
return self->windowing_handler;
}
FlKeyboardManager* fl_engine_get_keyboard_manager(FlEngine* self) {
g_return_val_if_fail(FL_IS_ENGINE(self), nullptr);
return self->keyboard_manager;

View File

@ -15,7 +15,6 @@
#include "flutter/shell/platform/linux/fl_renderable.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/fl_windowing_handler.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_dart_project.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
@ -584,16 +583,6 @@ void fl_engine_update_accessibility_features(FlEngine* engine, int32_t flags);
*/
void fl_engine_request_app_exit(FlEngine* engine);
/**
* fl_engine_get_windowing_handler:
* @engine: an #FlEngine.
*
* Gets the windowing handler used by this engine.
*
* Returns: an #FlWindowingHandler.
*/
FlWindowingHandler* fl_engine_get_windowing_handler(FlEngine* engine);
/**
* fl_engine_get_keyboard_manager:
* @engine: an #FlEngine.

View File

@ -1062,7 +1062,6 @@ TEST(FlEngineTest, ChildObjects) {
EXPECT_NE(fl_engine_get_task_runner(engine), nullptr);
EXPECT_NE(fl_engine_get_keyboard_manager(engine), nullptr);
EXPECT_NE(fl_engine_get_mouse_cursor_handler(engine), nullptr);
EXPECT_NE(fl_engine_get_windowing_handler(engine), nullptr);
}
// NOLINTEND(clang-analyzer-core.StackAddressEscape)

View File

@ -1,296 +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_windowing_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
static constexpr char kChannelName[] = "flutter/windowing";
static constexpr char kBadArgumentsError[] = "Bad Arguments";
static constexpr char kCreateRegularMethod[] = "createRegular";
static constexpr char kModifyRegularMethod[] = "modifyRegular";
static constexpr char kDestroyWindowMethod[] = "destroyWindow";
static constexpr char kSizeKey[] = "size";
static constexpr char kMinSizeKey[] = "minSize";
static constexpr char kMaxSizeKey[] = "maxSize";
static constexpr char kTitleKey[] = "title";
static constexpr char kStateKey[] = "state";
static constexpr char kViewIdKey[] = "viewId";
struct _FlWindowingChannel {
GObject parent_instance;
FlMethodChannel* channel;
// Handlers for incoming method calls.
FlWindowingChannelVTable* vtable;
// User data to pass to method call handlers.
gpointer user_data;
};
G_DEFINE_TYPE(FlWindowingChannel, fl_windowing_channel, G_TYPE_OBJECT)
// Returns TRUE if [args] is a valid size argument.
static gboolean is_valid_size_argument(FlValue* value) {
return fl_value_get_type(value) == FL_VALUE_TYPE_LIST &&
fl_value_get_length(value) == 2 &&
fl_value_get_type(fl_value_get_list_value(value, 0)) ==
FL_VALUE_TYPE_FLOAT &&
fl_value_get_type(fl_value_get_list_value(value, 1)) ==
FL_VALUE_TYPE_FLOAT;
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FlWindowingSize, g_free)
static FlWindowingSize* parse_size_value(FlValue* value) {
FlWindowingSize* size = g_new0(FlWindowingSize, 1);
size->width = fl_value_get_float(fl_value_get_list_value(value, 0));
size->height = fl_value_get_float(fl_value_get_list_value(value, 1));
return size;
}
static gboolean parse_window_state_value(FlValue* value, FlWindowState* state) {
if (fl_value_get_type(value) != FL_VALUE_TYPE_STRING) {
return FALSE;
}
const gchar* text = fl_value_get_string(value);
if (strcmp(text, "WindowState.restored") == 0) {
*state = FL_WINDOW_STATE_RESTORED;
return TRUE;
} else if (strcmp(text, "WindowState.maximized") == 0) {
*state = FL_WINDOW_STATE_MAXIMIZED;
return TRUE;
} else if (strcmp(text, "WindowState.minimized") == 0) {
*state = FL_WINDOW_STATE_MINIMIZED;
return TRUE;
}
return FALSE;
}
static const gchar* window_state_to_string(FlWindowState state) {
switch (state) {
case FL_WINDOW_STATE_UNDEFINED:
return nullptr;
case FL_WINDOW_STATE_RESTORED:
return "WindowState.restored";
case FL_WINDOW_STATE_MAXIMIZED:
return "WindowState.maximized";
case FL_WINDOW_STATE_MINIMIZED:
return "WindowState.minimized";
}
return nullptr;
}
// Called when a regular window should be created.
static FlMethodResponse* create_regular(FlWindowingChannel* self,
FlValue* args) {
if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Argument map missing or malformed", nullptr));
}
FlValue* size_value = fl_value_lookup_string(args, kSizeKey);
if (size_value == nullptr || !is_valid_size_argument(size_value)) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Missing/invalid size argument", nullptr));
}
g_autoptr(FlWindowingSize) size = parse_size_value(size_value);
FlValue* min_size_value = fl_value_lookup_string(args, kMinSizeKey);
g_autoptr(FlWindowingSize) min_size = nullptr;
if (min_size_value != nullptr) {
if (!is_valid_size_argument(min_size_value)) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid minSize argument", nullptr));
}
min_size = parse_size_value(min_size_value);
}
FlValue* max_size_value = fl_value_lookup_string(args, kMaxSizeKey);
g_autoptr(FlWindowingSize) max_size = nullptr;
if (max_size_value != nullptr) {
if (!is_valid_size_argument(max_size_value)) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid maxSize argument", nullptr));
}
max_size = parse_size_value(max_size_value);
}
FlValue* title_value = fl_value_lookup_string(args, kTitleKey);
const gchar* title = nullptr;
if (title_value != nullptr) {
if (fl_value_get_type(title_value) != FL_VALUE_TYPE_STRING) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid title argument", nullptr));
}
title = fl_value_get_string(title_value);
}
FlWindowState state = FL_WINDOW_STATE_UNDEFINED;
FlValue* state_value = fl_value_lookup_string(args, kStateKey);
if (state_value != nullptr) {
if (!parse_window_state_value(state_value, &state)) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid state argument", nullptr));
}
}
return self->vtable->create_regular(size, min_size, max_size, title, state,
self->user_data);
}
// Called when a regular window should be created.
static FlMethodResponse* modify_regular(FlWindowingChannel* self,
FlValue* args) {
if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Argument map missing or malformed", nullptr));
}
FlValue* view_id_value = fl_value_lookup_string(args, kViewIdKey);
if (view_id_value == nullptr ||
fl_value_get_type(view_id_value) != FL_VALUE_TYPE_INT) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Missing/invalid viewId argument", nullptr));
}
int64_t view_id = fl_value_get_int(view_id_value);
g_autoptr(FlWindowingSize) size = nullptr;
FlValue* size_value = fl_value_lookup_string(args, kSizeKey);
if (size_value != nullptr) {
if (!is_valid_size_argument(size_value)) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid size argument", nullptr));
}
size = parse_size_value(size_value);
}
FlValue* title_value = fl_value_lookup_string(args, kTitleKey);
const gchar* title = nullptr;
if (title_value != nullptr) {
if (fl_value_get_type(title_value) != FL_VALUE_TYPE_STRING) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid title argument", nullptr));
}
title = fl_value_get_string(title_value);
}
FlWindowState state = FL_WINDOW_STATE_UNDEFINED;
FlValue* state_value = fl_value_lookup_string(args, kStateKey);
if (state_value != nullptr) {
if (!parse_window_state_value(state_value, &state)) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Invalid state argument", nullptr));
}
}
return self->vtable->modify_regular(view_id, size, title, state,
self->user_data);
}
// Called when a window should be destroyed.
static FlMethodResponse* destroy_window(FlWindowingChannel* self,
FlValue* args) {
if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Argument map missing or malformed", nullptr));
}
FlValue* view_id_value = fl_value_lookup_string(args, kViewIdKey);
if (view_id_value == nullptr ||
fl_value_get_type(view_id_value) != FL_VALUE_TYPE_INT) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
kBadArgumentsError, "Missing/invalid viewId argument", nullptr));
}
int64_t view_id = fl_value_get_int(view_id_value);
return self->vtable->destroy_window(view_id, self->user_data);
}
// Called when a method call is received from Flutter.
static void method_call_cb(FlMethodChannel* channel,
FlMethodCall* method_call,
gpointer user_data) {
FlWindowingChannel* self = FL_WINDOWING_CHANNEL(user_data);
const gchar* method = fl_method_call_get_name(method_call);
FlValue* args = fl_method_call_get_args(method_call);
g_autoptr(FlMethodResponse) response = nullptr;
if (strcmp(method, kCreateRegularMethod) == 0) {
response = create_regular(self, args);
} else if (strcmp(method, kModifyRegularMethod) == 0) {
response = modify_regular(self, args);
} else if (strcmp(method, kDestroyWindowMethod) == 0) {
response = destroy_window(self, args);
} else {
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
}
if (response != nullptr) {
g_autoptr(GError) error = nullptr;
if (!fl_method_call_respond(method_call, response, &error)) {
g_warning("Failed to send method call response: %s", error->message);
}
}
}
static void fl_windowing_channel_dispose(GObject* object) {
FlWindowingChannel* self = FL_WINDOWING_CHANNEL(object);
g_clear_object(&self->channel);
G_OBJECT_CLASS(fl_windowing_channel_parent_class)->dispose(object);
}
static void fl_windowing_channel_class_init(FlWindowingChannelClass* klass) {
G_OBJECT_CLASS(klass)->dispose = fl_windowing_channel_dispose;
}
static void fl_windowing_channel_init(FlWindowingChannel* self) {}
FlWindowingChannel* fl_windowing_channel_new(FlBinaryMessenger* messenger,
FlWindowingChannelVTable* vtable,
gpointer user_data) {
FlWindowingChannel* self = FL_WINDOWING_CHANNEL(
g_object_new(fl_windowing_channel_get_type(), nullptr));
self->vtable = vtable;
self->user_data = user_data;
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
self->channel =
fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
fl_method_channel_set_method_call_handler(self->channel, method_call_cb, self,
nullptr);
return self;
}
FlMethodResponse* fl_windowing_channel_make_create_regular_response(
int64_t view_id,
FlWindowingSize* size,
FlWindowState state) {
g_autoptr(FlValue) result = fl_value_new_map();
fl_value_set_string_take(result, kViewIdKey, fl_value_new_int(view_id));
g_autoptr(FlValue) size_value = fl_value_new_list();
fl_value_append_take(size_value, fl_value_new_float(size->width));
fl_value_append_take(size_value, fl_value_new_float(size->height));
fl_value_set_string(result, kSizeKey, size_value);
fl_value_set_string_take(result, kStateKey,
fl_value_new_string(window_state_to_string(state)));
return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
}
FlMethodResponse* fl_windowing_channel_make_modify_regular_response() {
return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}
FlMethodResponse* fl_windowing_channel_make_destroy_window_response() {
return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}

View File

@ -1,81 +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_WINDOWING_CHANNEL_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_WINDOWING_CHANNEL_H_
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h"
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE(FlWindowingChannel,
fl_windowing_channel,
FL,
WINDOWING_CHANNEL,
GObject);
// States that a window can be in.
typedef enum {
FL_WINDOW_STATE_UNDEFINED,
FL_WINDOW_STATE_RESTORED,
FL_WINDOW_STATE_MAXIMIZED,
FL_WINDOW_STATE_MINIMIZED
} FlWindowState;
// Size dimensions used in windowing channel.
typedef struct {
double width;
double height;
} FlWindowingSize;
/**
* FlWindowingChannel:
*
* #FlWindowingChannel is a channel that implements the shell side
* of SystemChannels.windowing from the Flutter services library.
*/
typedef struct {
FlMethodResponse* (*create_regular)(FlWindowingSize* size,
FlWindowingSize* min_size,
FlWindowingSize* max_size,
const gchar* title,
FlWindowState state,
gpointer user_data);
FlMethodResponse* (*modify_regular)(int64_t view_id,
FlWindowingSize* size,
const gchar* title,
FlWindowState state,
gpointer user_data);
FlMethodResponse* (*destroy_window)(int64_t view_id, gpointer user_data);
} FlWindowingChannelVTable;
/**
* fl_windowing_channel_new:
* @messenger: an #FlBinaryMessenger
* @vtable: callbacks for incoming method calls.
* @user_data: data to pass in callbacks.
*
* Creates a new channel that sends handled windowing requests from the
* platform.
*
* Returns: a new #FlWindowingChannel
*/
FlWindowingChannel* fl_windowing_channel_new(FlBinaryMessenger* messenger,
FlWindowingChannelVTable* vtable,
gpointer user_data);
FlMethodResponse* fl_windowing_channel_make_create_regular_response(
int64_t view_id,
FlWindowingSize* size,
FlWindowState state);
FlMethodResponse* fl_windowing_channel_make_modify_regular_response();
FlMethodResponse* fl_windowing_channel_make_destroy_window_response();
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_WINDOWING_CHANNEL_H_

View File

@ -1,274 +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_windowing_handler.h"
#include "flutter/shell/platform/linux/fl_windowing_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"
typedef struct {
GWeakRef engine;
FlWindowingChannel* channel;
GHashTable* windows_by_view_id;
} FlWindowingHandlerPrivate;
enum { SIGNAL_CREATE_WINDOW, LAST_SIGNAL };
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE_WITH_PRIVATE(FlWindowingHandler,
fl_windowing_handler,
G_TYPE_OBJECT)
typedef struct {
GtkWindow* window;
FlView* view;
guint first_frame_cb_id;
} WindowData;
static WindowData* window_data_new(GtkWindow* window, FlView* view) {
WindowData* data = g_new0(WindowData, 1);
data->window = GTK_WINDOW(g_object_ref(window));
data->view = FL_VIEW(g_object_ref(view));
return data;
}
static void window_data_free(WindowData* data) {
g_signal_handler_disconnect(data->view, data->first_frame_cb_id);
g_object_unref(data->window);
g_object_unref(data->view);
g_free(data);
}
// Called when the first frame is received.
static void first_frame_cb(FlView* view, WindowData* data) {
gtk_window_present(data->window);
}
static WindowData* get_window_data(FlWindowingHandler* self, int64_t view_id) {
FlWindowingHandlerPrivate* priv =
reinterpret_cast<FlWindowingHandlerPrivate*>(
fl_windowing_handler_get_instance_private(self));
return static_cast<WindowData*>(
g_hash_table_lookup(priv->windows_by_view_id, GINT_TO_POINTER(view_id)));
}
static GtkWindow* fl_windowing_handler_create_window(
FlWindowingHandler* handler,
FlView* view) {
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
return GTK_WINDOW(window);
}
static FlMethodResponse* create_regular(FlWindowingSize* size,
FlWindowingSize* min_size,
FlWindowingSize* max_size,
const gchar* title,
FlWindowState state,
gpointer user_data) {
FlWindowingHandler* self = FL_WINDOWING_HANDLER(user_data);
FlWindowingHandlerPrivate* priv =
reinterpret_cast<FlWindowingHandlerPrivate*>(
fl_windowing_handler_get_instance_private(self));
g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
if (engine == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new("Internal error", "No engine", nullptr));
}
FlView* view = fl_view_new_for_engine(engine);
gtk_widget_show(GTK_WIDGET(view));
GtkWindow* window;
g_signal_emit(self, signals[SIGNAL_CREATE_WINDOW], 0, view, &window);
if (window == nullptr) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
"Internal error", "Failed to create window", nullptr));
}
gtk_window_set_default_size(GTK_WINDOW(window), size->width, size->height);
if (title != nullptr) {
gtk_window_set_title(GTK_WINDOW(window), title);
}
switch (state) {
case FL_WINDOW_STATE_MAXIMIZED:
gtk_window_maximize(GTK_WINDOW(window));
break;
case FL_WINDOW_STATE_MINIMIZED:
gtk_window_iconify(GTK_WINDOW(window));
break;
case FL_WINDOW_STATE_RESTORED:
case FL_WINDOW_STATE_UNDEFINED:
break;
}
GdkGeometry geometry;
GdkWindowHints geometry_mask = static_cast<GdkWindowHints>(0);
if (min_size != nullptr) {
geometry.min_width = min_size->width;
geometry.min_height = min_size->height;
geometry_mask =
static_cast<GdkWindowHints>(geometry_mask | GDK_HINT_MIN_SIZE);
}
if (max_size != nullptr) {
geometry.max_width = max_size->width;
geometry.max_height = max_size->height;
geometry_mask =
static_cast<GdkWindowHints>(geometry_mask | GDK_HINT_MAX_SIZE);
}
if (geometry_mask != 0) {
gtk_window_set_geometry_hints(GTK_WINDOW(window), nullptr, &geometry,
geometry_mask);
}
WindowData* data = window_data_new(GTK_WINDOW(window), view);
data->first_frame_cb_id =
g_signal_connect(view, "first-frame", G_CALLBACK(first_frame_cb), data);
// Make the resources for the view so rendering can start.
// We'll show the view when we have the first frame.
gtk_widget_realize(GTK_WIDGET(view));
g_hash_table_insert(priv->windows_by_view_id,
GINT_TO_POINTER(fl_view_get_id(view)), data);
// We don't know the current size and dimensions, so just reflect back what
// was requested.
FlWindowingSize* initial_size = size;
FlWindowState initial_state = state;
if (initial_state == FL_WINDOW_STATE_UNDEFINED) {
initial_state = FL_WINDOW_STATE_RESTORED;
}
return fl_windowing_channel_make_create_regular_response(
fl_view_get_id(view), initial_size, initial_state);
}
static FlMethodResponse* modify_regular(int64_t view_id,
FlWindowingSize* size,
const gchar* title,
FlWindowState state,
gpointer user_data) {
FlWindowingHandler* self = FL_WINDOWING_HANDLER(user_data);
WindowData* data = get_window_data(self, view_id);
if (data == nullptr) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
"Bad Arguments", "No window with given view ID", nullptr));
}
if (size != nullptr) {
gtk_window_resize(data->window, size->width, size->height);
}
if (title != nullptr) {
gtk_window_set_title(data->window, title);
}
GdkWindowState window_state;
switch (state) {
case FL_WINDOW_STATE_RESTORED:
if (gtk_window_is_maximized(data->window)) {
gtk_window_unmaximize(data->window);
}
window_state =
gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(data->window)));
if (window_state & GDK_WINDOW_STATE_ICONIFIED) {
gtk_window_deiconify(data->window);
}
break;
case FL_WINDOW_STATE_MAXIMIZED:
gtk_window_maximize(data->window);
break;
case FL_WINDOW_STATE_MINIMIZED:
gtk_window_iconify(data->window);
break;
case FL_WINDOW_STATE_UNDEFINED:
break;
}
return fl_windowing_channel_make_modify_regular_response();
}
static FlMethodResponse* destroy_window(int64_t view_id, gpointer user_data) {
FlWindowingHandler* self = FL_WINDOWING_HANDLER(user_data);
FlWindowingHandlerPrivate* priv =
reinterpret_cast<FlWindowingHandlerPrivate*>(
fl_windowing_handler_get_instance_private(self));
WindowData* data = get_window_data(self, view_id);
if (data == nullptr) {
return FL_METHOD_RESPONSE(fl_method_error_response_new(
"Bad Arguments", "No window with given view ID", nullptr));
}
gtk_widget_destroy(GTK_WIDGET(data->window));
g_hash_table_remove(priv->windows_by_view_id, GINT_TO_POINTER(view_id));
return fl_windowing_channel_make_destroy_window_response();
}
static void fl_windowing_handler_dispose(GObject* object) {
FlWindowingHandler* self = FL_WINDOWING_HANDLER(object);
FlWindowingHandlerPrivate* priv =
reinterpret_cast<FlWindowingHandlerPrivate*>(
fl_windowing_handler_get_instance_private(self));
g_weak_ref_clear(&priv->engine);
g_clear_object(&priv->channel);
g_clear_pointer(&priv->windows_by_view_id, g_hash_table_unref);
G_OBJECT_CLASS(fl_windowing_handler_parent_class)->dispose(object);
}
static void fl_windowing_handler_class_init(FlWindowingHandlerClass* klass) {
G_OBJECT_CLASS(klass)->dispose = fl_windowing_handler_dispose;
klass->create_window = fl_windowing_handler_create_window;
signals[SIGNAL_CREATE_WINDOW] = g_signal_new(
"create-window", fl_windowing_handler_get_type(), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(FlWindowingHandlerClass, create_window),
g_signal_accumulator_first_wins, nullptr, nullptr, GTK_TYPE_WINDOW, 1,
fl_view_get_type());
}
static void fl_windowing_handler_init(FlWindowingHandler* self) {
FlWindowingHandlerPrivate* priv =
reinterpret_cast<FlWindowingHandlerPrivate*>(
fl_windowing_handler_get_instance_private(self));
priv->windows_by_view_id =
g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
reinterpret_cast<GDestroyNotify>(window_data_free));
}
static FlWindowingChannelVTable windowing_channel_vtable = {
.create_regular = create_regular,
.modify_regular = modify_regular,
.destroy_window = destroy_window,
};
FlWindowingHandler* fl_windowing_handler_new(FlEngine* engine) {
g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);
FlWindowingHandler* self = FL_WINDOWING_HANDLER(
g_object_new(fl_windowing_handler_get_type(), nullptr));
FlWindowingHandlerPrivate* priv =
reinterpret_cast<FlWindowingHandlerPrivate*>(
fl_windowing_handler_get_instance_private(self));
g_weak_ref_init(&priv->engine, engine);
priv->channel = fl_windowing_channel_new(
fl_engine_get_binary_messenger(engine), &windowing_channel_vtable, self);
return self;
}

View File

@ -1,47 +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_WINDOWING_HANDLER_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_WINDOWING_HANDLER_H_
#include <gtk/gtk.h>
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"
G_BEGIN_DECLS
G_DECLARE_DERIVABLE_TYPE(FlWindowingHandler,
fl_windowing_handler,
FL,
WINDOWING_HANDLER,
GObject);
struct _FlWindowingHandlerClass {
GObjectClass parent_class;
GtkWindow* (*create_window)(FlWindowingHandler* handler, FlView* view);
};
/**
* FlWindowingHandler:
*
* #FlWindowingHandler is a handler that implements the shell side
* of SystemChannels.windowing from the Flutter services library.
*/
/**
* fl_windowing_handler_new:
* @engine: an #FlEngine.
*
* Creates a new handler that implements SystemChannels.windowing from the
* Flutter services library.
*
* Returns: a new #FlWindowingHandler
*/
FlWindowingHandler* fl_windowing_handler_new(FlEngine* engine);
G_END_DECLS
#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_WINDOWING_HANDLER_H_

View File

@ -1,640 +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_windowing_handler.h"
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
#include "flutter/shell/platform/linux/testing/fl_test_gtk_logs.h"
#include "flutter/shell/platform/linux/testing/mock_gtk.h"
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
static void set_size_arg(FlValue* args,
const gchar* name,
double width,
double height) {
g_autoptr(FlValue) size_value = fl_value_new_list();
fl_value_append_take(size_value, fl_value_new_float(width));
fl_value_append_take(size_value, fl_value_new_float(height));
fl_value_set_string(args, name, size_value);
}
static FlValue* make_create_regular_args(double width, double height) {
FlValue* args = fl_value_new_map();
set_size_arg(args, "size", width, height);
return args;
}
static int64_t parse_create_regular_response(FlMethodResponse* response) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
FlValue* result = fl_method_success_response_get_result(
FL_METHOD_SUCCESS_RESPONSE(response));
EXPECT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_MAP);
FlValue* view_id_value = fl_value_lookup_string(result, "viewId");
EXPECT_NE(view_id_value, nullptr);
EXPECT_EQ(fl_value_get_type(view_id_value), FL_VALUE_TYPE_INT);
int64_t view_id = fl_value_get_int(view_id_value);
EXPECT_GT(view_id, 0);
FlValue* size_value = fl_value_lookup_string(result, "size");
EXPECT_NE(size_value, nullptr);
EXPECT_EQ(fl_value_get_type(size_value), FL_VALUE_TYPE_LIST);
EXPECT_EQ(fl_value_get_length(size_value), 2u);
EXPECT_EQ(fl_value_get_type(fl_value_get_list_value(size_value, 0)),
FL_VALUE_TYPE_FLOAT);
EXPECT_EQ(fl_value_get_type(fl_value_get_list_value(size_value, 1)),
FL_VALUE_TYPE_FLOAT);
FlValue* state_value = fl_value_lookup_string(result, "state");
EXPECT_NE(state_value, nullptr);
EXPECT_EQ(fl_value_get_type(state_value), FL_VALUE_TYPE_STRING);
return view_id;
}
static FlValue* make_modify_regular_args(int64_t view_id) {
FlValue* args = fl_value_new_map();
fl_value_set_string_take(args, "viewId", fl_value_new_int(view_id));
return args;
}
static FlValue* make_destroy_window_args(int64_t view_id) {
FlValue* args = fl_value_new_map();
fl_value_set_string_take(args, "viewId", fl_value_new_int(view_id));
return args;
}
TEST(FlWindowingHandlerTest, CreateRegular) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_window_set_default_size(::testing::_, 800, 600));
g_autoptr(FlValue) args = make_create_regular_args(800, 600);
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
parse_create_regular_response(response);
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, CreateRegularMinSize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk,
gtk_window_set_geometry_hints(
::testing::_, nullptr,
::testing::Pointee(::testing::AllOf(
::testing::Field(&GdkGeometry::min_width, 100),
::testing::Field(&GdkGeometry::min_height, 200))),
GDK_HINT_MIN_SIZE));
g_autoptr(FlValue) args = make_create_regular_args(800, 600);
set_size_arg(args, "minSize", 100, 200);
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
parse_create_regular_response(response);
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, CreateRegularMaxSize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk,
gtk_window_set_geometry_hints(
::testing::_, nullptr,
::testing::Pointee(::testing::AllOf(
::testing::Field(&GdkGeometry::max_width, 1000),
::testing::Field(&GdkGeometry::max_height, 2000))),
GDK_HINT_MAX_SIZE));
g_autoptr(FlValue) args = make_create_regular_args(800, 600);
set_size_arg(args, "maxSize", 1000, 2000);
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
parse_create_regular_response(response);
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, CreateRegularWithTitle) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk,
gtk_window_set_title(::testing::_, ::testing::StrEq("TITLE")));
g_autoptr(FlValue) args = make_create_regular_args(800, 600);
fl_value_set_string_take(args, "title", fl_value_new_string("TITLE"));
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
parse_create_regular_response(response);
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, CreateRegularMaximized) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_window_maximize(::testing::_));
g_autoptr(FlValue) args = make_create_regular_args(800, 600);
fl_value_set_string_take(args, "state",
fl_value_new_string("WindowState.maximized"));
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
parse_create_regular_response(response);
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, CreateRegularMinimized) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_window_iconify(::testing::_));
g_autoptr(FlValue) args = make_create_regular_args(800, 600);
fl_value_set_string_take(args, "state",
fl_value_new_string("WindowState.minimized"));
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
parse_create_regular_response(response);
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyRegularSize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_window_resize(::testing::_, 1024, 768));
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
g_autoptr(FlValue) modify_args = make_modify_regular_args(view_id);
set_size_arg(modify_args, "size", 1024, 768);
gboolean modify_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", modify_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&modify_called);
EXPECT_TRUE(modify_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyRegularTitle) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk,
gtk_window_set_title(::testing::_, ::testing::StrEq("TITLE")));
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
g_autoptr(FlValue) modify_args = make_modify_regular_args(view_id);
fl_value_set_string_take(modify_args, "title", fl_value_new_string("TITLE"));
gboolean modify_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", modify_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&modify_called);
EXPECT_TRUE(modify_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyRegularMaximize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
EXPECT_CALL(mock_gtk, gtk_window_maximize(::testing::_));
g_autoptr(FlValue) modify_args = make_modify_regular_args(view_id);
fl_value_set_string_take(modify_args, "state",
fl_value_new_string("WindowState.maximized"));
gboolean modify_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", modify_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&modify_called);
EXPECT_TRUE(modify_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyRegularUnmaximize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_window_maximize(::testing::_));
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
fl_value_set_string_take(create_args, "state",
fl_value_new_string("WindowState.maximized"));
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
EXPECT_CALL(mock_gtk, gtk_window_is_maximized(::testing::_))
.WillOnce(::testing::Return(TRUE));
EXPECT_CALL(mock_gtk, gtk_window_unmaximize(::testing::_));
g_autoptr(FlValue) modify_args = make_modify_regular_args(view_id);
fl_value_set_string_take(modify_args, "state",
fl_value_new_string("WindowState.restored"));
gboolean modify_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", modify_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&modify_called);
EXPECT_TRUE(modify_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyRegularMinimize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
EXPECT_CALL(mock_gtk, gtk_window_iconify(::testing::_));
g_autoptr(FlValue) modify_args = make_modify_regular_args(view_id);
fl_value_set_string_take(modify_args, "state",
fl_value_new_string("WindowState.minimized"));
gboolean modify_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", modify_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&modify_called);
EXPECT_TRUE(modify_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyRegularUnminimize) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_window_iconify(::testing::_));
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
fl_value_set_string_take(create_args, "state",
fl_value_new_string("WindowState.minimized"));
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
EXPECT_CALL(mock_gtk, gdk_window_get_state(::testing::_))
.WillOnce(::testing::Return(GDK_WINDOW_STATE_ICONIFIED));
EXPECT_CALL(mock_gtk, gtk_window_deiconify(::testing::_));
g_autoptr(FlValue) modify_args = make_modify_regular_args(view_id);
fl_value_set_string_take(modify_args, "state",
fl_value_new_string("WindowState.restored"));
gboolean modify_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", modify_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&modify_called);
EXPECT_TRUE(modify_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, ModifyUnknownWindow) {
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
g_autoptr(FlValue) args = make_modify_regular_args(99);
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "modifyRegular", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
EXPECT_STREQ(fl_method_error_response_get_code(
FL_METHOD_ERROR_RESPONSE(response)),
"Bad Arguments");
EXPECT_STREQ(fl_method_error_response_get_message(
FL_METHOD_ERROR_RESPONSE(response)),
"No window with given view ID");
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, DestroyWindow) {
flutter::testing::fl_ensure_gtk_init();
::testing::NiceMock<flutter::testing::MockGtk> mock_gtk;
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
EXPECT_CALL(mock_gtk, gtk_window_new);
EXPECT_CALL(mock_gtk, gtk_widget_destroy);
g_autoptr(FlValue) create_args = make_create_regular_args(800, 600);
int64_t view_id = -1;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "createRegular", create_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
int64_t* view_id = static_cast<int64_t*>(user_data);
*view_id = parse_create_regular_response(response);
},
&view_id);
EXPECT_GT(view_id, 0);
g_autoptr(FlValue) destroy_args = make_destroy_window_args(view_id);
gboolean destroy_called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "destroyWindow", destroy_args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&destroy_called);
EXPECT_TRUE(destroy_called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}
TEST(FlWindowingHandlerTest, DestroyUnknownWindow) {
g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
g_autoptr(FlEngine) engine =
fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
g_autoptr(FlWindowingHandler) handler = fl_windowing_handler_new(engine);
g_autoptr(FlValue) args = make_destroy_window_args(99);
gboolean called = FALSE;
fl_mock_binary_messenger_invoke_standard_method(
messenger, "flutter/windowing", "destroyWindow", args,
[](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
gpointer user_data) {
EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
EXPECT_STREQ(fl_method_error_response_get_code(
FL_METHOD_ERROR_RESPONSE(response)),
"Bad Arguments");
EXPECT_STREQ(fl_method_error_response_get_message(
FL_METHOD_ERROR_RESPONSE(response)),
"No window with given view ID");
gboolean* called = static_cast<gboolean*>(user_data);
*called = TRUE;
},
&called);
EXPECT_TRUE(called);
fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
}