Skip to content

Conversation

@shgew
Copy link
Contributor

@shgew shgew commented Nov 19, 2025

Describe your PR, what does it fix/add?

  • This follows the investigation in Fullsceen with VRR causes slow and stuttery cursor/mouse movement #12013 where I described the VRR-induced cursor stutter / loss of raw mouse look after focus changes in Proton Wayland games (comment #14995612 and the later debugging notes 15003452, 15004222, 15004537).
  • We found that the “skip pointer frame when the pointer is locked” workaround is also running for native Wayland clients. With VRR enabled this means motion events get queued until a click, which matched the behavior I reported.
  • This patch restricts the skip to locked pointers targeting fullscreen Xwayland windows. Native Wayland titles now keep smooth mouse look with VRR on, while Xwayland still avoids the refresh rate spikes that originally motivated the hack.
  • Manually retested with my HDR + VRR config (misc.vrr=3, render.direct_scanout=2, cursor:no_break_fs_vrr 0/2, Proton-GE) and confirmed the regression is gone per comment #15013944.

Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)

  • I could only reproduce the regression on locked-pointer Wayland clients. Xwayland behavior is unchanged.
  • Happy to help dig deeper if someone can point to other places where locked cursors might still emit the extra frame callbacks that originally triggered shouldSkipScheduleFrameOnMouseEvent().

Is it ready for merging, or does it need work?

Ready. Let me know if you prefer gating this behind a config flag instead.

@fxzzi
Copy link
Contributor

fxzzi commented Nov 19, 2025

probably fixes #12032, can test when I get home

@vaxerski
Copy link
Member

pls do

@fxzzi
Copy link
Contributor

fxzzi commented Nov 19, 2025

pls do

yep, fixed

@Gliczy
Copy link
Contributor

Gliczy commented Nov 19, 2025

I tested a few games running in native Wayland: CS2, Minecraft, Ultrakill and Warframe; they all seem to behave properly now in regard to the issues discussed in #12013.

However, for games running in native Wayland with Proton-GE (Ultrakill and Warframe in this case), it is still needed to fullscreen off and fullscreen on the window for VRR to actually work (this also applies to DS).

@shgew
Copy link
Contributor Author

shgew commented Nov 19, 2025

However, for games running in native Wayland with Proton-GE (Ultrakill and Warframe in this case), it is still needed to fullscreen off and fullscreen on the window for VRR to actually work (this also applies to DS).

Same for me. It would be awesome to fix, but I couldn't find the reason why it happens.

@njdom24
Copy link
Contributor

njdom24 commented Nov 20, 2025

Same for me. It would be awesome to fix, but I couldn't find the reason why it happens.

I just tested and found the same behavior on Sway. Might not be solveable for us besides an IPC hook to quickly toggle fullscreen on app launch.

Edit: False alarm. I just had the above issue when launching a game set to borderless instead of fullscreen in its settings.

Edit 2: Unable to replicate the issue with Proton Wayland. Seems to get VRR fine on initial launch.

@dablenparty
Copy link

I just got done re-installing my entire system; fresh CachyOS install, fresh Hyprland install (I use my own PKGBUILD to compile from source), fresh Steam/Wine/Proton, and fresh game installs. I've tried STALKER 2, Minecraft, Killing Floor 2, HITMAN 2, and ELDEN RING (both kbm & controller). I have tried them all with both Wayland and XWayland. The only game I was able to replicate this issue in is HITMAN 2; however, setting no_break_fs_vrr = 0 did not help at all. Instead, setting min_refresh_rate = 60 (the lowest refresh-rate for my resolution, found with hyprctl monitors) mitigated it a bit and made it smooth enough to play. It's also worth noting that Minecraft doesn't run on Wayland natively without a custom GLFW patch and enabling VSync in-game while using VRR can cause mouse stuttering (depending on your MC version).

I brought this up in the discussion but it was ignored, so I want to ask again: what window rules are you guys using for game windows? I also had to toggle full-screen off then on again until I set up good window rules.

@adamnejm
Copy link

adamnejm commented Nov 25, 2025

What window rules are you guys using for game windows

Nothing really, I just force VRR on everything besides stuff explicitly listed.

misc:vrr = 3
windowrule = content game, class:.*
windowrule = novrr 1, class:^(Alacritty|firefox|mpv|vlc|codium|brave-browser)$

I also had to toggle full-screen off then on again

In Deadlock's case, the game doesn't fullscreen automatically on XWayland, while native Wayland seems to work perfectly (besides VRR bug ofc).

Not sure if that helps you in any way.

@shgew
Copy link
Contributor Author

shgew commented Nov 25, 2025

I just got done re-installing my entire system; fresh CachyOS install, fresh Hyprland install (I use my own PKGBUILD to compile from source), fresh Steam/Wine/Proton, and fresh game installs. I've tried STALKER 2, Minecraft, Killing Floor 2, HITMAN 2, and ELDEN RING (both kbm & controller). I have tried them all with both Wayland and XWayland. The only game I was able to replicate this issue in is HITMAN 2; however, setting no_break_fs_vrr = 0 did not help at all. Instead, setting min_refresh_rate = 60 (the lowest refresh-rate for my resolution, found with hyprctl monitors) mitigated it a bit and made it smooth enough to play. It's also worth noting that Minecraft doesn't run on Wayland natively without a custom GLFW patch and enabling VSync in-game while using VRR can cause mouse stuttering (depending on your MC version).

I brought this up in the discussion but it was ignored, so I want to ask again: what window rules are you guys using for game windows? I also had to toggle full-screen off then on again until I set up good window rules.

I tried setting the rules exactly as you shared, but it did not solve the issue for my setup.

Sorry about the ignore part. I wanted to come back to you and report my results, but I got too involved in the process of finding a solution and eventually forgot.

@dablenparty
Copy link

dablenparty commented Nov 26, 2025

Nothing really, I just force VRR on everything besides stuff explicitly listed.

misc:vrr = 3
windowrule = content game, class:.*
windowrule = novrr 1, class:^(Alacritty|firefox|mpv|vlc|codium|brave-browser)$

@adamnejm , you aren't forcing VRR with misc:vrr = 3, you have it in one of the auto modes. From the wiki:

vrr: controls the VRR (Adaptive Sync) of your monitors. 0 - off, 1 - on, 2 - fullscreen only, 3 - fullscreen with video or game content type [0/1/2/3]

Use misc:vrr = 1 to force it on. I also don't think it's a good idea to set every single window to content game, especially when your other rules rely on that content type (e.g. misc:vrr = 3). That's probably why your browsers and terminal are activating VRR and it seems like it's forced on even though it's not. I also noticed you are using the v2 windowrule syntax; when was the last time you updated Hyprland and where do you install it from?

In Deadlock's case, the game doesn't fullscreen automatically on XWayland, while native Wayland seems to work perfectly (besides VRR bug ofc).

There's a window rule for that:

windowrule = match:content 3, match:xwayland true, fullscreen true
# or
windowrule {
  # match:content isn't the most reliable
  match:content = 3
  match:xwayland = true

  fullscreen = true
}

I tried setting the rules exactly as you shared, but it did not solve the issue for my setup.
Sorry about the ignore part. I wanted to come back to you and report my results, but I got too involved in the process of finding a solution and eventually forgot.

@shgew it's fine that you forgot, but I didn't ask you to try my window rules, I asked you to share yours because you may have something misconfigured like Adam and that's important; it's very hard to narrow down a bug in code if we all have different configs and Hyprland versions, especially since not everyone can reliably replicate this issue. I've also changed my rules slightly since then and I'll paste them below again for posterity. I agree that VRR is borderline busted in Hyprland right now; I also think it's affected by hardware, user configs, or maybe even other software, too. I'm really not sure because the more research I do, the more discussions and PR's I find relating to cursors, VRR, and tearing in general. I've just changed my config to not use tearing at all because I found out the Linux kernel blocks hardware cursors if tearing is on which in turn blocks direct scanout, and tearing doesn't work on my TV anyway. I think you'll find that whole PR interesting, especially this comment.

My Relevant Window Rules

$steamAppClass = ^steam_app(_\d+|default)?$

# Content Types
windowrule = match:xdg_tag ^(proton-game)$,              tag +video-game
windowrule = match:content 3,                            tag +video-game
windowrule = match:initial_class $steamAppClass,         tag +video-game
windowrule = match:initial_class ^(.*\.exe)$,            tag +video-game
# just add the names of modpacks
windowrule = match:initial_title ^(Minecraft|Tekxit).*$, tag +video-game
windowrule = match:initial_class ^(artofrally).*$,       tag +video-game

# Game Window Rules
# default monitors are handled by proton.zsh

$gamingWorkspace = 10
workspace = $gamingWorkspace, defaultName:Gaming, border:false, shadow:false, rounding:false, decorate:false

windowrule {
    name = video-games
    match:tag = video-game
    workspace = $gamingWorkspace

    border_size = 0
    # ironic; even if they're tagged, they STILL might not have the right content type, so set it here too
    content = game
    decorate = false
    force_rgbx = true
    fullscreen = true
    # using 2 2 doesn't work for some games *cough* ELDEN RING
    fullscreen_state = 3 3
    idle_inhibit = always
    no_anim = true
    no_blur = true
    no_dim = true
    no_max_size = true
    no_shadow = true
    persistent_size = true
    pseudo = true
    render_unfocused = true
    rounding = 0
    # fixes games that fail to maximize *cough* ELDEN RING
    sync_fullscreen = true
}

@shgew
Copy link
Contributor Author

shgew commented Nov 26, 2025

I asked you to share yours

Here you go:

Window Rules
windowrule = [
  {
    name = "steam";
    "match:class" = "steam";
    min_size = "1 1";
    workspace = 11;
    rounding = 0;
  }

  {
    name = "proton-game-tag";
    "match:xdg_tag" = "proton-game";
    tag = "+game";
  }
  {
    name = "steam-apps-tag";
    "match:initial_class" = "steam_app_.*";
    tag = "+game";
  }
  {
    name = "dota2-tag";
    "match:class" = "dota2";
    tag = "+game";
  }
  {
    name = "gamescope-tag";
    "match:class" = "gamescope";
    tag = "+game";
  }
  {
    name = "minecraft-tag";
    "match:class" = "Minecraft.*";
    tag = "+game";
  }
  {
    name = "unigine-tag";
    "match:title" = "Unigine.*";
    "match:class" = "negative:Browser.*";
    tag = "+game";
  }

  {
    name = "games";

    "match:tag" = "game";

    workspace = 12;
    content = "game";
    border_size = 0;
    rounding = 0;
    decorate = false;
    force_rgbx = true;
    fullscreen = true;
    fullscreen_state = "3 3";
    sync_fullscreen = true;
    idle_inhibit = "always";
    no_anim = true;
    no_blur = true;
    no_dim = true;
    no_max_size = true;
    no_shadow = true;
    persistent_size = true;
  }

  {
    name = "dota2-no-vrr";
    "match:class" = "dota2";
    no_vrr = true;
  }
  {
    name = "shproto-no-vrr";
    "match:class" = "shproto.*";
    no_vrr = true;
  }
  {
    name = "drg-survivor-no-vrr";
    "match:class" = "steam_app_2321470";
    no_vrr = true;
  }
  {
    name = "clair-obscure-no-vrr";
    "match:title" = "Clair Obscur.*";
    no_vrr = true;
  }

  {
    name = "blueman";
    "match:class" = "^\\.blueman-manager-wrapped$";
    float = true;
    size = "30% 80%";
    move = "15 60";
  }
  {
    name = "pavucontrol";
    "match:class" = "org\\.pulseaudio\\.pavucontrol";
    float = true;
    size = "30% 80%";
    move = "15 60";
  }
];
Config
monitorv2 = [
  {
    output = "desc:Microstep MPG321UX OLED 0x01010101";
    mode = "3840x2160@240Hz";
    position = "auto";
    scale = 1.5;

    bitdepth = 10;
    cm = "edid";
  }
]
misc = {
  vrr = 3;
};

experimental = {
  xx_color_management_v4 = true;
};

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.

7 participants