diff --git a/engine/src/flutter/shell/platform/linux/fl_compositor_opengl.cc b/engine/src/flutter/shell/platform/linux/fl_compositor_opengl.cc index d5b6f27b05c..a64dcd64d01 100644 --- a/engine/src/flutter/shell/platform/linux/fl_compositor_opengl.cc +++ b/engine/src/flutter/shell/platform/linux/fl_compositor_opengl.cc @@ -375,8 +375,13 @@ static gboolean fl_compositor_opengl_render(FlCompositor* compositor, // If frame not ready, then wait for it. gint scale_factor = fl_gtk_surface_get_scale_factor(surface); +#if FLUTTER_LINUX_GTK4 + size_t width = fl_gtk_surface_get_width(surface); + size_t height = fl_gtk_surface_get_height(surface); +#else size_t width = fl_gtk_surface_get_width(surface) * scale_factor; size_t height = fl_gtk_surface_get_height(surface) * scale_factor; +#endif while (fl_framebuffer_get_width(self->framebuffer) != width || fl_framebuffer_get_height(self->framebuffer) != height) { g_mutex_unlock(&self->frame_mutex); diff --git a/engine/src/flutter/shell/platform/linux/fl_compositor_software.cc b/engine/src/flutter/shell/platform/linux/fl_compositor_software.cc index f042753ddd5..3151d940328 100644 --- a/engine/src/flutter/shell/platform/linux/fl_compositor_software.cc +++ b/engine/src/flutter/shell/platform/linux/fl_compositor_software.cc @@ -83,8 +83,13 @@ static gboolean fl_compositor_software_render(FlCompositor* compositor, // If frame not ready, then wait for it. gint scale_factor = fl_gtk_surface_get_scale_factor(surface); +#if FLUTTER_LINUX_GTK4 + size_t width = fl_gtk_surface_get_width(surface); + size_t height = fl_gtk_surface_get_height(surface); +#else size_t width = fl_gtk_surface_get_width(surface) * scale_factor; size_t height = fl_gtk_surface_get_height(surface) * scale_factor; +#endif while (self->width != width || self->height != height) { g_mutex_unlock(&self->frame_mutex); fl_task_runner_wait(self->task_runner); diff --git a/engine/src/flutter/shell/platform/linux/fl_view.cc b/engine/src/flutter/shell/platform/linux/fl_view.cc index bb4f8197abc..2eb952a2a83 100644 --- a/engine/src/flutter/shell/platform/linux/fl_view.cc +++ b/engine/src/flutter/shell/platform/linux/fl_view.cc @@ -117,6 +117,14 @@ static void fl_renderable_iface_init(FlRenderableInterface* iface); static void fl_view_plugin_registry_iface_init( FlPluginRegistryInterface* iface); +static void log_once(bool* flag, const char* message) { + if (*flag) { + return; + } + *flag = true; + g_warning("%s", message); +} + G_DEFINE_TYPE_WITH_CODE( FlView, fl_view, @@ -167,8 +175,8 @@ static gboolean window_delete_event_cb(FlView* self) { static gboolean window_close_request_cb(GtkWindow* window, FlView* self) { (void)window; fl_engine_request_app_exit(self->engine); - // Stop the event from propagating. - return TRUE; + // Allow the default handler to destroy the window if the engine doesn't. + return FALSE; } #endif @@ -251,11 +259,18 @@ static void setup_cursor(FlView* self) { } // Updates the engine with the current window metrics. -static void handle_geometry_changed(FlView* self) { - GtkAllocation allocation; - gtk_widget_get_allocation(GTK_WIDGET(self), &allocation); +static void handle_geometry_changed_with_size(FlView* self, + int width, + int height) { gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(self)); + if (width == 0 || height == 0) { + static bool logged_zero_allocation = false; + log_once(&logged_zero_allocation, + "handle_geometry_changed: zero-size allocation"); + return; + } + // Note we can't detect if a window is moved between monitors - this // information is provided by Wayland but GTK only notifies us if the scale // has changed, so moving between two monitors of the same scale doesn't @@ -276,9 +291,21 @@ static void handle_geometry_changed(FlView* self) { display_id = fl_display_monitor_get_display_id( fl_engine_get_display_monitor(self->engine), monitor); } - fl_engine_send_window_metrics_event( - self->engine, display_id, self->view_id, allocation.width * scale_factor, - allocation.height * scale_factor, scale_factor); + fl_engine_send_window_metrics_event(self->engine, display_id, self->view_id, + width * scale_factor, + height * scale_factor, scale_factor); +} + +static void handle_geometry_changed(FlView* self) { +#if FLUTTER_LINUX_GTK4 + int width = gtk_widget_get_width(GTK_WIDGET(self->render_area)); + int height = gtk_widget_get_height(GTK_WIDGET(self->render_area)); + handle_geometry_changed_with_size(self, width, height); +#else + GtkAllocation allocation; + gtk_widget_get_allocation(GTK_WIDGET(self), &allocation); + handle_geometry_changed_with_size(self, allocation.width, allocation.height); +#endif } static void view_added_cb(GObject* object, @@ -332,6 +359,12 @@ static void fl_view_present_layers(FlRenderable* renderable, size_t layers_count) { FlView* self = FL_VIEW(renderable); + if (layers_count > 0 && layers[0] != nullptr) { + static bool logged_first_layers = false; + log_once(&logged_first_layers, + "fl_view_present_layers: received first frame layers"); + } + fl_compositor_present_layers(self->compositor, layers, layers_count); // Perform the redraw in the GTK thead. @@ -802,9 +835,7 @@ static void size_allocate_cb(FlView* self) { #if FLUTTER_LINUX_GTK4 static void resize_cb(FlView* self, int width, int height) { - (void)width; - (void)height; - handle_geometry_changed(self); + handle_geometry_changed_with_size(self, width, height); } #endif @@ -843,6 +874,12 @@ static gboolean draw_cb(FlView* self, cairo_t* cr) { gdk_gl_context_clear_current(); } + if (!result) { + static bool logged_render_false = false; + log_once(&logged_render_false, + "draw_cb: compositor render returned false"); + } + return result; } diff --git a/engine/src/flutter/shell/platform/linux/fl_window_monitor.cc b/engine/src/flutter/shell/platform/linux/fl_window_monitor.cc index 7024392edb8..39c33ec5f91 100644 --- a/engine/src/flutter/shell/platform/linux/fl_window_monitor.cc +++ b/engine/src/flutter/shell/platform/linux/fl_window_monitor.cc @@ -59,7 +59,7 @@ static void title_notify_cb(FlWindowMonitor* self) { static gboolean close_request_cb(FlWindowMonitor* self) { flutter::IsolateScope scope(self->isolate); self->on_close(); - return TRUE; + return FALSE; } #else static gboolean delete_event_cb(FlWindowMonitor* self, GdkEvent* event) {