The idea behind this script is to only use VRR when a application is in fullscreen mode, here's the features:
- Has multi monitor support through a output whitelist config (I'd like this to be automatic in the future but there doesn't seem to be any way in swaymsg to identify if a output is VRR capable, one thing which comes to mind is checking EDID for VRR range).
- Determine if VRR needs to be toggled when a application is in fullscreen mode (which is how Windows does it usually and it's a option in Hyprland). This applies to:
- Opening a app
- Changing focus
- Switching workplaces
- Going into fullscreen mode (e.g. Youtube videos in Chromium)
As a result, you don't have to manually toggle VRR (which mitigates cursor stuttering in desktop mode when multi-tasking while gaming if VRR was to be enabled globally)
-
Install
jq
before proceeding -
Make sure your output has
adaptive_sync off
from start and that it invokes the script from the next step:~/.config/sway/config
output DP-1 { mode 3840x1600@143.998Hz position 0 0 adaptive_sync off # Recommended to avoid cursor stutter after starting Sway } output DP-2 { mode 1920x1080@119.982Hz position 3840 260 adaptive_sync off } exec "~/.config/sway/scripts/vrr_fullscreen.sh"
-
Script
$ mkdir -p ~/.config/sway/scripts/ $ touch ~/.config/sway/scripts/vrr_fullscreen.sh $ chmod +x ~/.config/sway/scripts/vrr_fullscreen.sh
~/.config/sway/scripts/vrr_fullscreen.sh
#!/usr/bin/env bash # List of supported outputs for VRR output_vrr_whitelist=( "DP-1" "DP-2" ) # Toggle VRR for fullscreened apps in prespecified displays to avoid stutters while in desktop swaymsg -t subscribe -m '[ "window" ]' | while read window_json; do window_event=$(echo ${window_json} | jq -r '.change') # Process only focus change and fullscreen toggle if [[ $window_event = "focus" || $window_event = "fullscreen_mode" ]]; then output_json=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused == true)') output_name=$(echo ${output_json} | jq -r '.name') # Use only VRR in whitelisted outputs if [[ ${output_vrr_whitelist[*]} =~ ${output_name} ]]; then output_vrr_status=$(echo ${output_json} | jq -r '.adaptive_sync_status') window_fullscreen_status=$(echo ${window_json} | jq -r '.container.fullscreen_mode') # Only update output if nesseccary to avoid flickering [[ $output_vrr_status = "disabled" && $window_fullscreen_status = "1" ]] && swaymsg output "${output_name}" adaptive_sync 1 [[ $output_vrr_status = "enabled" && $window_fullscreen_status = "0" ]] && swaymsg output "${output_name}" adaptive_sync 0 fi fi done