@@ -227,11 +227,17 @@ void GPUDisplayFrontendGlfw::scroll_callback(GLFWwindow* window, double x, doubl
227227
228228void GPUDisplayFrontendGlfw::cursorPos_callback (GLFWwindow* window, double x, double y)
229229{
230- me->mMouseMvX = x;
231- me->mMouseMvY = y;
230+ me->mMouseMvX = x * me-> mPixelRatio ; // Window coordinates to framebuffer pixels
231+ me->mMouseMvY = y * me-> mPixelRatio ;
232232}
233233
234- void GPUDisplayFrontendGlfw::resize_callback (GLFWwindow* window, int32_t width, int32_t height) { me->ResizeScene (width, height); }
234+ void GPUDisplayFrontendGlfw::resize_callback (GLFWwindow* window, int32_t width, int32_t height) // Framebuffer size in pixels
235+ {
236+ int32_t windowWidth, windowHeight;
237+ glfwGetWindowSize (window, &windowWidth, &windowHeight);
238+ me->mPixelRatio = windowWidth ? (double )width / windowWidth : 1 .;
239+ me->ResizeScene (width, height);
240+ }
235241
236242void GPUDisplayFrontendGlfw::focus_callback (GLFWwindow* window, int32_t focused)
237243{
@@ -240,7 +246,22 @@ void GPUDisplayFrontendGlfw::focus_callback(GLFWwindow* window, int32_t focused)
240246 }
241247}
242248
243- void GPUDisplayFrontendGlfw::maximize_callback (GLFWwindow* window, int32_t maximized) { me->setWindowState (glfwGetWindowMonitor (window) != nullptr , maximized); }
249+ void GPUDisplayFrontendGlfw::contentScale_callback (GLFWwindow* window, float xscale, float yscale)
250+ {
251+ me->mScale = xscale;
252+ }
253+
254+ void GPUDisplayFrontendGlfw::maximize_callback (GLFWwindow* window, int32_t maximized)
255+ {
256+ me->setWindowState (glfwGetWindowMonitor (window) != nullptr , maximized);
257+ if (glfwGetPlatform () == GLFW_PLATFORM_WAYLAND ) { // Called before the resize. GLFW keeps the maximized size if the compositor leaves the size to the client when unmaximizing, so restore the last windowed size
258+ if (maximized) {
259+ glfwGetWindowSize (window, &me->mWindowedWidth , &me->mWindowedHeight );
260+ } else {
261+ me->mRestoreWindowedSize = true ; // Must be applied after GLFW has processed the configure event, otherwise GLFW resizes to the pending maximized size again
262+ }
263+ }
264+ }
244265
245266#ifndef GPUCA_STANDALONE
246267void GPUDisplayFrontendGlfw::DisplayLoop ()
@@ -273,6 +294,7 @@ int32_t GPUDisplayFrontendGlfw::FrontendMain()
273294 glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT , 0 );
274295 glfwWindowHint (GLFW_OPENGL_PROFILE , mBackend ->CoreProfile () ? GLFW_OPENGL_CORE_PROFILE : GLFW_OPENGL_COMPAT_PROFILE );
275296 }
297+ glfwWindowHint (GLFW_SCALE_TO_MONITOR , GLFW_TRUE ); // Initial size scaled by the content scale on X11 / Win32
276298 mWindow = glfwCreateWindow (INIT_WIDTH , INIT_HEIGHT , DISPLAY_WINDOW_NAME , nullptr , nullptr );
277299 if (!mWindow ) {
278300 fprintf (stderr, " Error creating glfw window\n " );
@@ -288,10 +310,19 @@ int32_t GPUDisplayFrontendGlfw::FrontendMain()
288310 glfwSetMouseButtonCallback (mWindow , mouseButton_callback);
289311 glfwSetScrollCallback (mWindow , scroll_callback);
290312 glfwSetCursorPosCallback (mWindow , cursorPos_callback);
291- glfwSetWindowSizeCallback (mWindow , resize_callback);
313+ glfwSetFramebufferSizeCallback (mWindow , resize_callback);
292314 glfwSetWindowMaximizeCallback (mWindow , maximize_callback);
293315 glfwSetWindowFocusCallback (mWindow , focus_callback);
294- glfwSetWindowSizeLimits (mWindow , MIN_WIDTH , MIN_HEIGHT , GLFW_DONT_CARE , GLFW_DONT_CARE );
316+ float xscale, yscale;
317+ glfwGetWindowContentScale (mWindow , &xscale, &yscale);
318+ contentScale_callback (mWindow , xscale, yscale);
319+ glfwSetWindowContentScaleCallback (mWindow , contentScale_callback);
320+ const float limitScale = (glfwGetPlatform () == GLFW_PLATFORM_X11 || glfwGetPlatform () == GLFW_PLATFORM_WIN32 ) ? mScale : 1 .f ; // Window coordinates are pixels on X11 / Win32, logical on Wayland / macOS
321+ glfwSetWindowSizeLimits (mWindow , MIN_WIDTH * limitScale, MIN_HEIGHT * limitScale, GLFW_DONT_CARE , GLFW_DONT_CARE );
322+ int32_t fbWidth, fbHeight, windowWidth, windowHeight;
323+ glfwGetFramebufferSize (mWindow , &fbWidth, &fbHeight);
324+ glfwGetWindowSize (mWindow , &windowWidth, &windowHeight);
325+ mPixelRatio = windowWidth ? (double )fbWidth / windowWidth : 1 .; // Updated in resize_callback, which must not be called before InitDisplay
295326 applyInitialWindowState ();
296327 if (backend ()->backendType () == GPUDisplayBackend::TYPE_OPENGL ) {
297328 glfwSwapInterval (1 );
@@ -322,6 +353,12 @@ int32_t GPUDisplayFrontendGlfw::FrontendMain()
322353 }
323354 waitForFPSLimit ();
324355 glfwPollEvents ();
356+ if (mRestoreWindowedSize ) {
357+ mRestoreWindowedSize = false ;
358+ if (mWindowedWidth > 0 && mWindowedHeight > 0 && !glfwGetWindowAttrib (mWindow , GLFW_MAXIMIZED )) {
359+ glfwSetWindowSize (mWindow , mWindowedWidth , mWindowedHeight );
360+ }
361+ }
325362 }
326363
327364 ExitDisplay ();
0 commit comments