feat(hyprland): migrate config from .conf to .lua format (Hyprland 0.55+)
- Add hyprland.lua.j2 Ansible template with full Lua DSL config - Update tasks to deploy hyprland.lua instead of hyprland.conf - Add docs/tech/hyprland-lua-migration.md with API reference, dispatcher mapping, pitfalls, and validation commands - Update keybindings doc to reflect .lua config format Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -88,7 +88,7 @@
|
||||
group: "{{ system_user }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'hyprland.conf.j2', dest: 'hypr/hyprland.conf' }
|
||||
- { src: 'hyprland.lua.j2', dest: 'hypr/hyprland.lua' }
|
||||
- { src: 'hyprlock.conf.j2', dest: 'hypr/hyprlock.conf' }
|
||||
- { src: 'hypridle.conf.j2', dest: 'hypr/hypridle.conf' }
|
||||
- { src: 'hyprpaper.conf.j2', dest: 'hypr/hyprpaper.conf' }
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
-- =========================================================================
|
||||
-- hyprland.lua - managed by Ansible
|
||||
-- Hyprland 0.55+ Lua config for mw-pfeddersheim-workstation
|
||||
-- SUPER = Windows key
|
||||
-- =========================================================================
|
||||
|
||||
local terminal = "kitty"
|
||||
local fileManager = "kitty -e yazi"
|
||||
local menu = "hyprlauncher"
|
||||
local browser = "google-chrome-stable"
|
||||
local mainMod = "SUPER"
|
||||
|
||||
-----------------
|
||||
---- MONITORS ----
|
||||
-----------------
|
||||
|
||||
-- 1. DP-1 TERRA 3280W 2560x1440@144 (0x0)
|
||||
-- 2. DVI-D-1 BenQ BL2405 1920x1080@60 (rotated 90 CW)
|
||||
-- 3. HDMI-A-1 TERRA 3280W 2560x1440@144 (3640x0)
|
||||
hl.monitor({ output = "DP-1", mode = "2560x1440@60", position = "0x0", scale = "1" })
|
||||
hl.monitor({ output = "DVI-D-1", mode = "1920x1080@60", position = "2560x0", scale = "1", transform = "1" })
|
||||
hl.monitor({ output = "HDMI-A-1", mode = "2560x1440@60", position = "3640x0", scale = "1" })
|
||||
|
||||
hl.workspace_rule({ workspace = 1, monitor = "DP-1", default = true })
|
||||
hl.workspace_rule({ workspace = 2, monitor = "DVI-D-1", default = true })
|
||||
hl.workspace_rule({ workspace = 3, monitor = "HDMI-A-1", default = true })
|
||||
|
||||
-------------------------------
|
||||
---- ENVIRONMENT VARIABLES ----
|
||||
-------------------------------
|
||||
|
||||
hl.env("LIBVA_DRIVER_NAME", "nvidia")
|
||||
hl.env("XDG_SESSION_TYPE", "wayland")
|
||||
hl.env("GBM_BACKEND", "nvidia-drm")
|
||||
hl.env("__GLX_VENDOR_LIBRARY_NAME", "nvidia")
|
||||
hl.env("WLR_NO_HARDWARE_CURSORS", "1")
|
||||
hl.env("NVD_BACKEND", "direct")
|
||||
|
||||
---------------
|
||||
---- INPUT ----
|
||||
---------------
|
||||
|
||||
hl.config({
|
||||
input = {
|
||||
kb_layout = "de",
|
||||
follow_mouse = 1,
|
||||
sensitivity = 0,
|
||||
numlock_by_default = true,
|
||||
},
|
||||
})
|
||||
|
||||
hl.device({ name = "pixart-usb-optical-mouse", left_handed = 1 })
|
||||
|
||||
-----------------------
|
||||
---- LOOK AND FEEL ----
|
||||
-----------------------
|
||||
|
||||
hl.config({
|
||||
general = {
|
||||
gaps_in = 5, gaps_out = 10, border_size = 2,
|
||||
col = {
|
||||
active_border = { colors = {"rgba(33ccffee)", "rgba(00ff99ee)"}, angle = 45 },
|
||||
inactive_border = "rgba(595959aa)",
|
||||
},
|
||||
resize_on_border = false, allow_tearing = false, layout = "dwindle",
|
||||
},
|
||||
decoration = {
|
||||
rounding = 10, rounding_power = 2,
|
||||
active_opacity = 1.0, inactive_opacity = 1.0,
|
||||
shadow = { enabled = true, range = 4, render_power = 3, color = 0xee1a1a1a },
|
||||
blur = { enabled = true, size = 3, passes = 1, vibrancy = 0.1696 },
|
||||
},
|
||||
animations = { enabled = true },
|
||||
})
|
||||
|
||||
hl.curve("easeOutQuint", { type = "bezier", points = { {0.23,1},{0.32,1} } })
|
||||
hl.curve("easeInOutCubic", { type = "bezier", points = { {0.65,0.05},{0.36,1} } })
|
||||
hl.curve("linear", { type = "bezier", points = { {0,0},{1,1} } })
|
||||
hl.curve("almostLinear", { type = "bezier", points = { {0.5,0.5},{0.75,1} } })
|
||||
hl.curve("quick", { type = "bezier", points = { {0.15,0},{0.1,1} } })
|
||||
hl.curve("easy", { type = "spring", mass = 1, stiffness = 71.2633, dampening = 15.8273644 })
|
||||
|
||||
hl.animation({ leaf = "global", enabled = true, speed = 10, bezier = "default" })
|
||||
hl.animation({ leaf = "border", enabled = true, speed = 5.39, bezier = "easeOutQuint" })
|
||||
hl.animation({ leaf = "windows", enabled = true, speed = 4.79, spring = "easy" })
|
||||
hl.animation({ leaf = "windowsIn", enabled = true, speed = 4.1, spring = "easy", style = "popin 87%" })
|
||||
hl.animation({ leaf = "windowsOut", enabled = true, speed = 1.49, bezier = "linear", style = "popin 87%" })
|
||||
hl.animation({ leaf = "fadeIn", enabled = true, speed = 1.73, bezier = "almostLinear" })
|
||||
hl.animation({ leaf = "fadeOut", enabled = true, speed = 1.46, bezier = "almostLinear" })
|
||||
hl.animation({ leaf = "fade", enabled = true, speed = 3.03, bezier = "quick" })
|
||||
hl.animation({ leaf = "layers", enabled = true, speed = 3.81, bezier = "easeOutQuint" })
|
||||
hl.animation({ leaf = "layersIn", enabled = true, speed = 4, bezier = "easeOutQuint", style = "fade" })
|
||||
hl.animation({ leaf = "layersOut", enabled = true, speed = 1.5, bezier = "linear", style = "fade" })
|
||||
hl.animation({ leaf = "fadeLayersIn", enabled = true, speed = 1.79, bezier = "almostLinear" })
|
||||
hl.animation({ leaf = "fadeLayersOut", enabled = true, speed = 1.39, bezier = "almostLinear" })
|
||||
hl.animation({ leaf = "workspaces", enabled = true, speed = 1.94, bezier = "almostLinear", style = "fade" })
|
||||
hl.animation({ leaf = "workspacesIn", enabled = true, speed = 1.21, bezier = "almostLinear", style = "fade" })
|
||||
hl.animation({ leaf = "workspacesOut", enabled = true, speed = 1.94, bezier = "almostLinear", style = "fade" })
|
||||
hl.animation({ leaf = "zoomFactor", enabled = true, speed = 7, bezier = "quick" })
|
||||
|
||||
hl.config({ dwindle = { preserve_split = true } })
|
||||
hl.config({ master = { new_status = "master" } })
|
||||
hl.config({ misc = { force_default_wallpaper = 0, disable_hyprland_logo = true } })
|
||||
|
||||
---------------------
|
||||
---- KEYBINDINGS ----
|
||||
---------------------
|
||||
|
||||
-- Core binds
|
||||
hl.bind(mainMod .. " + Q", hl.dsp.window.close())
|
||||
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(terminal))
|
||||
hl.bind(mainMod .. " + RETURN", hl.dsp.exec_cmd(terminal))
|
||||
hl.bind(mainMod .. " + M", hl.dsp.exec_cmd("command -v hyprshutdown >/dev/null 2>&1 && hyprshutdown || hyprctl dispatch 'hl.dsp.exit()'"))
|
||||
hl.bind(mainMod .. " + E", hl.dsp.exec_cmd(fileManager))
|
||||
hl.bind(mainMod .. " + V", hl.dsp.window.float({ action = "toggle" }))
|
||||
hl.bind(mainMod .. " + D", hl.dsp.exec_cmd(menu))
|
||||
hl.bind(mainMod .. " + P", hl.dsp.window.pseudo())
|
||||
hl.bind(mainMod .. " + J", hl.dsp.layout("togglesplit"))
|
||||
|
||||
-- Worktime safers
|
||||
hl.bind(mainMod .. " + F", hl.dsp.window.fullscreen({ mode = 0 }))
|
||||
hl.bind(mainMod .. " + R", hl.dsp.exec_cmd("hyprctl reload"))
|
||||
hl.bind(mainMod .. " + SPACE", hl.dsp.window.float({ action = "toggle" }))
|
||||
hl.bind(mainMod .. " + TAB", hl.dsp.exec_cmd("hyprctl dispatch cyclenext"))
|
||||
hl.bind(mainMod .. " + SHIFT + TAB", hl.dsp.exec_cmd("hyprctl dispatch cyclenext prev"))
|
||||
|
||||
-- Scratchpad
|
||||
hl.bind(mainMod .. " + GRAVE", hl.dsp.workspace.toggle_special("magic"))
|
||||
hl.bind(mainMod .. " + SHIFT + GRAVE", hl.dsp.window.move({ workspace = "special:magic" }))
|
||||
|
||||
-- Home row focus
|
||||
hl.bind(mainMod .. " + H", hl.dsp.focus({ direction = "left" }))
|
||||
hl.bind(mainMod .. " + L", hl.dsp.focus({ direction = "right" }))
|
||||
|
||||
-- Home row move window
|
||||
hl.bind(mainMod .. " + SHIFT + H", hl.dsp.window.move({ direction = "left" }))
|
||||
hl.bind(mainMod .. " + SHIFT + L", hl.dsp.window.move({ direction = "right" }))
|
||||
hl.bind(mainMod .. " + SHIFT + K", hl.dsp.window.move({ direction = "up" }))
|
||||
hl.bind(mainMod .. " + SHIFT + J", hl.dsp.window.move({ direction = "down" }))
|
||||
|
||||
-- Home row resize
|
||||
hl.bind(mainMod .. " + ALT + H", hl.dsp.exec_cmd("hyprctl dispatch resizeactive -40 0"))
|
||||
hl.bind(mainMod .. " + ALT + L", hl.dsp.exec_cmd("hyprctl dispatch resizeactive 40 0"))
|
||||
hl.bind(mainMod .. " + ALT + K", hl.dsp.exec_cmd("hyprctl dispatch resizeactive 0 -40"))
|
||||
hl.bind(mainMod .. " + ALT + J", hl.dsp.exec_cmd("hyprctl dispatch resizeactive 0 40"))
|
||||
|
||||
-- Arrow focus
|
||||
hl.bind(mainMod .. " + left", hl.dsp.focus({ direction = "left" }))
|
||||
hl.bind(mainMod .. " + right", hl.dsp.focus({ direction = "right" }))
|
||||
hl.bind(mainMod .. " + up", hl.dsp.focus({ direction = "up" }))
|
||||
hl.bind(mainMod .. " + down", hl.dsp.focus({ direction = "down" }))
|
||||
|
||||
-- Arrow move window
|
||||
hl.bind(mainMod .. " + SHIFT + left", hl.dsp.window.move({ direction = "left" }))
|
||||
hl.bind(mainMod .. " + SHIFT + right", hl.dsp.window.move({ direction = "right" }))
|
||||
hl.bind(mainMod .. " + SHIFT + up", hl.dsp.window.move({ direction = "up" }))
|
||||
hl.bind(mainMod .. " + SHIFT + down", hl.dsp.window.move({ direction = "down" }))
|
||||
|
||||
-- Lock, browser
|
||||
hl.bind(mainMod .. " + CTRL + L", hl.dsp.exec_cmd("hyprlock"))
|
||||
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(browser))
|
||||
|
||||
-- Workspaces 1-9
|
||||
for i = 1, 9 do
|
||||
hl.bind(mainMod .. " + " .. i, hl.dsp.focus({ workspace = i }))
|
||||
hl.bind(mainMod .. " + SHIFT + " .. i, hl.dsp.window.move({ workspace = i }))
|
||||
end
|
||||
|
||||
-- Screenshots
|
||||
hl.bind("Print", hl.dsp.exec_cmd("grimblast copysave area"))
|
||||
hl.bind(mainMod .. " + Print", hl.dsp.exec_cmd("grimblast copysave active"))
|
||||
hl.bind(mainMod .. " + SHIFT + Print", hl.dsp.exec_cmd("grimblast copysave output"))
|
||||
hl.bind(mainMod .. " + ALT + Print", hl.dsp.exec_cmd('grim -g "$(slurp)" - | satty -f -'))
|
||||
|
||||
--------------------------------
|
||||
---- WINDOW RULES ----
|
||||
--------------------------------
|
||||
|
||||
hl.window_rule({
|
||||
name = "suppress-maximize-events",
|
||||
match = { class = ".*" },
|
||||
suppress_event = "maximize",
|
||||
})
|
||||
|
||||
hl.window_rule({
|
||||
name = "fix-xwayland-drags",
|
||||
match = { class = "^$", title = "^$", xwayland = true, float = true, fullscreen = false, pin = false },
|
||||
no_focus = true,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Hyprland Keybindings — Full Cheatsheet
|
||||
# Hyprland Keybindings - Full Cheatsheet
|
||||
|
||||
**Layout:** German (de) | **Mod key:** SUPER (Windows key) | **Source:** `hyprctl binds` live
|
||||
**Layout:** German (de) | **Mod key:** SUPER (Windows key) | **Config:** `hyprland.lua` (Hyprland 0.55+)
|
||||
|
||||
---
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
| `SUPER+SHIFT+TAB` | Cycle previous window | cyclenext prev |
|
||||
| `SUPER+` `` ` `` (Grave) | Toggle scratchpad | togglespecialworkspace |
|
||||
| `SUPER+SHIFT+` `` ` `` | Send window to scratchpad | movetoworkspace special |
|
||||
| `SUPER+CTRL+K` | Keybind cheat menu | *(broken — pipelines to grep+fuzzel)* |
|
||||
| `SUPER+CTRL+K` | Keybind cheat menu | *(broken - pipelines to grep+fuzzel)* |
|
||||
| `SUPER+CTRL+L` | Lock screen | hyprlock |
|
||||
| `SUPER+B` | Web browser | google-chrome-stable |
|
||||
|
||||
@@ -103,8 +103,10 @@ Every kitty terminal tile shows a title bar with:
|
||||
|
||||
## Notes
|
||||
|
||||
- `SUPER+CTRL+K` (keybind menu) does **not work** — the `sed` pipeline breaks. Needs fix.
|
||||
- The `sed` pipeline `sed 's/^bind\s*=\s*\$mainMod/SUPER/;s/\s*#/#/'` fails silently because the unescaped `$` in the `sed` command gets interpreted as a variable.
|
||||
- `SUPER+CTRL+K` (keybind menu) does **not work** - the `sed` pipeline breaks.
|
||||
The Lua config format makes this harder to grep; consider a different approach.
|
||||
- Config migrated from `.conf` to `.lua` format (Hyprland 0.55+).
|
||||
See `docs/tech/hyprland-lua-migration.md` for the migration mapping.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
# Hyprland Lua Config Migration (0.55+)
|
||||
|
||||
## Summary
|
||||
|
||||
Hyprland 0.55 deprecates the legacy `hyprlang` (`.conf`) format in favor of a native Lua
|
||||
DSL (`hyprland.lua`). Both formats coexist during transition, but `.lua` is the future.
|
||||
|
||||
## Configuration File Priority
|
||||
|
||||
| File | Format | Priority |
|
||||
|------|--------|----------|
|
||||
| `~/.config/hypr/hyprland.lua` | Lua DSL (`hl.*` API) | **Preferred** (0.55+) |
|
||||
| `~/.config/hypr/hyprland.conf` | Legacy hyprlang | Deprecated |
|
||||
|
||||
When both exist, Hyprland loads `.lua` first. If `.lua` is present, `.conf` is ignored.
|
||||
|
||||
## Lua API Quick Reference
|
||||
|
||||
```lua
|
||||
-- Variables
|
||||
local terminal = "kitty"
|
||||
local mainMod = "SUPER"
|
||||
|
||||
-- Config blocks
|
||||
hl.config({ general = { gaps_in = 5 } })
|
||||
hl.env("XCURSOR_SIZE", "24")
|
||||
hl.monitor({ output = "", mode = "preferred", position = "auto", scale = "auto" })
|
||||
|
||||
-- Keybindings (single combined key string)
|
||||
hl.bind(mainMod .. " + Q", hl.dsp.window.close())
|
||||
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(terminal))
|
||||
|
||||
-- Window/workspace rules
|
||||
hl.window_rule({ name = "my-rule", match = { class = ".*" }, suppress_event = "maximize" })
|
||||
hl.workspace_rule({ workspace = 1, monitor = "DP-1", default = true })
|
||||
|
||||
-- Autostart
|
||||
hl.on("hyprland.start", function() hl.exec_cmd("waybar &") end)
|
||||
|
||||
-- Gestures, animations
|
||||
hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" })
|
||||
hl.curve("easeOutQuint", { type = "bezier", points = { {0.23, 1}, {0.32, 1} } })
|
||||
hl.animation({ leaf = "windows", enabled = true, speed = 4.79, spring = "easy" })
|
||||
```
|
||||
|
||||
## Dispatcher Functions (`hl.dsp.*`)
|
||||
|
||||
| Lua API | Legacy .conf equivalent |
|
||||
|---------|------------------------|
|
||||
| `hl.dsp.exec_cmd("cmd")` | `exec, cmd` |
|
||||
| `hl.dsp.window.close()` | `killactive` |
|
||||
| `hl.dsp.window.float({ action = "toggle" })` | `togglefloating` |
|
||||
| `hl.dsp.window.pseudo()` | `pseudo` |
|
||||
| `hl.dsp.window.fullscreen({ mode = 0 })` | `fullscreen, 0` |
|
||||
| `hl.dsp.window.move({ direction = "left" })` | `movewindow, l` |
|
||||
| `hl.dsp.window.move({ workspace = 2 })` | `movetoworkspace, 2` |
|
||||
| `hl.dsp.window.drag()` / `.resize()` | mouse bind |
|
||||
| `hl.dsp.focus({ direction = "left" })` | `movefocus, l` |
|
||||
| `hl.dsp.focus({ workspace = 2 })` | `workspace, 2` |
|
||||
| `hl.dsp.focus({ workspace = "e+1" })` | `workspace, e+1` |
|
||||
| `hl.dsp.workspace.toggle_special("magic")` | `togglespecialworkspace` |
|
||||
| `hl.dsp.layout("togglesplit")` | `layoutmsg, togglesplit` |
|
||||
|
||||
## Pitfalls Learned
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| `hl.dsp.focus({ direction = "next" })` | **Invalid.** Only `left/right/up/down` accepted. Use `hl.dsp.exec_cmd("hyprctl dispatch cyclenext")` instead. |
|
||||
| `tap-to-click = true` | **Invalid Lua.** Hyphens not allowed in identifiers. Use `tap_to_click` (Hyprland accepts underscores). |
|
||||
| `hl.bind("", "Print", ...)` | **Invalid.** Lua API uses single key string: `hl.bind("Print", ...)`. |
|
||||
| `hl.bind(mainMod, "Q", ...)` | **Invalid.** Combine into one string: `hl.bind(mainMod .. " + Q", ...)`. |
|
||||
| `resizeactive` not in `hl.dsp.*` | Use `hl.dsp.exec_cmd("hyprctl dispatch resizeactive -40 0")` as wrapper. |
|
||||
| `luac -p` false positives | Standard `luac` can't validate Hyprland's custom `hl.*` API. Use `hyprctl configerrors` at runtime instead. |
|
||||
|
||||
## Validation
|
||||
|
||||
```bash
|
||||
# Runtime validation (requires running Hyprland session)
|
||||
hyprctl configerrors
|
||||
|
||||
# Over SSH (find instance signature first)
|
||||
HYPRLAND_INSTANCE_SIGNATURE=$(ls /run/user/$(id -u)/hypr/) hyprctl configerrors
|
||||
|
||||
# Syntax-only check (limited - won't catch hl.* API issues)
|
||||
luac -p ~/.config/hypr/hyprland.lua
|
||||
```
|
||||
|
||||
## conf-to-lua Migration Mapping
|
||||
|
||||
| Legacy `.conf` | Lua `.lua` |
|
||||
|----------------|------------|
|
||||
| `$mainMod = SUPER` | `local mainMod = "SUPER"` |
|
||||
| `monitor=DP-1,...` | `hl.monitor({ output = "DP-1", ... })` |
|
||||
| `env = KEY,VALUE` | `hl.env("KEY", "VALUE")` |
|
||||
| `input { ... }` | `hl.config({ input = { ... } })` |
|
||||
| `general { ... }` | `hl.config({ general = { ... } })` |
|
||||
| `bind = MOD, KEY, exec, cmd` | `hl.bind(mod .. " + KEY", hl.dsp.exec_cmd("cmd"))` |
|
||||
| `bind = MOD, KEY, killactive` | `hl.bind(mod .. " + KEY", hl.dsp.window.close())` |
|
||||
| `bind = MOD, KEY, togglefloating` | `hl.bind(mod .. " + KEY", hl.dsp.window.float({ action = "toggle" }))` |
|
||||
| `bind = MOD, KEY, fullscreen, 0` | `hl.bind(mod .. " + KEY", hl.dsp.window.fullscreen({ mode = 0 }))` |
|
||||
| `bind = MOD, KEY, movefocus, l` | `hl.bind(mod .. " + KEY", hl.dsp.focus({ direction = "left" }))` |
|
||||
| `bind = MOD, KEY, movewindow, l` | `hl.bind(mod .. " + KEY", hl.dsp.window.move({ direction = "left" }))` |
|
||||
| `bind = MOD, KEY, workspace, N` | `hl.bind(mod .. " + KEY", hl.dsp.focus({ workspace = N }))` |
|
||||
| `bind = MOD, KEY, cyclenext` | `hl.bind(mod .. " + KEY", hl.dsp.exec_cmd("hyprctl dispatch cyclenext"))` |
|
||||
| `bind = MOD, KEY, pseudo` | `hl.bind(mod .. " + KEY", hl.dsp.window.pseudo())` |
|
||||
| `bind = MOD, KEY, layoutmsg, togglesplit` | `hl.bind(mod .. " + KEY", hl.dsp.layout("togglesplit"))` |
|
||||
| `bind = , Print, exec, cmd` | `hl.bind("Print", hl.dsp.exec_cmd("cmd"))` |
|
||||
| `bind = MOD, KEY, exit` | `hl.bind(mod .. " + KEY", hl.dsp.exec_cmd("hyprctl dispatch exit"))` |
|
||||
| `device { name = "..."; ... }` | `hl.device({ name = "...", ... })` |
|
||||
| `workspace = 1, monitor:DP-1, default:true` | `hl.workspace_rule({ workspace = 1, monitor = "DP-1", default = true })` |
|
||||
| `exec-once = cmd` | `hl.on("hyprland.start", function() hl.exec_cmd("cmd") end)` |
|
||||
| `col.active_border = rgba(...) 45deg` | `col = { active_border = { colors = {"rgba(...)"}, angle = 45 } }` |
|
||||
|
||||
## Multi-Machine Setup
|
||||
|
||||
This project manages configs for two machines with identical keybindings but different hardware:
|
||||
|
||||
| Aspect | Workstation (pfeddersheim) | MacBook Pro 16,1 |
|
||||
|--------|---------------------------|-------------------|
|
||||
| GPU | NVIDIA (6 env vars) | Intel UHD 630 + AMD RX 5500M (no env vars) |
|
||||
| Monitors | 3 fixed (DP-1, DVI-D-1, HDMI-A-1) | Built-in + HDMI dock (auto-detect) |
|
||||
| Input | de layout, left-handed mouse | de + mac_nodeadkeys + caps:swapescape, touchpad |
|
||||
| Touchpad | N/A | natural_scroll, gestures, disable_while_typing |
|
||||
| Media keys | N/A | Volume, brightness, playerctl |
|
||||
| Window rules | None | Suppress maximize, XWayland fix |
|
||||
| Config format | `.lua` (Ansible-managed) | `.lua` (manual) |
|
||||
Reference in New Issue
Block a user