fix(engine/linux): adjust GTK4 geometry sizing and compositor dimensions

This commit is contained in:
Rich Young 2026-02-05 19:42:40 -05:00
parent 5c64528a0d
commit 03480d5d4a
4 changed files with 59 additions and 12 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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) {