Skip to content
This repository was archived by the owner on Dec 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion plugins/color_panel/gtk/color_panel_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// See color_panel.dart for documentation.
const char kChannelName[] = "flutter/colorpanel";
const char kNoScreenError[] = "No Screen";
const char kShowColorPanelMethod[] = "ColorPanel.Show";
const char kColorPanelShowAlpha[] = "ColorPanel.ShowAlpha";
const char kHideColorPanelMethod[] = "ColorPanel.Hide";
Expand Down Expand Up @@ -92,9 +93,14 @@ static FlMethodResponse* show_color_panel(FlColorPanelPlugin* self,
gboolean use_alpha =
use_alpha_value != nullptr ? fl_value_get_bool(use_alpha_value) : FALSE;

FlView* view = fl_plugin_registrar_get_view(self->registrar);
if (view == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

self->color_chooser_dialog = GTK_COLOR_CHOOSER_DIALOG(
gtk_color_chooser_dialog_new(kWindowTitle, nullptr));
FlView* view = fl_plugin_registrar_get_view(self->registrar);
GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
gtk_window_set_transient_for(GTK_WINDOW(self->color_chooser_dialog), window);
gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(self->color_chooser_dialog),
Expand Down
6 changes: 6 additions & 0 deletions plugins/file_chooser/gtk/file_chooser_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// See channel_controller.dart for documentation.
const char kChannelName[] = "flutter/filechooser";
const char kBadArgumentsError[] = "Bad Arguments";
const char kNoScreenError[] = "No Screen";
const char kShowOpenPanelMethod[] = "FileChooser.Show.Open";
const char kShowSavePanelMethod[] = "FileChooser.Show.Save";
const char kInitialDirectoryKey[] = "initialDirectory";
Expand Down Expand Up @@ -84,6 +85,11 @@ static FlMethodResponse* show_dialog(FlFileChooserPlugin* self,
confirm_button_text = fl_value_get_string(value);

FlView* view = fl_plugin_registrar_get_view(self->registrar);
if (view == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
g_autoptr(GtkFileChooserNative) dialog =
GTK_FILE_CHOOSER_NATIVE(gtk_file_chooser_native_new(
Expand Down
12 changes: 10 additions & 2 deletions plugins/menubar/gtk/menubar_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// See menu_channel.dart for documentation.
const char kChannelName[] = "flutter/menubar";
const char kBadArgumentsError[] = "Bad Arguments";
const char kNoScreenError[] = "No Screen";
const char kFailureError[] = "Failure";
const char kMenuSetMethod[] = "Menubar.SetMenu";
const char kMenuItemSelectedCallbackMethod[] = "Menubar.SelectedCallback";
Expand Down Expand Up @@ -145,6 +146,11 @@ static FlMethodResponse* menu_set(FlMenubarPlugin* self, FlValue* args) {
}

FlView* view = fl_plugin_registrar_get_view(self->registrar);
if (view == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

GtkApplication* app = gtk_window_get_application(
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))));
if (app == nullptr) {
Expand Down Expand Up @@ -213,8 +219,10 @@ FlMenubarPlugin* fl_menubar_plugin_new(FlPluginRegistrar* registrar) {

// Add a GAction for the menubar to trigger.
FlView* view = fl_plugin_registrar_get_view(self->registrar);
GtkApplication* app = gtk_window_get_application(
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))));
GtkApplication* app = nullptr;
if (view != nullptr)
app = gtk_window_get_application(
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))));
if (app != nullptr) {
g_autoptr(GSimpleAction) inactive_action =
g_simple_action_new("flutter-menu-inactive", nullptr);
Expand Down
33 changes: 33 additions & 0 deletions plugins/window_size/gtk/window_size_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// See window_size_channel.dart for documentation.
const char kChannelName[] = "flutter/windowsize";
const char kBadArgumentsError[] = "Bad Arguments";
const char kNoScreenError[] = "No Screen";
const char kGetScreenListMethod[] = "getScreenList";
const char kGetWindowInfoMethod[] = "getWindowInfo";
const char kSetWindowFrameMethod[] = "setWindowFrame";
Expand Down Expand Up @@ -49,12 +50,16 @@ G_DEFINE_TYPE(FlWindowSizePlugin, fl_window_size_plugin, g_object_get_type())
// Gets the window being controlled.
GtkWindow* get_window(FlWindowSizePlugin* self) {
FlView* view = fl_plugin_registrar_get_view(self->registrar);
if (view == nullptr) return nullptr;

return GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
}

// Gets the display connection.
GdkDisplay* get_display(FlWindowSizePlugin* self) {
FlView* view = fl_plugin_registrar_get_view(self->registrar);
if (view == nullptr) return nullptr;

return gtk_widget_get_display(GTK_WIDGET(view));
}

Expand Down Expand Up @@ -97,6 +102,11 @@ static FlMethodResponse* get_screen_list(FlWindowSizePlugin* self) {
g_autoptr(FlValue) screens = fl_value_new_list();

GdkDisplay* display = get_display(self);
if (display == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

gint n_monitors = gdk_display_get_n_monitors(display);
for (gint i = 0; i < n_monitors; i++) {
GdkMonitor* monitor = gdk_display_get_monitor(display, i);
Expand All @@ -109,6 +119,10 @@ static FlMethodResponse* get_screen_list(FlWindowSizePlugin* self) {
// Gets information about the Flutter window.
static FlMethodResponse* get_window_info(FlWindowSizePlugin* self) {
GtkWindow* window = get_window(self);
if (window == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

g_autoptr(FlValue) window_info = fl_value_new_map();

Expand Down Expand Up @@ -158,6 +172,11 @@ static FlMethodResponse* set_window_frame(FlWindowSizePlugin* self,
double height = fl_value_get_float(fl_value_get_list_value(args, 3));

GtkWindow* window = get_window(self);
if (window == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

gtk_window_move(window, static_cast<gint>(x), static_cast<gint>(y));
gtk_window_resize(window, static_cast<gint>(width),
static_cast<gint>(height));
Expand All @@ -183,6 +202,11 @@ static FlMethodResponse* set_window_minimum_size(FlWindowSizePlugin* self,
double width = fl_value_get_float(fl_value_get_list_value(args, 0));
double height = fl_value_get_float(fl_value_get_list_value(args, 1));

if (get_window() == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

if (width >= 0 && height >= 0) {
self->window_geometry.min_width = static_cast<gint>(width);
self->window_geometry.min_height = static_cast<gint>(height);
Expand All @@ -204,6 +228,11 @@ static FlMethodResponse* set_window_maximum_size(FlWindowSizePlugin* self,
double width = fl_value_get_float(fl_value_get_list_value(args, 0));
double height = fl_value_get_float(fl_value_get_list_value(args, 1));

if (get_window() == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}

self->window_geometry.max_width = static_cast<gint>(width);
self->window_geometry.max_height = static_cast<gint>(height);

Expand All @@ -221,6 +250,10 @@ static FlMethodResponse* set_window_title(FlWindowSizePlugin* self,
}

GtkWindow* window = get_window(self);
if (window == nullptr) {
return FL_METHOD_RESPONSE(
fl_method_error_response_new(kNoScreenError, nullptr, nullptr));
}
gtk_window_set_title(window, fl_value_get_string(args));

return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
Expand Down
1 change: 1 addition & 0 deletions testbed/gtk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
add_executable(${BINARY_NAME}
"main.cc"
"fl_application.cc"
"fl_headless_application.cc"
"window_configuration.cc"
"${FLUTTER_MANAGED_DIR}/gtk_plugin_registrant.cc"
)
Expand Down
49 changes: 49 additions & 0 deletions testbed/gtk/fl_headless_application.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "fl_headless_application.h"

#include <flutter_linux/flutter_linux.h>
#include <flutter_linux/fl_engine_extra.h>

#include "flutter/gtk_plugin_registrant.h"

struct _FlHeadlessApplication {
GApplication parent_instance;

FlEngine* engine;
};

G_DEFINE_TYPE(FlHeadlessApplication, fl_headless_application,
G_TYPE_APPLICATION)

// Implements GApplication::activate.
static void fl_headless_application_activate(GApplication* application) {
FlHeadlessApplication* self = FL_HEADLESS_APPLICATION(application);

g_autoptr(FlDartProject) project = fl_dart_project_new();
self->engine = fl_engine_new_headless(project);

g_application_hold(application);

fl_register_plugins(FL_PLUGIN_REGISTRY(self->engine));
}

// Implements GObject::dispose.
static void fl_headless_application_dispose(GObject* object) {
FlHeadlessApplication* self = FL_HEADLESS_APPLICATION(object);

g_clear_object(&self->engine);

G_OBJECT_CLASS(fl_headless_application_parent_class)->dispose(object);
}

static void fl_headless_application_class_init(
FlHeadlessApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = fl_headless_application_activate;
G_OBJECT_CLASS(klass)->dispose = fl_headless_application_dispose;
}

static void fl_headless_application_init(FlHeadlessApplication* self) {}

FlHeadlessApplication* fl_headless_application_new() {
return FL_HEADLESS_APPLICATION(
g_object_new(fl_headless_application_get_type(), nullptr));
}
19 changes: 19 additions & 0 deletions testbed/gtk/fl_headless_application.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef FLUTTER_FL_HEADLESS_APPLICATION_H_
#define FLUTTER_FL_HEADLESS_APPLICATION_H_

#include <gio/gio.h>

G_DECLARE_FINAL_TYPE(FlHeadlessApplication, fl_headless_application, FL,
HEADLESS_APPLICATION, GApplication)

/**
* fl_headless_application_new:
*
* Creates a new Flutter headless application.
*
* Returns: a new #FlHeadlessApplication.
*/
FlHeadlessApplication* fl_headless_application_new();

#endif // FLUTTER_FL_HEADLESS_APPLICATION_H_

11 changes: 9 additions & 2 deletions testbed/gtk/main.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#include "fl_application.h"
#include "fl_headless_application.h"

int main(int argc, char** argv) {
g_autoptr(FlApplication) app = fl_application_new();
return g_application_run(G_APPLICATION(app), argc, argv);
g_autoptr(GApplication) app = nullptr;

if (gdk_init_check(&argc, &argv))
app = G_APPLICATION(fl_application_new());
else
app = G_APPLICATION(fl_headless_application_new());

return g_application_run(app, argc, argv);
}