feat(sway): 4K scale 2, natural mouse scroll, idle inhibit for emulators
CI / flake (push) Skipped
CI / flake (push) Skipped
Three unrelated desktop-side fixes, all in home/sway.nix. Sway cannot key an output rule on resolution, so scale 2 on 4K displays is applied by a user service that runs once at session start and again on every output event, which is what makes it survive a display being switched off and on. The scale guard in the jq filter stops the subscription feeding itself. kanshi still owns mode and position; no profile here sets a scale, so the two do not fight. natural_scroll on type:pointer gives mice the same scroll direction as the touchpads already had. PCSX2 and Dolphin default to borderless-windowed rather than compositor fullscreen, so the existing inhibit_idle fullscreen rules never matched and swaylock engaged mid-game. Inhibit on focus for the emulators instead. The Steam session is unaffected either way: swayidle is wanted by graphical-session.target and conditional on WAYLAND_DISPLAY, and the gamescope session provides neither. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0e10083ea4
commit
61a57f41e6
@@ -124,6 +124,25 @@ The greeter is **Dvorak**, like every other host here (`modules/sway.nix` forces
|
|||||||
`XKB_DEFAULT_VARIANT=dvorak` on cage). Only relevant if someone else has to type
|
`XKB_DEFAULT_VARIANT=dvorak` on cage). Only relevant if someone else has to type
|
||||||
a password.
|
a password.
|
||||||
|
|
||||||
|
### The Sway session behind it
|
||||||
|
|
||||||
|
Two fleet-wide rules in `home/sway.nix` matter more on a television than
|
||||||
|
anywhere else:
|
||||||
|
|
||||||
|
- Any output running at 4K is forced to **scale 2** (1920x1080 logical). Sway's
|
||||||
|
config cannot key an output rule on resolution, so a small user service
|
||||||
|
applies it at session start and again on every output event — which is what
|
||||||
|
makes it survive the TV being switched off and on.
|
||||||
|
- The emulators inhibit idle **while focused**, not only while fullscreen.
|
||||||
|
PCSX2 and Dolphin default to borderless-windowed rather than compositor
|
||||||
|
fullscreen, so the generic `inhibit_idle fullscreen` rules never fired and
|
||||||
|
swaylock cut in mid-game.
|
||||||
|
|
||||||
|
Neither applies in the Steam session: `swayidle` is a home-manager user service
|
||||||
|
wanted by `graphical-session.target` and conditional on `WAYLAND_DISPLAY`, and
|
||||||
|
the gamescope session starts neither, so nothing locks the screen in Big
|
||||||
|
Picture.
|
||||||
|
|
||||||
### Adding non-Steam titles to Big Picture
|
### Adding non-Steam titles to Big Picture
|
||||||
|
|
||||||
RetroArch, PCSX2, Dolphin and Clone Hero are installed system-wide but are not
|
RetroArch, PCSX2, Dolphin and Clone Hero are installed system-wide but are not
|
||||||
|
|||||||
+2
-2
@@ -18,8 +18,8 @@ rebuild, never the generated dotfiles.
|
|||||||
- Letter keys are **keysyms** (the character produced), not physical positions.
|
- Letter keys are **keysyms** (the character produced), not physical positions.
|
||||||
The keyboard is **Dvorak** (`us`/`dvorak`), so e.g. "Super+s" is whatever key
|
The keyboard is **Dvorak** (`us`/`dvorak`), so e.g. "Super+s" is whatever key
|
||||||
types `s` in Dvorak.
|
types `s` in Dvorak.
|
||||||
- Shortcuts apply to every Sway host (MBP, T400, Mac Pro); brightness keys are
|
- Shortcuts apply to every Sway host (MBP, T400, Mac Pro, Console); brightness
|
||||||
laptop-only, as noted.
|
keys are laptop-only, as noted.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,28 @@ let
|
|||||||
- | ${pkgs.swappy}/bin/swappy -f -
|
- | ${pkgs.swappy}/bin/swappy -f -
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# Sway's config cannot express an output rule keyed on resolution, so scale is
|
||||||
|
# applied from outside it: once at session start, then on every output event,
|
||||||
|
# which is what makes it survive a display being unplugged or power-cycled.
|
||||||
|
# The `.scale != 2` guard stops the subscription feeding itself, since setting
|
||||||
|
# a scale is itself an output event.
|
||||||
|
scaleHidpi = pkgs.writeShellScript "sway-scale-hidpi" ''
|
||||||
|
apply() {
|
||||||
|
${pkgs.sway}/bin/swaymsg -r -t get_outputs \
|
||||||
|
| ${pkgs.jq}/bin/jq -r '.[]
|
||||||
|
| select(.active and .current_mode.width >= 3840 and .scale != 2)
|
||||||
|
| .name' \
|
||||||
|
| while read -r name; do
|
||||||
|
${pkgs.sway}/bin/swaymsg output "$name" scale 2
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
apply
|
||||||
|
${pkgs.sway}/bin/swaymsg -t subscribe -m '["output"]' | while read -r _; do
|
||||||
|
apply
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
# Binding-mode names. The string is both the `modes` attr key and what the
|
# Binding-mode names. The string is both the `modes` attr key and what the
|
||||||
# bar's mode indicator shows, so the keys are spelled out in the label.
|
# bar's mode indicator shows, so the keys are spelled out in the label.
|
||||||
layoutMode = "layout: [s]tacking [w]tabbed [e]split";
|
layoutMode = "layout: [s]tacking [w]tabbed [e]split";
|
||||||
@@ -60,6 +82,8 @@ in
|
|||||||
tap = "enabled";
|
tap = "enabled";
|
||||||
natural_scroll = "enabled";
|
natural_scroll = "enabled";
|
||||||
};
|
};
|
||||||
|
# Mice (the MX Master 3 among them) scroll the same way as the touchpads.
|
||||||
|
input."type:pointer".natural_scroll = "enabled";
|
||||||
|
|
||||||
# Solid Catppuccin Mocha base as the wallpaper (no image dependency).
|
# Solid Catppuccin Mocha base as the wallpaper (no image dependency).
|
||||||
output."*".bg = "#${ctp.base} solid_color";
|
output."*".bg = "#${ctp.base} solid_color";
|
||||||
@@ -111,6 +135,18 @@ in
|
|||||||
criteria.class = ".*";
|
criteria.class = ".*";
|
||||||
command = "inhibit_idle fullscreen";
|
command = "inhibit_idle fullscreen";
|
||||||
}
|
}
|
||||||
|
# Emulators default to borderless-windowed rather than compositor
|
||||||
|
# fullscreen, so the rules above never fire and swaylock cuts in
|
||||||
|
# mid-game. Inhibit on focus instead, which does not depend on how the
|
||||||
|
# application asked to fill the screen.
|
||||||
|
{
|
||||||
|
criteria.app_id = "(?i)^(pcsx2|dolphin-emu|retroarch|clone.?hero)";
|
||||||
|
command = "inhibit_idle focus";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
criteria.class = "(?i)^(pcsx2|dolphin-emu|retroarch|clone.?hero)";
|
||||||
|
command = "inhibit_idle focus";
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
# Binding modes (submenus). Entered from keybindings below; each action
|
# Binding modes (submenus). Entered from keybindings below; each action
|
||||||
@@ -307,6 +343,24 @@ in
|
|||||||
Install.WantedBy = [ "sway-session.target" ];
|
Install.WantedBy = [ "sway-session.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Every 4K output runs at scale 2 (1920x1080 logical), on every host and
|
||||||
|
# whatever the display is called. kanshi below owns mode and position; this
|
||||||
|
# owns scale for the one case that is a fleet-wide rule rather than a
|
||||||
|
# per-display fact, and the two do not fight because no kanshi profile here
|
||||||
|
# sets a scale.
|
||||||
|
systemd.user.services.sway-scale-hidpi = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Force scale 2 on 4K Sway outputs";
|
||||||
|
PartOf = [ "graphical-session.target" ];
|
||||||
|
After = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${scaleHidpi}";
|
||||||
|
Restart = "on-failure";
|
||||||
|
};
|
||||||
|
Install.WantedBy = [ "sway-session.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
# Output/display management. Reacts to hotplug and applies per-display
|
# Output/display management. Reacts to hotplug and applies per-display
|
||||||
# mode/scale/position. Profiles are hardware-specific: the safe default below
|
# mode/scale/position. Profiles are hardware-specific: the safe default below
|
||||||
# just enables the internal laptop panel; add docked/desktop profiles with the
|
# just enables the internal laptop panel; add docked/desktop profiles with the
|
||||||
|
|||||||
Reference in New Issue
Block a user