77
88#include " flutter/generated_plugin_registrant.h"
99
10- struct _MyApplication {
10+ struct _MyApplication
11+ {
1112 GtkApplication parent_instance;
12- char ** dart_entrypoint_arguments;
13+ char ** dart_entrypoint_arguments;
1314};
1415
1516G_DEFINE_TYPE (MyApplication, my_application, GTK_TYPE_APPLICATION)
1617
17- // Implements GApplication::activate.
18- static void my_application_activate(GApplication* application) {
19- MyApplication* self = MY_APPLICATION (application);
18+ // Called when first Flutter frame received.
19+ static void first_frame_cb(MyApplication *self, FlView *view)
20+ {
21+ gtk_widget_show (gtk_widget_get_toplevel (GTK_WIDGET (view)));
22+ }
2023
21- GList* windows = gtk_application_get_windows (GTK_APPLICATION (application));
22- if (windows) {
23- gtk_window_present (GTK_WINDOW (windows->data ));
24- return ;
24+ // Implements GApplication::activate.
25+ static void my_application_activate (GApplication *application)
26+ {
27+ MyApplication *self = MY_APPLICATION (application);
28+
29+ GList *windows = gtk_application_get_windows (GTK_APPLICATION (application));
30+ if (windows)
31+ {
32+ gtk_window_present (GTK_WINDOW (windows->data ));
33+ return ;
2534 }
2635
27- GtkWindow* window =
36+ GtkWindow * window =
2837 GTK_WINDOW (gtk_application_window_new (GTK_APPLICATION (application)));
29-
3038 // Use a header bar when running in GNOME as this is the common style used
3139 // by applications and is the setup most users will be using (e.g. Ubuntu
3240 // desktop).
@@ -36,19 +44,24 @@ static void my_application_activate(GApplication* application) {
3644 // if future cases occur).
3745 gboolean use_header_bar = TRUE ;
3846#ifdef GDK_WINDOWING_X11
39- GdkScreen* screen = gtk_window_get_screen (window);
40- if (GDK_IS_X11_SCREEN (screen)) {
41- const gchar* wm_name = gdk_x11_screen_get_window_manager_name (screen);
42- if (g_strcmp0 (wm_name, " GNOME Shell" ) != 0 ) {
47+ GdkScreen *screen = gtk_window_get_screen (window);
48+ if (GDK_IS_X11_SCREEN (screen))
49+ {
50+ const gchar *wm_name = gdk_x11_screen_get_window_manager_name (screen);
51+ if (g_strcmp0 (wm_name, " GNOME Shell" ) != 0 )
52+ {
4353 use_header_bar = FALSE ;
4454 }
4555 }
4656#endif
47- if (use_header_bar) {
48-
49- } else {
57+ if (use_header_bar)
58+ {
59+ }
60+ else
61+ {
5062 gtk_window_set_title (window, " MusicPod" );
5163 }
64+
5265 GdkGeometry geometry_min;
5366 geometry_min.min_width = 500 ;
5467 geometry_min.min_height = 700 ;
@@ -58,27 +71,38 @@ static void my_application_activate(GApplication* application) {
5871 g_autoptr (FlDartProject) project = fl_dart_project_new ();
5972 fl_dart_project_set_dart_entrypoint_arguments (project, self->dart_entrypoint_arguments );
6073
61- FlView* view = fl_view_new (project);
74+ FlView * view = fl_view_new (project);
6275 gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (view));
6376
6477 fl_register_plugins (FL_PLUGIN_REGISTRY (view));
78+ // Background defaults to black, override it here if necessary, e.g. #00000000 for transparent.
79+ GdkRGBA background_color;
80+ gdk_rgba_parse (&background_color, " #00000000" );
81+ fl_view_set_background_color (view, &background_color);
82+
83+ // Show the window when Flutter renders.
84+ // Requires the view to be realized so we can start rendering.
85+ g_signal_connect_swapped (view, " first-frame" , G_CALLBACK (first_frame_cb), self);
86+ gtk_widget_realize (GTK_WIDGET (view));
6587
66- gtk_widget_show (GTK_WIDGET (window));
6788 gtk_widget_show (GTK_WIDGET (view));
89+
6890 gtk_widget_grab_focus (GTK_WIDGET (view));
6991}
7092
7193// Implements GApplication::local_command_line.
72- static gboolean my_application_local_command_line (GApplication* application, gchar*** arguments, int * exit_status) {
73- MyApplication* self = MY_APPLICATION (application);
94+ static gboolean my_application_local_command_line (GApplication *application, gchar ***arguments, int *exit_status)
95+ {
96+ MyApplication *self = MY_APPLICATION (application);
7497 // Strip out the first argument as it is the binary name.
7598 self->dart_entrypoint_arguments = g_strdupv (*arguments + 1 );
7699
77100 g_autoptr (GError) error = nullptr ;
78- if (!g_application_register (application, nullptr , &error)) {
79- g_warning (" Failed to register: %s" , error->message );
80- *exit_status = 1 ;
81- return TRUE ;
101+ if (!g_application_register (application, nullptr , &error))
102+ {
103+ g_warning (" Failed to register: %s" , error->message );
104+ *exit_status = 1 ;
105+ return TRUE ;
82106 }
83107
84108 g_application_activate (application);
@@ -88,41 +112,52 @@ static gboolean my_application_local_command_line(GApplication* application, gch
88112}
89113
90114// Implements GApplication::startup.
91- static void my_application_startup (GApplication* application) {
92- // MyApplication* self = MY_APPLICATION(object);
115+ static void my_application_startup (GApplication *application)
116+ {
117+ // MyApplication* self = MY_APPLICATION(object);
93118
94119 // Perform any actions required at application startup.
95120
96121 G_APPLICATION_CLASS (my_application_parent_class)->startup (application);
97122}
98123
99124// Implements GApplication::shutdown.
100- static void my_application_shutdown (GApplication* application) {
101- // MyApplication* self = MY_APPLICATION(object);
125+ static void my_application_shutdown (GApplication *application)
126+ {
127+ // MyApplication* self = MY_APPLICATION(object);
102128
103129 // Perform any actions required at application shutdown.
104130
105131 G_APPLICATION_CLASS (my_application_parent_class)->shutdown (application);
106132}
107133
108134// Implements GObject::dispose.
109- static void my_application_dispose (GObject* object) {
110- MyApplication* self = MY_APPLICATION (object);
135+ static void my_application_dispose (GObject *object)
136+ {
137+ MyApplication *self = MY_APPLICATION (object);
111138 g_clear_pointer (&self->dart_entrypoint_arguments , g_strfreev);
112139 G_OBJECT_CLASS (my_application_parent_class)->dispose (object);
113140}
114141
115- static void my_application_class_init (MyApplicationClass* klass) {
142+ static void my_application_class_init (MyApplicationClass *klass)
143+ {
116144 G_APPLICATION_CLASS (klass)->activate = my_application_activate;
117145 G_APPLICATION_CLASS (klass)->local_command_line = my_application_local_command_line;
118146 G_APPLICATION_CLASS (klass)->startup = my_application_startup;
119147 G_APPLICATION_CLASS (klass)->shutdown = my_application_shutdown;
120148 G_OBJECT_CLASS (klass)->dispose = my_application_dispose;
121149}
122150
123- static void my_application_init (MyApplication* self) {}
151+ static void my_application_init (MyApplication *self) {}
152+
153+ MyApplication *my_application_new ()
154+ {
155+ // Set the program name to the application ID, which helps various systems
156+ // like GTK and desktop environments map this running application to its
157+ // corresponding .desktop file. This ensures better integration by allowing
158+ // the application to be recognized beyond its binary name.
159+ g_set_prgname (APPLICATION_ID);
124160
125- MyApplication* my_application_new () {
126161 return MY_APPLICATION (g_object_new (
127162 my_application_get_type (), " application-id" , APPLICATION_ID, " flags" ,
128163 G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,
0 commit comments