Skip to content

[rcore][glfw] Fix window scaling on Wayland with GLFW 3.4+#5564

Merged
raysan5 merged 3 commits into
raysan5:masterfrom
0xPD33:fix-wayland-scaling
Feb 17, 2026
Merged

[rcore][glfw] Fix window scaling on Wayland with GLFW 3.4+#5564
raysan5 merged 3 commits into
raysan5:masterfrom
0xPD33:fix-wayland-scaling

Conversation

@0xPD33
Copy link
Copy Markdown
Contributor

@0xPD33 0xPD33 commented Feb 15, 2026

Summary

GLFW 3.4 changed GLFW_SCALE_FRAMEBUFFER to default TRUE on all platforms. Previously only macOS set this hint explicitly. On Wayland with display scaling (1.5x, 2x, etc.), this causes:

  • Content rendering in a subset of the window (typically bottom-left)
  • Incorrect mouse coordinates
  • Wrong GetScreenWidth/GetScreenHeight values

Changes

  • Non-HiDPI path: Disable GLFW_SCALE_FRAMEBUFFER on Wayland when FLAG_WINDOW_HIGHDPI is not set, restoring 1:1 window-to-framebuffer mapping
  • HiDPI init: On Wayland, read actual framebuffer size from GLFW via glfwGetFramebufferSize() instead of calling glfwSetWindowSize() with scaled dimensions (which double-scales, since GLFW_SCALE_TO_MONITOR has no effect on Wayland but GLFW_SCALE_FRAMEBUFFER scales independently)
  • Mouse scaling: Skip SetMouseScale() on Wayland since GLFW already reports mouse coordinates in logical (window) space — unlike X11/Windows where GLFW_SCALE_TO_MONITOR resizes the window and mouse coords are in pixel space

All changes are guarded by glfwGetPlatform() == GLFW_PLATFORM_WAYLAND to avoid affecting existing X11/Windows/macOS behavior.

Test plan

  • Tested at 1x, 1.5x, and 2x display scaling on Niri (Wayland compositor)
  • Standard mode (no FLAG_WINDOW_HIGHDPI): grid fills window, corner rectangles touch edges, mouse tracks correctly
  • HiDPI mode (FLAG_WINDOW_HIGHDPI): same visual checks, GetScreenWidth returns logical size, GetRenderWidth returns physical size
  • X11/Windows — existing behavior unchanged (no Wayland platform detected, original code paths execute)

Environment: NixOS, Niri compositor, GLFW 3.4, NVIDIA RTX 5060 Ti (driver 580.126.09)

Fixes #5504

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
@kevin-kmetz
Copy link
Copy Markdown

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%).

Comment thread src/platforms/rcore_desktop_glfw.c Outdated
Comment thread src/platforms/rcore_desktop_glfw.c Outdated
Comment thread src/platforms/rcore_desktop_glfw.c Outdated
Comment thread src/platforms/rcore_desktop_glfw.c Outdated
Comment thread src/platforms/rcore_desktop_glfw.c Outdated
Comment thread src/platforms/rcore_desktop_glfw.c Outdated
Comment thread src/platforms/rcore_desktop_glfw.c Outdated
@CrackedPixel
Copy link
Copy Markdown
Contributor

You beat me to it and did it better 🤣 nice job 👍

@0xPD33
Copy link
Copy Markdown
Contributor Author

0xPD33 commented Feb 16, 2026

Will fix the formatting now, thanks for the review!

…gnment, collapse single-statement ifs to one line, remove trailing periods from comments
@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 16, 2026

@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 #if defined(_GLFW_WAYLAND) can be used instead of checking current platform through glfw? Afair, it doesn't need additional changes on build systems...

@raysan5 raysan5 changed the title Fix window scaling on Wayland with GLFW 3.4+ [rcore][glfw] Fix window scaling on Wayland with GLFW 3.4+ Feb 16, 2026
@raysan5 raysan5 added the platform: Linux (Wayland) Linux platform - Wayland windowing label Feb 16, 2026
@planetis-m
Copy link
Copy Markdown
Contributor

@raysan5 isn't figuring out which platform to use (X11/Wayland) negotiated at runtime? Seems like a downgrade to use defines.

@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 16, 2026

@planetis-m no, platform to use always has been defined by user on Makefile, at least for GLFW backend

@planetis-m
Copy link
Copy Markdown
Contributor

@raysan5 was this PR reverted? #3863

@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 16, 2026

@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.

@planetis-m
Copy link
Copy Markdown
Contributor

@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.

@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 16, 2026

@planetis-m I prefer current approach, thanks for your understanding.

@0xPD33
Copy link
Copy Markdown
Contributor Author

0xPD33 commented Feb 16, 2026

@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 #if defined(_GLFW_WAYLAND) can be used instead of checking current platform through glfw? Afair, it doesn't need additional changes on build systems...

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 #if defined(GLFW_PLATFORM_WAYLAND). The one you mentioned might be for internal use only during GLFW's own build, the one I just mentioned is the public equivalent from GLFW 3.4 headers. Please correct me if I'm wrong.

@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 17, 2026

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 #if defined(GLFW_PLATFORM_WAYLAND). The one you mentioned might be for internal use only during GLFW's own build, the one I just mentioned is the public equivalent from GLFW 3.4 headers. Please correct me if I'm wrong.

Reviewing the code, it seems GLFW_PLATFORM_WAYLAND is only intended to be used with glfwGetPlatform() at runtime, the compile-time flags to be checked are _GLFW_WAYLAND and _GLFW_X11 as shown here.

Further investigating the code, it seems _GLFW_WAYLAND is enabled through CMake when GLFW_BUILD_WAYLAND is defined, but raylib does not use GLFW CMake build system, and expects to build for specific platform using _GLFW_WAYLAND flag, that It's managed by raylib Makefile.

So, _GLFW_WAYLAND and _GLFW_X11 must be checked in code for compile time. The only concern is that it seems both flags can be enabled, if both backends are supported (X11 + Wayland).

@raysan5 raysan5 merged commit 4678a54 into raysan5:master Feb 17, 2026
16 checks passed
@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 17, 2026

@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.

@planetis-m
Copy link
Copy Markdown
Contributor

@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.

@raysan5
Copy link
Copy Markdown
Owner

raysan5 commented Feb 17, 2026

@planetis-m I don't understand what you mean, but feel free to send a PR for review with your proposed improvements. Thanks.

Please don’t break Linux again.

And please, moderate your tone. This kind of messages definitely do not help the project.

Tubbles added a commit to Tubbles/sleipner that referenced this pull request Apr 25, 2026
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform: Linux (Wayland) Linux platform - Wayland windowing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[rcore][glfw] Window scaling in Linux Wayland is broken

5 participants