hyprland settings rework

This commit is contained in:
2026-09-12 22:52:47 +01:00
parent d41aac2a41
commit bc9794ff00
6 changed files with 410 additions and 298 deletions
+9 -4
View File
@@ -48,24 +48,25 @@
# "npm:@odinlayer/pi-provider-litellm"
"npm:pi-provider-litellm"
# Web search / content extraction (opencode-crawlberg + opencode-html-to-markdown equivalent)
"npm:pi-web-access"
# "npm:pi-web-access"
# Local document parsing / OCR (opencode-xberg equivalent)
"npm:pi-docparser"
# "npm:@gotgenes/pi-permission-system"
"npm:@vanillagreen/pi-extension-manager"
# "npm:@vanillagreen/pi-extension-manager"
# "npm:@vanillagreen/pi-qol"
"npm:pi-vitals"
"npm:pi-spark"
# "npm:pi-spark"
# "npm:pi-caveman"
"npm:@tmustier/pi-usage-extension"
"npm:@heyhuynhgiabuu/pi-pretty"
"npm:pi-lens"
# "npm:pi-lens"
# "npm:pi-lean-ctx"
# "npm:@rohaquinlop/pi-deepseek-cache"
"npm:pi-cache-optimizer"
"npm:pi-opencode-go-cache"
"npm:@pi-vault/pi-dcp"
"git:github.com/DietrichGebert/ponytail"
"npm:pi-commandcode-provider"
];
};
context = ''
@@ -172,6 +173,10 @@
"type" = "api_key";
"key" = "$OPENCODE_GO_API_KEY";
};
"command-code" = {
"type" = "api_key";
"key" = "$COMMANDCODE_API_KEY";
};
};
};
+4 -10
View File
@@ -15,7 +15,7 @@
};
modules.helium = settings: {
homeManager =
{ pkgs, ... }:
{ pkgs, lib, ... }:
let
heliumPkg = inputs.heliumFlake.packages.${pkgs.stdenv.hostPlatform.system}.helium;
# The upstream `helium` launcher is a plain Nix wrapper that ignores any
@@ -53,15 +53,9 @@
xdg.configFile."net.imput.helium/WidevineCdm/latest-component-updated-widevine-cdm" = {
text = ''{"Path":"${pkgs.widevine-cdm}/share/google/chrome/WidevineCdm"}'';
};
wayland.windowManager.hyprland.extraLuaFiles = lib.mkIf settings.default {
"helium-bind.lua" = {
autoLoad = true;
content = ''
-- Helium launcher bind (lua config: settings.bind cannot express dispatchers)
hl.bind("SUPER + E", hl.dsp.exec_cmd("helium"))
'';
};
};
wayland.windowManager.hyprland.settings.bind = lib.mkIf settings.default [
{ _args = [ "SUPER + E" (lib.generators.mkLuaInline ''hl.dsp.exec_cmd("helium")'') ]; }
];
};
};
}
+280 -161
View File
@@ -9,7 +9,7 @@
homeManager =
{
pkgs,
home,
lib,
...
}:
let
@@ -34,175 +34,91 @@
mreowScript = pkgs.writeShellScript "mreow" ''
exec $(tofi-drun -c ${tofiCfg})
'';
mainMod = "SUPER";
hlBind = key: dispatcher: "hl.bind(\"${key}\", ${dispatcher})";
workspaceLines = pkgs.lib.concatLists (
# Each `settings.<fn>` list entry renders as `hl.<fn>(<table>)`.
# `_args` renders a multi-argument call instead of one Lua table,
# and mkLuaInline passes raw Lua through for dispatchers.
dsp = lib.generators.mkLuaInline;
bind = key: dispatcher: { _args = [ key dispatcher ]; };
bezier = name: points: {
_args = [
name
{
type = "bezier";
inherit points;
}
];
};
wsBinds = lib.concatLists (
builtins.genList (
i:
let
ws = toString (i + 1);
in
[
(hlBind "${mainMod} + ${ws}" "hl.dsp.focus({ workspace = ${ws} })")
(hlBind "${mainMod} + SHIFT + ${ws}" "hl.dsp.window.move({ workspace = ${ws} })")
(bind "${mainMod} + ${ws}" (dsp ''hl.dsp.focus({ workspace = ${ws} })''))
(bind "${mainMod} + SHIFT + ${ws}" (dsp ''hl.dsp.window.move({ workspace = ${ws} })''))
]
) 9
);
hlBindCode = pkgs.lib.concatStringsSep "\n" (
[
"-- Hyprland configuration"
""
"local mainMod = \"${mainMod}\""
""
"-- Config"
"hl.config({"
" general = {"
" gaps_in = 1,"
" gaps_out = 1,"
" border_size = 1,"
" resize_on_border = false,"
" allow_tearing = true,"
" layout = \"dwindle\","
" },"
" input = {"
" follow_mouse = 2,"
" kb_layout = \"gb\","
" },"
" decoration = {"
" rounding = 4,"
" rounding_power = 1,"
" active_opacity = 1.0,"
" inactive_opacity = 1.0,"
" shadow = {"
" enabled = false,"
" },"
" blur = {"
" enabled = true,"
" passes = 1,"
" new_optimizations = true,"
" ignore_opacity = false,"
" },"
" },"
" cursor = {"
" no_hardware_cursors = false,"
" },"
" dwindle = {"
" preserve_split = true,"
" },"
" misc = {"
" force_default_wallpaper = -1,"
" disable_hyprland_logo = false,"
" enable_anr_dialog = false,"
" },"
"})"
""
"-- Monitors"
"hl.monitor({ output = \"HDMI-A-1\", mode = \"1920x1080@60\", position = \"0x0\", scale = \"1\" })"
"hl.monitor({ output = \"DP-2\", mode = \"1920x1080@120\", position = \"1920x0\", scale = \"1\" })"
""
"-- Input"
"hl.device({ name = \"default\", kb_layout = \"gb\", sensitivity = -0.5 })"
""
"-- Curves"
"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} } })"
""
"-- Animations"
"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 = 2.79, bezier = \"easeOutQuint\" })"
"hl.animation({ leaf = \"windowsIn\", enabled = true, speed = 1, bezier = \"easeOutQuint\", style = \"popin 87%\" })"
"hl.animation({ leaf = \"windowsOut\", enabled = true, speed = 1, bezier = \"linear\", style = \"popin 87%\" })"
"hl.animation({ leaf = \"windowsMove\", enabled = true, speed = 1, bezier = \"easeInOutCubic\" })"
"hl.animation({ leaf = \"fadeIn\", enabled = true, speed = 0.5, bezier = \"almostLinear\" })"
"hl.animation({ leaf = \"fadeOut\", enabled = true, speed = 0.5, bezier = \"almostLinear\" })"
"hl.animation({ leaf = \"fade\", enabled = true, speed = 1, 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, bezier = \"almostLinear\", style = \"slide\" })"
"hl.animation({ leaf = \"workspacesIn\", enabled = true, speed = 1, bezier = \"easeInOutCubic\", style = \"slide\" })"
"hl.animation({ leaf = \"workspacesOut\", enabled = true, speed = 1, bezier = \"easeInOutCubic\", style = \"slide\" })"
"hl.animation({ leaf = \"zoomFactor\", enabled = true, speed = 7, bezier = \"quick\" })"
""
"-- Binds"
(hlBind "${mainMod} + R" "hl.dsp.exec_cmd(\"${mreowScript}\")")
(hlBind "${mainMod} + C" "hl.dsp.window.close()")
(hlBind "${mainMod} + M" "hl.dsp.exec_cmd(\"uwsm stop\")")
(hlBind "${mainMod} + Q" "hl.dsp.exec_cmd(\"kitty\")")
(hlBind "${mainMod} + V" "hl.dsp.window.float({ action = \"toggle\" })")
(hlBind "${mainMod} + left" "hl.dsp.focus({ direction = \"left\" })")
(hlBind "${mainMod} + right" "hl.dsp.focus({ direction = \"right\" })")
(hlBind "${mainMod} + up" "hl.dsp.focus({ direction = \"up\" })")
(hlBind "${mainMod} + down" "hl.dsp.focus({ direction = \"down\" })")
(hlBind "${mainMod} + L" "hl.dsp.exec_cmd(\"wlogout\")")
(hlBind "${mainMod} + S" "hl.dsp.exec_cmd(\"wayfreeze --after-freeze-cmd '${meowScript}'\")")
(hlBind "${mainMod} + F" "hl.dsp.window.fullscreen({ action = \"toggle\" })")
(hlBind "${mainMod} + SHIFT + Q" "hl.dsp.window.close()")
(hlBind "${mainMod} + mouse_down" "hl.dsp.focus({ workspace = \"e+1\" })")
(hlBind "${mainMod} + mouse_up" "hl.dsp.focus({ workspace = \"e-1\" })")
""
"-- Mouse binds"
(hlBind "${mainMod} + mouse:272" "hl.dsp.window.drag()")
(hlBind "${mainMod} + mouse:273" "hl.dsp.window.resize()")
""
"-- Media keys"
(hlBind "XF86AudioLowerVolume" "hl.dsp.exec_cmd(\"wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-\")")
(hlBind "XF86AudioRaiseVolume" "hl.dsp.exec_cmd(\"wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+\")")
(hlBind "XF86AudioMute" "hl.dsp.exec_cmd(\"wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle\")")
(hlBind "XF86AudioPlay" "hl.dsp.exec_cmd(\"playerctl play-pause\")")
(hlBind "XF86AudioNext" "hl.dsp.exec_cmd(\"playerctl next\")")
(hlBind "XF86AudioPrev" "hl.dsp.exec_cmd(\"playerctl previous\")")
(hlBind "XF86AudioMicMute" "hl.dsp.exec_cmd(\"wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle\")")
(hlBind "home" "hl.dsp.exec_cmd(\"wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle\")")
(hlBind "end" "hl.dsp.exec_cmd(\"wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle\")")
(hlBind "F8" "hl.dsp.pass({ window = [[match:class:^(com.obsproject.Studio)$]] })")
""
"-- Workspaces"
(hlBind "${mainMod} + 0" "hl.dsp.focus({ workspace = 10 })")
(hlBind "${mainMod} + SHIFT + 0" "hl.dsp.window.move({ workspace = 10 })")
]
++ workspaceLines
++ [
""
"-- Window rules"
"hl.window_rule({ suppress_event = \"maximize\" })"
"hl.window_rule({ match = { class = \"gamescope\" }, workspace = \"5\", immediate = true, confine_pointer = true })"
"hl.window_rule({ match = { initial_title = \"OBS Studio Crash Detected\" }, pin = true })"
"hl.window_rule({ match = { initial_title = \"Discord Popout\" }, workspace = \"1 silent\" })"
""
"-- Layer rules"
"hl.layer_rule({ match = { namespace = \"notifications\" }, no_screen_share = true })"
""
"-- Host-specific overrides: load ~/.config/hypr/hyprland-local.lua if present (must be valid Lua)"
"local home = os.getenv(\"HOME\")"
"if home then"
" local localPath = home .. '/.config/hypr/hyprland-local.lua'"
" local f = io.open(localPath, 'r')"
" if f then"
" f:close()"
" local chunk, err = loadfile(localPath)"
" if chunk then chunk() else io.stderr:write('hyprland-local.lua error: ' .. err .. '\\n') end"
" end"
"end"
]
);
in
{
home.packages = [
pkgs.hyprcursor
pkgs.wlogout
pkgs.hyprshutdown
pkgs.tofi
pkgs.killall
pkgs.grim
pkgs.slurp
pkgs.wayclip
];
# wlogout menu. Default layout, except Shutdown hands off to
# hyprshutdown so apps close gracefully before poweroff.
# programs.wlogout only accepts one command per button, so
# --post-cmd carries the actual poweroff.
programs.wlogout = {
enable = true;
layout = [
{
label = "lock";
action = "loginctl lock-session";
text = "Lock";
keybind = "l";
}
{
label = "hibernate";
action = "systemctl hibernate";
text = "Hibernate";
keybind = "h";
}
{
label = "logout";
action = "loginctl terminate-user $USER";
text = "Logout";
keybind = "e";
}
{
label = "shutdown";
action = "hyprshutdown --post-cmd 'systemctl poweroff'";
text = "Shutdown";
keybind = "s";
}
{
label = "suspend";
action = "systemctl suspend";
text = "Suspend";
keybind = "u";
}
{
label = "reboot";
action = "systemctl reboot";
text = "Reboot";
keybind = "r";
}
];
};
home.pointerCursor = {
enable = true;
name = "rose-pine-hyprcursor";
@@ -225,17 +141,220 @@
];
};
};
# systemd.user.services.hyprpaper = {
# partOf = [ "hyprland-session.target" ];
# after = [ "hyprland-session.target" ];
# };
# Hand-written config as extraLuaFile so Home Manager still
# generates hypr/hyprland.lua itself, including the systemd
# session activation hooks (hyprland-session.target start/stop
# + dbus-update-activation-environment --systemd --all).
wayland.windowManager.hyprland.extraLuaFiles."hl-main.lua" = {
autoLoad = true;
content = hlBindCode;
# The systemd session activation hooks (hyprland-session.target
# start/stop + dbus-update-activation-environment --systemd --all)
# are still generated by Home Manager; only the imperative tail of
# the config needs raw Lua.
wayland.windowManager.hyprland = {
settings = {
config = {
general = {
gaps_in = 1;
gaps_out = 1;
border_size = 1;
resize_on_border = false;
allow_tearing = true;
layout = "dwindle";
};
input = {
follow_mouse = 2;
kb_layout = "gb";
};
decoration = {
rounding = 4;
rounding_power = 1;
active_opacity = 1.0;
inactive_opacity = 1.0;
shadow.enabled = false;
blur = {
enabled = true;
passes = 1;
new_optimizations = true;
ignore_opacity = false;
};
};
cursor.no_hardware_cursors = false;
dwindle.preserve_split = true;
misc = {
force_default_wallpaper = -1;
disable_hyprland_logo = false;
enable_anr_dialog = false;
};
};
monitor = [
{
output = "HDMI-A-1";
mode = "1920x1080@60";
position = "0x0";
scale = "1";
}
{
output = "DP-2";
mode = "1920x1080@120";
position = "1920x0";
scale = "1";
}
];
device = {
name = "default";
kb_layout = "gb";
sensitivity = -0.5;
};
# Curves are sorted ahead of animations by the module's
# `importantPrefixes` default, so the beziers exist by name.
curve = [
(bezier "easeOutQuint" [
[ 0.23 1 ]
[ 0.32 1 ]
])
(bezier "easeInOutCubic" [
[ 0.65 0.05 ]
[ 0.36 1 ]
])
(bezier "linear" [
[ 0 0 ]
[ 1 1 ]
])
(bezier "almostLinear" [
[ 0.5 0.5 ]
[ 0.75 1 ]
])
(bezier "quick" [
[ 0.15 0 ]
[ 0.1 1 ]
])
];
animation = [
{ leaf = "global"; enabled = true; speed = 10; bezier = "default"; }
{ leaf = "border"; enabled = true; speed = 5.39; bezier = "easeOutQuint"; }
{ leaf = "windows"; enabled = true; speed = 2.79; bezier = "easeOutQuint"; }
{ leaf = "windowsIn"; enabled = true; speed = 1; bezier = "easeOutQuint"; style = "popin 87%"; }
{ leaf = "windowsOut"; enabled = true; speed = 1; bezier = "linear"; style = "popin 87%"; }
{ leaf = "windowsMove"; enabled = true; speed = 1; bezier = "easeInOutCubic"; }
{ leaf = "fadeIn"; enabled = true; speed = 0.5; bezier = "almostLinear"; }
{ leaf = "fadeOut"; enabled = true; speed = 0.5; bezier = "almostLinear"; }
{ leaf = "fade"; enabled = true; speed = 1; bezier = "quick"; }
{ leaf = "layers"; enabled = true; speed = 3.81; bezier = "easeOutQuint"; }
{ leaf = "layersIn"; enabled = true; speed = 4; bezier = "easeOutQuint"; style = "fade"; }
{ leaf = "layersOut"; enabled = true; speed = 1.5; bezier = "linear"; style = "fade"; }
{ leaf = "fadeLayersIn"; enabled = true; speed = 1.79; bezier = "almostLinear"; }
{ leaf = "fadeLayersOut"; enabled = true; speed = 1.39; bezier = "almostLinear"; }
{ leaf = "workspaces"; enabled = true; speed = 1; bezier = "almostLinear"; style = "slide"; }
{ leaf = "workspacesIn"; enabled = true; speed = 1; bezier = "easeInOutCubic"; style = "slide"; }
{ leaf = "workspacesOut"; enabled = true; speed = 1; bezier = "easeInOutCubic"; style = "slide"; }
{ leaf = "zoomFactor"; enabled = true; speed = 7; bezier = "quick"; }
];
bind = [
(bind "${mainMod} + R" (dsp ''hl.dsp.exec_cmd("${mreowScript}")''))
(bind "${mainMod} + C" (dsp ''hl.dsp.window.close()''))
(bind "${mainMod} + M" (dsp ''hl.dsp.exec_cmd("uwsm stop")''))
(bind "${mainMod} + Q" (dsp ''hl.dsp.exec_cmd("kitty")''))
(bind "${mainMod} + V" (dsp ''hl.dsp.window.float({ action = "toggle" })''))
(bind "${mainMod} + left" (dsp ''hl.dsp.focus({ direction = "left" })''))
(bind "${mainMod} + right" (dsp ''hl.dsp.focus({ direction = "right" })''))
(bind "${mainMod} + up" (dsp ''hl.dsp.focus({ direction = "up" })''))
(bind "${mainMod} + down" (dsp ''hl.dsp.focus({ direction = "down" })''))
(bind "${mainMod} + L" (dsp ''hl.dsp.exec_cmd("wlogout")''))
(bind "${mainMod} + S" (dsp ''hl.dsp.exec_cmd("wayfreeze --after-freeze-cmd '${meowScript}'")''))
(bind "${mainMod} + F" (dsp ''hl.dsp.window.fullscreen({ action = "toggle" })''))
(bind "${mainMod} + SHIFT + Q" (dsp ''hl.dsp.window.close()''))
(bind "${mainMod} + mouse_down" (dsp ''hl.dsp.focus({ workspace = "e+1" })''))
(bind "${mainMod} + mouse_up" (dsp ''hl.dsp.focus({ workspace = "e-1" })''))
# Mouse binds
(bind "${mainMod} + mouse:272" (dsp ''hl.dsp.window.drag()''))
(bind "${mainMod} + mouse:273" (dsp ''hl.dsp.window.resize()''))
# Media keys
(bind "XF86AudioLowerVolume" (dsp ''hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-")''))
(bind "XF86AudioRaiseVolume" (dsp ''hl.dsp.exec_cmd("wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+")''))
(bind "XF86AudioMute" (dsp ''hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle")''))
(bind "XF86AudioPlay" (dsp ''hl.dsp.exec_cmd("playerctl play-pause")''))
(bind "XF86AudioNext" (dsp ''hl.dsp.exec_cmd("playerctl next")''))
(bind "XF86AudioPrev" (dsp ''hl.dsp.exec_cmd("playerctl previous")''))
(bind "XF86AudioMicMute" (dsp ''hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle")''))
(bind "home" (dsp ''hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle")''))
(bind "end" (dsp ''hl.dsp.exec_cmd("wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle")''))
(bind "F8" (dsp ''hl.dsp.pass({ window = [[match:class:^(com.obsproject.Studio)$]] })''))
# Workspaces
(bind "${mainMod} + 0" (dsp ''hl.dsp.focus({ workspace = 10 })''))
(bind "${mainMod} + SHIFT + 0" (dsp ''hl.dsp.window.move({ workspace = 10 })''))
]
++ wsBinds;
window_rule = [
{ suppress_event = "maximize"; }
{
match.class = "gamescope";
workspace = "5";
immediate = true;
confine_pointer = true;
}
{
match.initial_title = "OBS Studio Crash Detected";
pin = true;
}
# Steam, Discord (equibop), Telegram, Spotify and OBS
# always open on their own workspace regardless of how
# they were launched. These sit before the "Discord
# Popout" rule: window rules apply in declaration order
# and the last match wins, so popouts still land on
# workspace 1.
{
match.class = "steam";
workspace = "6 silent";
}
{
match.class = "equibop";
workspace = "8 silent";
}
{
match.class = "org.telegram.desktop";
workspace = "8 silent";
}
{
match.class = "spotify";
workspace = "9 silent";
}
{
match.class = "com.obsproject.Studio";
workspace = "10 silent";
}
{
match.initial_title = "Discord Popout";
workspace = "1 silent";
}
];
layer_rule = [
{
match.namespace = "notifications";
no_screen_share = true;
}
];
};
# Host-specific overrides: load ~/.config/hypr/hyprland-local.lua
# if present (must be valid Lua). Runs last so a host can override
# anything set above.
extraConfig = ''
local home = os.getenv("HOME")
if home then
local localPath = home .. '/.config/hypr/hyprland-local.lua'
local f = io.open(localPath, 'r')
if f then
f:close()
local chunk, err = loadfile(localPath)
if chunk then chunk() else io.stderr:write('hyprland-local.lua error: ' .. err .. '\n') end
end
end
'';
};
};
};
+3 -9
View File
@@ -42,15 +42,9 @@
];
in
{
wayland.windowManager.hyprland.extraLuaFiles = lib.mkIf settings.default {
"zen-browser-bind.lua" = {
autoLoad = true;
content = ''
-- Zen launcher bind (lua config: settings.bind cannot express dispatchers)
hl.bind("SUPER + E", hl.dsp.exec_cmd("zen"))
'';
};
};
wayland.windowManager.hyprland.settings.bind = lib.mkIf settings.default [
{ _args = [ "SUPER + E" (lib.generators.mkLuaInline ''hl.dsp.exec_cmd("zen")'') ]; }
];
home.packages = [
(pkgs.wrapFirefox
inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.zen-browser-unwrapped