diff --git a/dot_config/hypr/hypridle.conf b/dot_config/hypr/hypridle.conf.tmpl similarity index 64% rename from dot_config/hypr/hypridle.conf rename to dot_config/hypr/hypridle.conf.tmpl index 7cf710d..fa40d58 100644 --- a/dot_config/hypr/hypridle.conf +++ b/dot_config/hypr/hypridle.conf.tmpl @@ -1,3 +1,4 @@ +{{- $tags := .chezmoi.config.data.tags -}} ### based on the example config from hyprland.org general { @@ -8,20 +9,25 @@ general { ignore_systemd_inhibit = false # whether to ignore systemd-inhibit --what=idle inhibitors } +{{ if index $tags "laptop" -}} +# Laptop: aggressive timeouts to save battery. +listener { + timeout = 180 # 3min + on-timeout = hyprctl dispatch dpms off # screen off + on-resume = hyprctl dispatch dpms on +} -#listener { -# timeout = 150 # 2.5min. -# on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor. -# on-resume = brightnessctl -r # monitor backlight restore. -#} - -# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight. -#listener { -# timeout = 150 # 2.5min. -# on-timeout = brightnessctl -sd rgb:kbd_backlight set 0 # turn off keyboard backlight. -# on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight. -#} +listener { + timeout = 360 # 6min + on-timeout = loginctl lock-session # lock screen +} +listener { + timeout = 900 # 15min + on-timeout = systemctl suspend # suspend +} +{{- else -}} +# Desktop: relaxed timeouts. listener { timeout = 300 # 5min on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed @@ -37,3 +43,4 @@ listener { timeout = 1200 # 20min on-timeout = systemctl suspend # suspend pc } +{{- end }} diff --git a/dot_config/hypr/hyprland.d.lua/input.lua.tmpl b/dot_config/hypr/hyprland.d.lua/input.lua.tmpl index 6489f5b..8f9ef01 100644 --- a/dot_config/hypr/hyprland.d.lua/input.lua.tmpl +++ b/dot_config/hypr/hyprland.d.lua/input.lua.tmpl @@ -4,7 +4,9 @@ hl.config({ input = { kb_layout = "ultimatekeys", kb_options = "caps:escape_shifted_capslock", + {{- if (index $tags "desktop") }} numlock_by_default = true, + {{- end }} repeat_rate = 25, repeat_delay = 600, follow_mouse = 0, @@ -13,11 +15,13 @@ hl.config({ mouse_refocus = true, float_switch_override_focus = 2, special_fallthrough = true, + {{- if (index $tags "laptop") }} touchpad = { disable_while_typing = true, scroll_factor = 1.0, tap_to_click = true } + {{- end }} } }) @@ -28,3 +32,26 @@ hl.device({ accel_profile = "flat" }) {{- end }} + +{{- if (index $tags "laptop") }} +-- Trackpad gestures (v0.55 API): 3-finger horizontal swipe → workspaces, +-- 4-finger vertical swipe → special workspace. +hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" }) +hl.gesture({ fingers = 4, direction = "vertical", action = "special" }) +{{- end }} + +{{- if (index $tags "touchscreen") }} +-- Map touchscreen + stylus to the internal display so input coords +-- don't stretch across external monitors when docked. +hl.config({ + input = { + tablet = { + output = "eDP-1", + relative_input = false + } + } +}) +hl.device({ name = "ipts-045e:001f-touchscreen", output = "eDP-1" }) +hl.device({ name = "iptsd-virtual-stylus-045e:001f", output = "eDP-1" }) +hl.device({ name = "iptsd-virtual-touchscreen-045e:001f", output = "eDP-1" }) +{{- end }} diff --git a/dot_config/hypr/hyprland.d.lua/keybinds.lua.tmpl b/dot_config/hypr/hyprland.d.lua/keybinds.lua.tmpl index e92b08a..2163b07 100644 --- a/dot_config/hypr/hyprland.d.lua/keybinds.lua.tmpl +++ b/dot_config/hypr/hyprland.d.lua/keybinds.lua.tmpl @@ -380,3 +380,65 @@ hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { locked = tr hl.bind("XF86AudioPause", hl.dsp.exec_cmd("playerctl play-pause"), { locked = true, description = "Play/pause" }) hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { locked = true, description = "Next track" }) hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { locked = true, description = "Previous track" }) + +-- Brightness — let brightnessctl do the math; parse its -m output for the OSD. +local function brightness_step(arg) + return function() + local f = io.popen("brightnessctl -e4 -n2 -m s " .. arg .. " 2>/dev/null") + if not f then return end + local line = f:read("*l"); f:close() + local pct = line and line:match("[^,]*,[^,]*,[^,]*,(%d+)%%") + if pct then + hl.notification.create({ text = "Brightness: " .. pct .. "%", timeout = 1200, icon = "info" }) + end + end +end +hl.bind("XF86MonBrightnessUp", brightness_step("1%+"), { locked = true, repeating = true, description = "Brightness up (1%)" }) +hl.bind("XF86MonBrightnessDown", brightness_step("1%-"), { locked = true, repeating = true, description = "Brightness down (1%)" }) +hl.bind("SHIFT + XF86MonBrightnessUp", brightness_step("5%+"), { locked = true, repeating = true, description = "Brightness up (5%)" }) +hl.bind("SHIFT + XF86MonBrightnessDown", brightness_step("5%-"), { locked = true, repeating = true, description = "Brightness down (5%)" }) +hl.bind("CTRL + XF86MonBrightnessUp", brightness_step("70%"), { locked = true, description = "Brightness 70%" }) +hl.bind("CTRL + XF86MonBrightnessDown", brightness_step("20%"), { locked = true, description = "Brightness 20%" }) + +{{- if (index .chezmoi.config.data.tags "laptop") }} + +-- ─── Surface Type Cover ────────────────────────────────────────────────────── +local tc_touchpad = "microsoft-surface-type-cover-touchpad" +local tc_keyboard = "microsoft-surface-type-cover-keyboard" + +local function device_enabled(name) + -- Reads live state; falls back to true on any error so toggles still work. + local ok, v = pcall(hl.get_config, "device[" .. name .. "]:enabled") + if not ok then return true end + if v == nil then return true end + return v ~= false and v ~= 0 and v ~= "false" +end + +local function set_device(name, enabled) + hl.device({ name = name, enabled = enabled }) +end + +-- SUPER+T: toggle touchpad based on live state (no local-cache desync) +hl.bind(mainMod .. " + T", function() + local new_state = not device_enabled(tc_touchpad) + set_device(tc_touchpad, new_state) + hl.notification.create({ + text = "Touchpad: " .. (new_state and "ON" or "OFF"), + timeout = 1500, + icon = new_state and "ok" or "info", + }) +end, { description = "Toggle touchpad" }) + +-- Tablet-mode switch: fold cover back → disable kb+touchpad, unfold → re-enable +hl.bind("switch:on:Microsoft Surface Type Cover Tablet Mode Switch", function() + set_device(tc_touchpad, false) + set_device(tc_keyboard, false) + hl.notification.create({ text = "Tablet mode", timeout = 1500, icon = "info" }) +end, { description = "Tablet mode: disable Type Cover" }) + +hl.bind("switch:off:Microsoft Surface Type Cover Tablet Mode Switch", function() + set_device(tc_touchpad, true) + set_device(tc_keyboard, true) + hl.notification.create({ text = "Laptop mode", timeout = 1500, icon = "ok" }) +end, { description = "Laptop mode: enable Type Cover" }) +{{- end }} diff --git a/dot_config/hypr/hyprland.d.lua/rules.lua.tmpl b/dot_config/hypr/hyprland.d.lua/rules.lua.tmpl index 1c5d0b0..19e117d 100644 --- a/dot_config/hypr/hyprland.d.lua/rules.lua.tmpl +++ b/dot_config/hypr/hyprland.d.lua/rules.lua.tmpl @@ -34,7 +34,11 @@ hl.config({ }) -- Permissions (NEW in v0.55) -hl.permission({ binary = "/usr/bin/grim", type = "screencopy", mode = "allow" }) +hl.permission({ binary = "/usr/bin/grim", type = "screencopy", mode = "allow" }) +hl.permission({ binary = "/usr/bin/grimblast", type = "screencopy", mode = "allow" }) +hl.permission({ binary = "/usr/bin/wf-recorder", type = "screencopy", mode = "allow" }) +hl.permission({ binary = "/usr/lib/xdg-desktop-portal-hyprland", type = "screencopy", mode = "allow" }) +hl.permission({ binary = "/usr/bin/hyprpm", type = "plugin", mode = "allow" }) -- Window Rules hl.window_rule({ match = { class = ".*" }, suppress_event = "maximize" }) diff --git a/dot_config/hypr/hyprland.lua.tmpl b/dot_config/hypr/hyprland.lua.tmpl index 15c1a6d..b9c16b3 100644 --- a/dot_config/hypr/hyprland.lua.tmpl +++ b/dot_config/hypr/hyprland.lua.tmpl @@ -12,3 +12,11 @@ require("input") require("layout") require("rules") require("keybinds") + +{{- if (index $tags "touchscreen") }} +-- Auto-rotate eDP-1 based on accelerometer (iio-sensor-proxy + iio-hyprland). +-- Requires: yay -S iio-sensor-proxy iio-hyprland && systemctl enable --now iio-sensor-proxy +hl.on("hyprland.start", function() + hl.dispatch(hl.dsp.exec_cmd("uwsm app -- iio-hyprland")) +end) +{{- end }}