[rcore][glfw] Fix window scaling on Wayland with GLFW 3.4+#5564
Conversation
GLFW 3.4 defaults GLFW_SCALE_FRAMEBUFFER to TRUE on all platforms, causing framebuffer/window size mismatch on Wayland with display scaling (content renders in a subset of the window, mouse coordinates are wrong). Three fixes: - Disable GLFW_SCALE_FRAMEBUFFER on Wayland when FLAG_WINDOW_HIGHDPI is not set, restoring 1:1 window-to-framebuffer mapping - With FLAG_WINDOW_HIGHDPI, read actual framebuffer size from GLFW instead of resizing the window (which double-scales on Wayland where GLFW_SCALE_TO_MONITOR has no effect) - Skip mouse coordinate scaling on Wayland since GLFW already reports coordinates in logical (window) space Tested on NixOS/Niri with GLFW 3.4 at 1x, 1.5x, and 2x scaling. Fixes raysan5#5504
ToggleFullscreen and ToggleBorderlessWindowed exit paths manually scale screen size by DPI before passing to glfwSetWindowMonitor, which double-scales on Wayland where GLFW_SCALE_FRAMEBUFFER already handles it. Skip the manual resize on Wayland. Also fix FramebufferSizeCallback fullscreen branch: on Wayland with GLFW_SCALE_FRAMEBUFFER the framebuffer is still scaled in fullscreen, so use the logical window size as screen size and derive screenScale from the framebuffer/window ratio. Fixes raysan5#5504
|
I noted in the relevant open issue that this pull request when checked out resolved the issue on my system (Fedora + Wayland + 4 monitors + one scaled up to 225%). |
|
You beat me to it and did it better 🤣 nice job 👍 |
|
Will fix the formatting now, thanks for the review! |
…gnment, collapse single-statement ifs to one line, remove trailing periods from comments
|
@0xPD33 thank you very much for the fix and @kevin-kmetz @CrackedPixel thanks for reviewing it. I tested it on Windows 10 and macOS, with multi-monitor and multi-dpi, with HighDPI enabled and disabled. All seems to work as expected. My only concern, there is no need to include platform-specific code that won't be executed so, maybe |
|
@raysan5 isn't figuring out which platform to use (X11/Wayland) negotiated at runtime? Seems like a downgrade to use defines. |
|
@planetis-m no, platform to use always has been defined by user on Makefile, at least for GLFW backend |
|
@planetis-m I don't know, you can probably check That PR was modifying an external library that potentially could be updated so changes reverted. I don't know at the moment if it was the case. In any case I think it's a better approach let the dev choose the desired windowing system backend instead of making assumptions depending on the windowing system where the application is compiled. |
Ray, I may be misinterpreting your message, but I think it’s worth reconsidering what you’re asking for. Linux already has runtime platform detection since the PR I referenced. For that reason, using a C preprocessor definition would not be advisable, as it would break that behavior. Additionally, it is generally uncommon in software development to close an issue before the PR that addresses it has been merged. |
|
@planetis-m I prefer current approach, thanks for your understanding. |
Okay so I can give this a shot, it does make sense to me. Would be great if we can agree on it first. Also unsure if that flag is correct or if it should be |
Reviewing the code, it seems Further investigating the code, it seems So, |
|
@0xPD33 I'm checking the code and I think it can be tricky in some cases to consider the flags, so I'm merging and reviewing it myself when required. Thank you very much for the improvement. |
|
@raysan5 Please don’t break Linux again. Take a close look at the previous PR I linked and what it’s supposed to do. If you want a compile-time define, use a standard #if defined(linux) or BSD check, and keep runtime detection for the windowing backend (X11 vs. Wayland). Thank you for being reasonable. |
|
@planetis-m I don't understand what you mean, but feel free to send a PR for review with your proposed improvements. Thanks.
And please, moderate your tone. This kind of messages definitely do not help the project. |
raylib 5.5 plus the bundled GLFW 3.4 produced a black screen on
Wayland: GetScreenWidth reported the monitor size while
GetRenderWidth stayed at the initial InitWindow size, so the blit
destination mapped outside the GL viewport. Audio and game logic
ran fine, only rendering was broken. Yesterday's cherry-pick of
upstream PR #4909 (GLFW_SCALE_FRAMEBUFFER=FALSE) only addressed a
narrow non-HiDPI corner case and did not fix the underlying
screen/render desync, confirmed by a fresh trace log on the patched
5.5 build.
raylib 6.0 (released 2026-04-23) ships a complete fix as part of
the REDESIGNED Fullscreen modes and High-DPI content scaling work.
The Wayland-specific path lives in src/platforms/rcore_desktop_glfw.c
(PR #5564, merged 2026-02-17), gated on
glfwGetPlatform() == GLFW_PLATFORM_WAYLAND. Upstream tested the new
window system on Linux X11/Wayland, Windows, and macOS with multiple
monitors and 4K resolutions.
Changes:
- engine/vendor/raylib/ replaced wholesale with the raylib 6.0
source subset (src/, cmake/, CMakeLists.txt, CMakeOptions.txt,
LICENSE, raylib.pc.in, README.md), sha256
2b3ee1e2120c7a0796b33062c7e9a694dd8a8caa56a96319ac8c8ecf54a90d0b.
- Both 5.5-era patches dropped, both absorbed upstream:
PR #4671 (Android shared-linker -Wl,--no-undefined strip) is in
cmake/LibraryConfigurations.cmake at lines 84-89.
PR #4909 + PR #5564 (Wayland framebuffer scaling) are in
src/platforms/rcore_desktop_glfw.c.
recipes/raylib/patches/ removed entirely. Provenance in
engine/vendor/raylib/SLEIPNER_MODIFICATIONS.md.
- raylib 6.0's CMakeLists.txt requires CMake 3.25 or higher. Android
side bumped from CMake 3.22.1 to 3.31.4 (highest available in
androidenv): flake.nix cmakeVersions and
android/app/build.gradle.kts externalNativeBuild version both
updated. The Android NDK 28 toolchain runs cleanly under cmake
3.31.4.
- Engine code at engine/src/main.c is unchanged. raylib 6.0's
redesigned ToggleBorderlessWindowed calls glfwSetWindowMonitor
with the monitor handle on entry and skips manual resize on
Wayland exit, so the existing init flow should drive the
framebuffer to the monitor size correctly. If the end-to-end
Wayland test shows otherwise, the engine init will be revisited
in a follow-up.
Verification:
- nix develop -c cmake --build build/Release: clean.
- nix develop -c ctest --test-dir build/Release: 25/25 pass.
- nix develop .#windows -c cmake --build build/windows: clean
(PLATFORM=SDL via SDL2 from pkgsSdl2.pkgsCross.mingwW64.SDL2).
- nix develop .#android -c ./gradlew assembleRelease: APK built
at android/app/build/outputs/apk/release/app-release.apk.
The runtime Wayland test is on the user's hardware.
References:
- https://github.com/raysan5/raylib/releases/tag/6.0
- raysan5/raylib#5564
- raysan5/raylib#4908
Assisted-by: Claude:claude-opus-4-7
Summary
GLFW 3.4 changed
GLFW_SCALE_FRAMEBUFFERto defaultTRUEon all platforms. Previously only macOS set this hint explicitly. On Wayland with display scaling (1.5x, 2x, etc.), this causes:GetScreenWidth/GetScreenHeightvaluesChanges
GLFW_SCALE_FRAMEBUFFERon Wayland whenFLAG_WINDOW_HIGHDPIis not set, restoring 1:1 window-to-framebuffer mappingglfwGetFramebufferSize()instead of callingglfwSetWindowSize()with scaled dimensions (which double-scales, sinceGLFW_SCALE_TO_MONITORhas no effect on Wayland butGLFW_SCALE_FRAMEBUFFERscales independently)SetMouseScale()on Wayland since GLFW already reports mouse coordinates in logical (window) space — unlike X11/Windows whereGLFW_SCALE_TO_MONITORresizes the window and mouse coords are in pixel spaceAll changes are guarded by
glfwGetPlatform() == GLFW_PLATFORM_WAYLANDto avoid affecting existing X11/Windows/macOS behavior.Test plan
FLAG_WINDOW_HIGHDPI): grid fills window, corner rectangles touch edges, mouse tracks correctlyFLAG_WINDOW_HIGHDPI): same visual checks,GetScreenWidthreturns logical size,GetRenderWidthreturns physical sizeEnvironment: NixOS, Niri compositor, GLFW 3.4, NVIDIA RTX 5060 Ti (driver 580.126.09)
Fixes #5504