364 lines
15 KiB
Nix
364 lines
15 KiB
Nix
{ modules, ... }:
|
|
{
|
|
modules.hyprland = {
|
|
provides = {
|
|
doloro-settings = {
|
|
includes = [
|
|
modules.dunst
|
|
];
|
|
homeManager =
|
|
{
|
|
pkgs,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
tofiCfg = pkgs.writeTextFile {
|
|
name = "hyprland-tofi-config";
|
|
text = ''
|
|
width = 100%
|
|
height = 100%
|
|
border-width = 0
|
|
outline-width = 0
|
|
padding-left = 35%
|
|
padding-top = 35%
|
|
result-spacing = 25
|
|
num-results = 5
|
|
font = monospace
|
|
background-color = #000A
|
|
'';
|
|
};
|
|
meowScript = pkgs.writeShellScript "meow" ''
|
|
fish -c 'grim -g $(slurp) -t png - &| wl-copy -t image/png; killall wayfreeze'
|
|
'';
|
|
mreowScript = pkgs.writeShellScript "mreow" ''
|
|
exec $(tofi-drun -c ${tofiCfg})
|
|
'';
|
|
|
|
mainMod = "SUPER";
|
|
|
|
# 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
|
|
[
|
|
(bind "${mainMod} + ${ws}" (dsp ''hl.dsp.focus({ workspace = ${ws} })''))
|
|
(bind "${mainMod} + SHIFT + ${ws}" (dsp ''hl.dsp.window.move({ workspace = ${ws} })''))
|
|
]
|
|
) 9
|
|
);
|
|
in
|
|
{
|
|
home.packages = [
|
|
pkgs.hyprcursor
|
|
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";
|
|
package = pkgs.rose-pine-hyprcursor;
|
|
hyprcursor.enable = true;
|
|
};
|
|
services.hyprpaper = {
|
|
enable = true;
|
|
settings = {
|
|
splash = true;
|
|
wallpaper = [
|
|
{
|
|
monitor = "HDMI-A-1";
|
|
path = "/home/doloro/Wallpaper.jpg";
|
|
}
|
|
{
|
|
monitor = "DP-2";
|
|
path = "/home/doloro/Wallpaper.jpg";
|
|
}
|
|
];
|
|
};
|
|
};
|
|
# 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
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|