Skip to content

feat: add borderless_fullscreen window rule#12892

Open
jmylchreest wants to merge 1 commit intohyprwm:mainfrom
jmylchreest:feat/borderless-fullscreen-tracking
Open

feat: add borderless_fullscreen window rule#12892
jmylchreest wants to merge 1 commit intohyprwm:mainfrom
jmylchreest:feat/borderless-fullscreen-tracking

Conversation

@jmylchreest
Copy link
Copy Markdown
Contributor

Some applications, especially games, use "borderless windowed" or "windowed fullscreen" mode instead of true fullscreen. These windows don't set fullscreen hints via the compositor protocol, so Hyprland doesn't treat them as fullscreen - meaning layer surfaces like waybar remain visible on top.

However, these windows do set their geometry to match the monitor size. This PR adds a new borderless_fullscreen window rule/property that allows opting specific windows into being treated as effectively fullscreen when they cover the monitor.

Key features:

  • Opt-in via borderless_fullscreen window rule or setprop
  • Uses 5px tolerance for coverage detection (handles minor offsets from decorations/rounding)
  • Layer surfaces (TOP layer) fade out smoothly when window covers monitor
  • Continuous checking in render path handles dynamic resize/move
  • Works with existing fullscreen animations

Test plan

  1. Open any floating window (e.g., kitty)
  2. Enable the rule: hyprctl setprop active borderless_fullscreen 1
  3. Make it floating if not already: hyprctl dispatch setfloating
  4. Resize to cover the monitor: hyprctl dispatch resizeactive exact 1920 1080 (adjust for your resolution)
  5. Move to origin: hyprctl dispatch moveactive exact 0 0
  6. Observe waybar fades out
  7. Resize smaller or move off-origin - waybar fades back in

Alternative: Use window rule for specific apps:

  windowrule {
   name = steam
   borderless_fullscreen = on
   match:class = ^(steam_app_.)$
}

This PR has a minor conflict with the special workspace fullscreen fix in Monitor.cpp in #12851 - both modify inFullscreenMode(). They are distinct features and the conflict is simple to resolve (the special workspace fix adds checking special workspaces first, this PR adds checking borderless fullscreen windows).

Add a new window rule that treats windows covering the monitor (without
using the fullscreen protocol) as effectively fullscreen. This causes
layer surfaces like waybar to hide when the window covers the screen.

The feature is opt-in via the borderless_fullscreen window rule and
uses a 5px tolerance for coverage detection. Layer surface visibility
is updated continuously in the render path for smooth animated fading.

Changes:
- Add borderless_fullscreen window rule effect
- Add isBorderlessFullscreen() geometric check with 5px tolerance
- Add isEffectivelyFullscreen() that checks real OR borderless fullscreen
- Add getFullscreenWindow() to CMonitor for unified fullscreen window access
- Update inFullscreenMode() to include borderless fullscreen windows
- Add continuous layer alpha check in render path for TOP layer surfaces
- Update DesktopAnimationManager to handle effectively fullscreen windows
- Add hyprctl getprop/setprop support for borderless_fullscreen
- Add unit tests for geometry detection and integration tests
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 6, 2026

Hello and thank you for making a PR to Hyprland!

Please check the PR Guidelines and make sure your PR follows them.
It will make the entire review process faster. :)

If your code can be tested, please always add tests. See more here.

beep boop, I'm just a bot. A real human will review your PR soon.

@fxzzi
Copy link
Copy Markdown
Contributor

fxzzi commented Jan 6, 2026

to me this doesn't make sense as a rule, I think hyprland should instead have an option to auto-fullscreen windows which are centered on a monitor and have dimensions equal to that of the monitor (or with a tolerance as you said equal to your gap sizes). This should avoid those cases where you launch a game, it's filling your screen, but not in fullscreen compositor side.

edit:
for me I avoid having windowrules for fullscreening games, this is because stuff like launchers, or other programs which aren't the game itself are then also fullscreened, causing issues. this would be great to avoid having to also make windowrules for every game you play (i am aware of steam_app class etc)

@jmylchreest
Copy link
Copy Markdown
Contributor Author

I originally built this out as a global config option, but I wasn't convinced this was the correct behaviour for all apps so thought transitioning this to a window rules gave the option to override (either way) for specific apps. It's simple enough to default it to on. Because it influences the zorder/alpha of layers above it if it's considered fullscreen it can cause frustration if you simply have a window thats the size of the monitor - it'll hide TOP notifications, for example.

However, I do disagree with the centered app comment because the window hints and many apps will translate positional values based on the 0x0, from which we calculate monitor placement. For fullscreen apps that set EWMH sure, but many will use the monitor dimensions of the first monitor regardless (XWayland translation causes this), so this seemed safer.

Because of how this detects the borderless window, setting a window with the prop as "borderless_fullscreen" does not actually set it as fullscreen at all, it only allows it to be considered fullscreen at render time IF it is resized to be as big or larger than the monitor within the tolerance. Setting this to on for all windows is likely very safe, but I didn't want to assume it was.

just to reiterate, this does not force anything to be fullscreen, it simply introduces a calculated state, whereby if the window is allowed to be considered as fullscreen (but without it having set the EWHM fullscreen hint using the protocol) if it is as large or larger and covering the viewport of the whole monitor it is on (within a 5px tolerance). Launchers will still show their normal size/have no influence.

@fxzzi
Copy link
Copy Markdown
Contributor

fxzzi commented Jan 8, 2026

I do see your point. Tested and works fine on GTAV.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants