From 036087097b6de0be2ad00a99b5ee84d9ad2ad152 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 26 Nov 2025 19:16:19 +0100 Subject: [PATCH] Fix initial scale of wxGLCanvas under EGL/Wayland The scale of the canvas was set up correctly only once we received "size-allocate" signal from GTK, but this doesn't necessarily happen when the window is first shown and after its scale factor is actually known. Ensure that we use the correct scale by catching the notification about its change too. This makes buffer scale factor correct from the very beginning, without having to wait for a resize. See #23733, #25465. --- include/wx/unix/glegl.h | 2 +- src/unix/glegl.cpp | 33 ++++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/include/wx/unix/glegl.h b/include/wx/unix/glegl.h index a83448bd14..fcdf567d2b 100644 --- a/include/wx/unix/glegl.h +++ b/include/wx/unix/glegl.h @@ -148,7 +148,7 @@ private: static EGLConfig ms_glEGLConfig; friend void wxEGLUpdatePosition(wxGLCanvasEGL* win); - friend void wxEGLSetScale(wxGLCanvasEGL* win, int scale); + friend void wxEGLUpdateGeometry(GtkWidget* widget, wxGLCanvasEGL* win); }; // ---------------------------------------------------------------------------- diff --git a/src/unix/glegl.cpp b/src/unix/glegl.cpp index 78f8f3a6e0..2f4fef6992 100644 --- a/src/unix/glegl.cpp +++ b/src/unix/glegl.cpp @@ -436,9 +436,17 @@ void wxEGLUpdatePosition(wxGLCanvasEGL* win) wl_subsurface_set_position(win->m_wlSubsurface, x, y); } -// Helper declared as friend in the header and so can access m_wlSurface. -void wxEGLSetScale(wxGLCanvasEGL* win, int scale) +// Helper declared as friend in the header and so can access member variables. +// +// Used when size or scale factor changes +void wxEGLUpdateGeometry(GtkWidget* widget, wxGLCanvasEGL* win) { + int scale = gtk_widget_get_scale_factor(widget); + wl_egl_window_resize(win->m_wlEGLWindow, win->m_width * scale, + win->m_height * scale, 0, 0); + + wxEGLUpdatePosition(win); + wl_surface_set_buffer_scale(win->m_wlSurface, scale); } @@ -497,12 +505,14 @@ static void gtk_glcanvas_size_callback(GtkWidget *widget, GtkAllocation *, wxGLCanvasEGL *win) { - int scale = gtk_widget_get_scale_factor(widget); - wl_egl_window_resize(win->m_wlEGLWindow, win->m_width * scale, - win->m_height * scale, 0, 0); + wxEGLUpdateGeometry(widget, win); +} - wxEGLUpdatePosition(win); - wxEGLSetScale(win, scale); +static void gtk_glcanvas_scale_factor_notify(GtkWidget* widget, + GParamSpec*, + wxGLCanvasEGL *win) +{ + wxEGLUpdateGeometry(widget, win); } } // extern "C" @@ -574,8 +584,17 @@ bool wxGLCanvasEGL::CreateSurface() // Not unmapping the canvas as soon as possible causes problems when reparenting g_signal_connect(m_widget, "unmap", G_CALLBACK(gtk_glcanvas_unmap_callback), this); + + // We connect to "size-allocate" to update the position of the + // subsurface when the toplevel window is moved, which also updates the + // scale as a side effect, but we need to also separately connect to + // "notify::scale-factor" to catch scale changes, which is especially + // important initially, as we don't get a "size-allocate" with the + // correct scale when the window is created. g_signal_connect(m_widget, "size-allocate", G_CALLBACK(gtk_glcanvas_size_callback), this); + g_signal_connect(m_widget, "notify::scale-factor", + G_CALLBACK (gtk_glcanvas_scale_factor_notify), this); } #endif