4498e538ea
Note: not the actual initial commit. I swear I will stop repeatedly force pushing to this single commit eventually ok.
447 lines
15 KiB
Nix
447 lines
15 KiB
Nix
{ pkgs, inputs, config, lib, self, osConfig, theme, ... }:
|
|
|
|
let
|
|
cfg = config.my.graphical.wayland.hyprland;
|
|
in {
|
|
options.my.graphical.wayland.hyprland = {
|
|
enable = lib.mkEnableOption null;
|
|
tearing = lib.mkEnableOption null;
|
|
mainMod = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "SUPER";
|
|
};
|
|
lockBinary = lib.mkOption {
|
|
type = lib.types.str;
|
|
};
|
|
wallpaper = {
|
|
enable = lib.mkEnableOption null // {
|
|
default = true;
|
|
};
|
|
backend = lib.mkOption {
|
|
type = lib.types.enum [ "hyprpaper" "swaybg" ];
|
|
default = "swaybg";
|
|
};
|
|
image = lib.mkOption {
|
|
type = lib.types.pathInStore;
|
|
default = "${self}/assets/snowyMountain.jpg";
|
|
};
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable (let
|
|
toggleOption = pkgs.writeShellScriptBin "hypr-toggle-opt" ''
|
|
hyprctl keyword "$1" "$(hyprctl getoption "$1" -j | ${pkgs.jaq}/bin/jaq '1 - .int')"
|
|
'';
|
|
copyOutput = pkgs.writeShellScript "hypr-copy-output" ''
|
|
MONITOR="$(hyprctl monitors -j | ${pkgs.jaq}/bin/jaq -r '.[] | select(.focused).name')"
|
|
grim -o "$MONITOR" - | wl-copy -t image/png
|
|
'';
|
|
copyWindow = pkgs.writeShellScript "hypr-copy-window" ''
|
|
WINDOW="$(hyprctl activewindow -j | ${pkgs.jaq}/bin/jaq -r '.address')"
|
|
grim -w "$WINDOW" - | wl-copy -t image/png
|
|
'';
|
|
winShiftS = with pkgs; writeShellScriptBin "win-shift-s" ''
|
|
FILENAME="/tmp/win-shift-s-$PPID.png"
|
|
MONITOR="$(hyprctl monitors -j | ${_ jaq} -r '.[] | select(.focused)')"
|
|
${_ grim} -o "$(${_ jaq} -r '.name' <<< "$MONITOR")" "$FILENAME"
|
|
${_ imv} -f "$FILENAME" & IMV_PROC=$!
|
|
DIMENSIONS="$(${_ slurp} -f '%wx%h+%X+%Y')"
|
|
[ "$?" -eq 0 ] && \
|
|
${_ imagemagick} "$FILENAME" -crop "$DIMENSIONS" - | \
|
|
${wl-clipboard}/bin/wl-copy -t image/png
|
|
kill $IMV_PROC
|
|
exec rm "$FILENAME"
|
|
'';
|
|
timeWindow = let
|
|
inherit (inputs.cl-hyprland-ipc.packages.${pkgs.system}) cl-hyprland-ipc;
|
|
inherit (cl-hyprland-ipc) asdfFasl faslExt;
|
|
sbclWithPackages = pkgs.sbcl.withPackages (_: [ cl-hyprland-ipc ]);
|
|
in pkgs.runCommand "time-window" { } ''
|
|
${sbclWithPackages}/bin/sbcl --load ${asdfFasl}/asdf.${faslExt} \
|
|
--load ${../../scripts/time-window.lisp} \
|
|
--eval '(setf uiop:*image-entry-point* #'\''\''time-window:main)' \
|
|
--eval '(uiop:dump-image "time-window" :executable t :compression t)'
|
|
mkdir -p $out/bin
|
|
cp time-window $out/bin
|
|
'';
|
|
in {
|
|
home.packages = [
|
|
toggleOption
|
|
timeWindow
|
|
];
|
|
|
|
wayland.windowManager.hyprland = let
|
|
c = builtins.mapAttrs (_: t: "0xFF${t}") theme;
|
|
inherit (cfg) mainMod;
|
|
activeBorder = "${c.peach} ${c.mauve} 45deg";
|
|
transparent = "0x00000000";
|
|
in {
|
|
enable = true;
|
|
package = osConfig.programs.hyprland.package;
|
|
settings = {
|
|
exec-once = lib.optional (!osConfig.my.fs.luks.enable) "${pkgs.writeShellScript "start-hyprland" ''
|
|
[ -n "$GREETD_SOCK" ] && ${pkgs.swaylock-effects}/bin/swaylock ${
|
|
lib.optionalString cfg.wallpaper.enable "-i ${cfg.wallpaper.image}"
|
|
} &
|
|
''}";
|
|
|
|
env = [ ]
|
|
++ lib.optional config.my.graphical.emacs.enable "VISUAL, emacsclient -c";
|
|
|
|
monitor = [
|
|
"eDP-1, preferred, 0x0, 1.33"
|
|
", preferred, auto, 1"
|
|
|
|
# Manually reserved area for bar
|
|
", addreserved, 42, 0, 0, 0"
|
|
];
|
|
|
|
input = {
|
|
kb_layout = "us";
|
|
kb_options = "numpad:mac";
|
|
repeat_delay = 300;
|
|
repeat_rate = 20;
|
|
float_switch_override_focus = 2;
|
|
|
|
touchpad = {
|
|
natural_scroll = true;
|
|
scroll_factor = 0.3;
|
|
};
|
|
};
|
|
|
|
general = {
|
|
layout = "dwindle";
|
|
allow_tearing = cfg.tearing;
|
|
gaps_in = 5;
|
|
gaps_out = 13;
|
|
border_size = 3;
|
|
"col.active_border" = activeBorder;
|
|
"col.inactive_border" = transparent;
|
|
};
|
|
|
|
dwindle = {
|
|
force_split = 2;
|
|
preserve_split = true;
|
|
no_gaps_when_only = 1;
|
|
special_scale_factor = 0.9;
|
|
};
|
|
|
|
decoration = {
|
|
rounding = 11;
|
|
dim_special = 0;
|
|
drop_shadow = false;
|
|
|
|
blur = {
|
|
enabled = false;
|
|
size = 8;
|
|
passes = 2;
|
|
|
|
ignore_opacity = true;
|
|
xray = true;
|
|
|
|
noise = 0;
|
|
contrast = 1;
|
|
brightness = 1;
|
|
};
|
|
};
|
|
|
|
group = {
|
|
"col.border_active" = activeBorder;
|
|
"col.border_inactive" = transparent;
|
|
"col.border_locked_active" = c.red;
|
|
"col.border_locked_inactive" = transparent;
|
|
|
|
groupbar = {
|
|
render_titles = false;
|
|
height = 3;
|
|
"col.active" = c.green;
|
|
"col.inactive" = transparent;
|
|
"col.locked_active" = c.red;
|
|
"col.locked_inactive" = transparent;
|
|
};
|
|
};
|
|
|
|
animations = {
|
|
enabled = true;
|
|
|
|
bezier = [
|
|
"easeInSine, 0.12, 0, 0.39, 0"
|
|
"easeOutSine, 0.61, 1, 0.88, 1"
|
|
];
|
|
|
|
animation = [
|
|
"windowsIn, 1, 3, easeOutSine, slide"
|
|
"windowsOut, 1, 3, easeInSine, slide"
|
|
"windowsMove, 1, 2.5, easeOutSine, slide"
|
|
|
|
"workspaces, 1, 2.5, easeOutSine, slide"
|
|
"specialWorkspace, 1, 6, default, slidevert"
|
|
|
|
"fade, 0"
|
|
];
|
|
};
|
|
|
|
gestures = {
|
|
workspace_swipe = true;
|
|
};
|
|
|
|
binds = {
|
|
allow_workspace_cycles = true;
|
|
};
|
|
|
|
xwayland = {
|
|
use_nearest_neighbor = false;
|
|
force_zero_scaling = true;
|
|
};
|
|
|
|
misc = {
|
|
vrr = 1;
|
|
|
|
disable_hyprland_logo = true;
|
|
disable_splash_rendering = true;
|
|
background_color = c.crust;
|
|
|
|
disable_autoreload = true;
|
|
focus_on_activate = true;
|
|
animate_manual_resizes = false;
|
|
animate_mouse_windowdragging = false;
|
|
new_window_takes_over_fullscreen = 2;
|
|
|
|
enable_swallow = false;
|
|
swallow_regex = "^(foot(client)?|kitty)$";
|
|
};
|
|
|
|
windowrule = [
|
|
"tile, ^(Aseprite)$"
|
|
"fullscreen, ^(Baba Is You|ADanceOfFireAndIce)$"
|
|
"float, ^(EverestSplash-linux)$"
|
|
"float, title:^(emacs-everywhere)$"
|
|
] ++ lib.optional cfg.tearing
|
|
"immediate, ^(ADanceOfFireAndIce|Celeste|hollow_knight\\.x86_64|portal2_linux)$";
|
|
|
|
windowrulev2 = [
|
|
"float, class:^(firefox)$, title:^(Picture-in-Picture)$"
|
|
"pin, class:^(firefox)$, title:^(Picture-in-Picture)$"
|
|
|
|
"tile, class:^(Spotify)$, title:^(?!Ozone X11$).*$"
|
|
"float, class:^(Spotify)$, title:^$"
|
|
];
|
|
|
|
bind = [
|
|
"${mainMod}, Return, exec, foot"
|
|
"${mainMod}, C, killactive,"
|
|
"${mainMod} SHIFT, C, exec, hyprctl activewindow -j | ${pkgs.jaq}/bin/jaq -r '.pid' | xargs kill -9"
|
|
"${mainMod}, E, exec, thunar"
|
|
"${mainMod}, M, exec, emacsclient -c"
|
|
"${mainMod} SHIFT, M, exec, emacsclient -e '(emacs-everywhere)'"
|
|
"${mainMod} SHIFT, Return, togglefloating,"
|
|
|
|
"${mainMod}, Space, fullscreen, 1"
|
|
"${mainMod} SHIFT, Space, fullscreen, 0"
|
|
|
|
"${mainMod}, I, exec, dunstctl action"
|
|
"${mainMod} SHIFT, I, exec, dunstctl context"
|
|
"${mainMod} ALT, I, exec, dunstctl history-pop"
|
|
"${mainMod} CTRL, I, exec, dunstctl close"
|
|
|
|
"${mainMod}, Semicolon, exec, killall fuzzel || fuzzel"
|
|
|
|
"${mainMod}, Y, pin,"
|
|
|
|
# Groups
|
|
"${mainMod}, F, changegroupactive, f"
|
|
"${mainMod} SHIFT, F, togglegroup,"
|
|
"${mainMod} CTRL, F, lockactivegroup, toggle"
|
|
|
|
# Directions
|
|
"${mainMod}, Period, layoutmsg, preselect r"
|
|
"${mainMod}, Comma, layoutmsg, preselect d"
|
|
"${mainMod}, S, layoutmsg, togglesplit"
|
|
|
|
# Moving windows (with groups)
|
|
"${mainMod} SHIFT, left, movewindoworgroup, l"
|
|
"${mainMod} SHIFT, right, movewindoworgroup, r"
|
|
"${mainMod} SHIFT, up, movewindoworgroup, u"
|
|
"${mainMod} SHIFT, down, movewindoworgroup, d"
|
|
"${mainMod} SHIFT, H, movewindoworgroup, l"
|
|
"${mainMod} SHIFT, L, movewindoworgroup, r"
|
|
"${mainMod} SHIFT, K, movewindoworgroup, u"
|
|
"${mainMod} SHIFT, J, movewindoworgroup, d"
|
|
|
|
# Moving windows (without groups)
|
|
"${mainMod} ALT, left, movewindow, l"
|
|
"${mainMod} ALT, right, movewindow, r"
|
|
"${mainMod} ALT, up, movewindow, u"
|
|
"${mainMod} ALT, down, movewindow, d"
|
|
"${mainMod} ALT, H, movewindow, l"
|
|
"${mainMod} ALT, L, movewindow, r"
|
|
"${mainMod} ALT, K, movewindow, u"
|
|
"${mainMod} ALT, J, movewindow, d"
|
|
|
|
# Workspaces
|
|
"${mainMod} CTRL, P, focusworkspaceoncurrentmonitor, previous"
|
|
"${mainMod} CTRL, N, focusworkspaceoncurrentmonitor, empty"
|
|
"${mainMod} CTRL SHIFT, P, movetoworkspace, previous"
|
|
"${mainMod} CTRL SHIFT, N, movetoworkspace, empty"
|
|
|
|
# Screenshot
|
|
", Print, exec, ${copyOutput}"
|
|
"ALT, Print, exec, ${copyWindow}"
|
|
"${mainMod} SHIFT, S, exec, grim -g \"$(slurp)\" - | wl-copy -t image/png"
|
|
|
|
# Move focus
|
|
"${mainMod}, left, movefocus, l"
|
|
"${mainMod}, right, movefocus, r"
|
|
"${mainMod}, up, movefocus, u"
|
|
"${mainMod}, down, movefocus, d"
|
|
"${mainMod}, H, movefocus, l"
|
|
"${mainMod}, L, movefocus, r"
|
|
"${mainMod}, K, movefocus, u"
|
|
"${mainMod}, J, movefocus, d"
|
|
|
|
# Switch workspaces with mainMod + [1-9]
|
|
"${mainMod}, 1, focusworkspaceoncurrentmonitor, 1"
|
|
"${mainMod}, 2, focusworkspaceoncurrentmonitor, 2"
|
|
"${mainMod}, 3, focusworkspaceoncurrentmonitor, 3"
|
|
"${mainMod}, 4, focusworkspaceoncurrentmonitor, 4"
|
|
"${mainMod}, 5, focusworkspaceoncurrentmonitor, 5"
|
|
"${mainMod}, 6, focusworkspaceoncurrentmonitor, 6"
|
|
"${mainMod}, 7, focusworkspaceoncurrentmonitor, 7"
|
|
"${mainMod}, 8, focusworkspaceoncurrentmonitor, 8"
|
|
"${mainMod}, 9, focusworkspaceoncurrentmonitor, 9"
|
|
|
|
# Switch workspaces with mainMod + N/P/O
|
|
"${mainMod}, N, focusworkspaceoncurrentmonitor, e+1"
|
|
"${mainMod}, P, focusworkspaceoncurrentmonitor, e-1"
|
|
"${mainMod} SHIFT, N, movetoworkspace, e+1"
|
|
"${mainMod} SHIFT, P, movetoworkspace, e-1"
|
|
|
|
# Move active window to a workspace with mainMod + SHIFT + [1-9]
|
|
"${mainMod} SHIFT, 1, movetoworkspace, 1"
|
|
"${mainMod} SHIFT, 2, movetoworkspace, 2"
|
|
"${mainMod} SHIFT, 3, movetoworkspace, 3"
|
|
"${mainMod} SHIFT, 4, movetoworkspace, 4"
|
|
"${mainMod} SHIFT, 5, movetoworkspace, 5"
|
|
"${mainMod} SHIFT, 6, movetoworkspace, 6"
|
|
"${mainMod} SHIFT, 7, movetoworkspace, 7"
|
|
"${mainMod} SHIFT, 8, movetoworkspace, 8"
|
|
"${mainMod} SHIFT, 9, movetoworkspace, 9"
|
|
|
|
# Scroll through existing workspaces with mainMod + scroll/side buttons
|
|
"${mainMod}, mouse_down, focusworkspaceoncurrentmonitor, e-1"
|
|
"${mainMod}, mouse_up, focusworkspaceoncurrentmonitor, e+1"
|
|
"${mainMod}, mouse:275, focusworkspaceoncurrentmonitor, e-1"
|
|
"${mainMod}, mouse:276, focusworkspaceoncurrentmonitor, e+1"
|
|
|
|
# Scratchpads
|
|
"${mainMod} SHIFT, 0, movetoworkspace, special:a"
|
|
"${mainMod}, 0, togglespecialworkspace, a"
|
|
"${mainMod} SHIFT, minus, movetoworkspace, special:b"
|
|
"${mainMod}, minus, togglespecialworkspace, b"
|
|
"${mainMod} SHIFT, equal, movetoworkspace, special:c"
|
|
"${mainMod}, equal, togglespecialworkspace, c"
|
|
|
|
"${mainMod}, T, exec, ${toggleOption}/bin/hypr-toggle-opt input:touchpad:disable_while_typing"
|
|
];
|
|
|
|
bindl = [
|
|
"${mainMod}, Q, exec, ${cfg.lockBinary}"
|
|
"${mainMod} ALT, Q, exec, killall ${cfg.lockBinary} .${cfg.lockBinary}-wrapped ; ${cfg.lockBinary}"
|
|
"${mainMod} SHIFT, Q, exit,"
|
|
|
|
", XF86AudioMute, exec, dunst-volume set-mute toggle"
|
|
];
|
|
|
|
binde = [
|
|
# Resize windows
|
|
"${mainMod} CTRL ALT, left, resizeactive, -10 0"
|
|
"${mainMod} CTRL ALT, right, resizeactive, 10 0"
|
|
"${mainMod} CTRL ALT, up, resizeactive, 0 -10"
|
|
"${mainMod} CTRL ALT, down, resizeactive, 0 10"
|
|
"${mainMod} CTRL ALT, H, resizeactive, -10 0"
|
|
"${mainMod} CTRL ALT, L, resizeactive, 10 0"
|
|
"${mainMod} CTRL ALT, K, resizeactive, 0 -10"
|
|
"${mainMod} CTRL ALT, J, resizeactive, 0 10"
|
|
|
|
# Move floating windows
|
|
"${mainMod} CTRL, left, moveactive, -50 0"
|
|
"${mainMod} CTRL, right, moveactive, 50 0"
|
|
"${mainMod} CTRL, up, moveactive, 0 -50"
|
|
"${mainMod} CTRL, down, moveactive, 0 50"
|
|
"${mainMod} CTRL, H, moveactive, -50 0"
|
|
"${mainMod} CTRL, L, moveactive, 50 0"
|
|
"${mainMod} CTRL, K, moveactive, 0 -50"
|
|
"${mainMod} CTRL, J, moveactive, 0 50"
|
|
];
|
|
|
|
bindm = [
|
|
# Move/resize windows with mainMod + LMB/RMB and dragging
|
|
"${mainMod}, mouse:272, movewindow"
|
|
"${mainMod}, mouse:273, resizewindow"
|
|
];
|
|
|
|
bindel = [
|
|
# Media keys
|
|
", XF86AudioRaiseVolume, exec, dunst-volume set-volume 5%+"
|
|
", XF86AudioLowerVolume, exec, dunst-volume set-volume 5%-"
|
|
|
|
", XF86MonBrightnessDown, exec, dunst-brightness 5%+"
|
|
", XF86MonBrightnessUp, exec, dunst-brightness 5%-"
|
|
];
|
|
};
|
|
|
|
extraConfig = ''
|
|
# Passthrough mode
|
|
bind = ${mainMod}, Escape, submap, passthrough
|
|
submap = passthrough
|
|
bind = ${mainMod}, Escape, submap, reset
|
|
submap = reset
|
|
|
|
# OBS
|
|
bind = ${mainMod} CTRL, O, submap, OBS
|
|
submap = OBS
|
|
bind = , Space, pass, ^(com\.obsproject\.Studio)$
|
|
bind = , P, pass, ^(com\.obsproject\.Studio)$
|
|
bind = , Escape, submap, reset
|
|
bind = ${mainMod}, Escape, submap, reset
|
|
submap = reset
|
|
'';
|
|
};
|
|
|
|
systemd.user.services = lib.mkIf cfg.wallpaper.enable {
|
|
hyprpaper = lib.mkIf (cfg.wallpaper.backend == "hyprpaper") {
|
|
Unit = {
|
|
Description = "Background wallpaper image via hyprpaper";
|
|
After = "hyprland-session.target";
|
|
};
|
|
Service = {
|
|
ExecStart = let
|
|
hyprpaperConfig = pkgs.writeText "hyprpaper.conf" ''
|
|
preload = ${cfg.wallpaper.image}
|
|
wallpaper = ,${cfg.wallpaper.image}
|
|
ipc = off
|
|
splash = off
|
|
'';
|
|
in "${pkgs.hyprpaper}/bin/hyprpaper -c ${hyprpaperConfig}";
|
|
};
|
|
Install = {
|
|
WantedBy = [ "hyprland-session.target" ];
|
|
};
|
|
};
|
|
|
|
swaybg = lib.mkIf (cfg.wallpaper.backend == "swaybg") {
|
|
Unit = {
|
|
Description = "Background wallpaper image via swaybg";
|
|
After = "hyprland-session.target";
|
|
};
|
|
Service = {
|
|
ExecStart = "${pkgs.swaybg}/bin/swaybg -i ${cfg.wallpaper.image} -m fill -o '*'";
|
|
};
|
|
Install = {
|
|
WantedBy = [ "hyprland-session.target" ];
|
|
};
|
|
};
|
|
};
|
|
});
|
|
}
|