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:
ja
2026-06-15 06:43:23 +02:00
co-authored by Junie
parent f1544747a0
commit fe7f133136
4 changed files with 324 additions and 6 deletions
+1 -1
View File
@@ -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,
})