LW7EMVOBZAG5K4QXAKPM46IV2U2U7EWKFKY4S3AR2SJESHJ7YJ3AC
2AA2CTPIDRVJ4TRA5UK2IS4W6EKSIB3UBZWXPOVLX4FMJLSBOLPAC
U6GSJX5ZG4O7R3XO4CA7G62TTDE22HRZ2LL7EQKLQSYCHCAA3CQQC
QF7VMCPGQIVJI2CPGJOEWS3ROVCB2CB7STNZ4N55UHMGWOZAHJIAC
T4B2IJ4JIWX4C4QJI2S5TQHBO4U4ZFCIWR2VNIH6MGAOPMIAVHAQC
SBZM65IDAB2EJ5AN6MGG5CYEDIEEKUODGUONIPAH3MN6AJC7DTSAC
A5LLNGHQYNL2EOXRIAH4VR6AGBEYYKX4AMWYXS4T2SKS2EKZK3VAC
M42H5HLDPW5VN6H7PAXZQ5QILN4ZOCVIKZVCWZ5T26VEW4UZRN7AC
47GPXWYAN5HMMVVIWFEAY63MID4U2UHIBH4HNMDYWNQ2J6E2WX6AC
{
config,
lib,
...
}: let
cfg = config.dotfiles.gui.hyprland;
# makes strings like "title:<pattern>" or "window-id"
mkPattern = {
pattern,
field,
sep,
}: "${field}${sep}${pattern}";
# makes simple title matches like "title:^.*<pattern>.*$"
titleContains = titlePattern:
mkPattern {
pattern = "^.*${titlePattern}.*$";
field = "title";
sep = ":";
};
classIs = name:
if builtins.stringLength name > 0
then "${mkPattern {
pattern = "^.*${name}.*$";
field = "class";
sep = ":";
}},"
else "";
# puts the above together producing a list of rules for each pattern
# e.g. if you wanted to apply nodim and noblur to windows with YouTube in the title
# or if they're a firefox Picture-in-Picture window
# [
# ["nodim,title:^.*YouTube.*$", "noblur,title:^.*YouTube.*$"]
# ["nodim,title:^.*Picture-in-Picture.*$",class:(firefox), "noblur,title:^.*Picture-in-Picture.*$",class:(firefox)]
# ]
mkRules = patterns: rules: (map (rule: (map (pattern: "${rule},${pattern}")) patterns) rules);
floatWindows = {
titles,
class ? "",
}:
mkRules (map (title: "${classIs class}${titleContains title}") (lib.lists.toList titles)) ["float"];
noDimWindowsTitled = {
titles,
class ? "",
}:
mkRules (map (title: "${classIs class}${titleContains title}") (lib.lists.toList titles)) ["nodim" "noblur"];
in {
config = lib.mkIf cfg.enable {
# https://wiki.hyprland.org/Configuring/Window-Rules/#rules
# these end up
wayland.windowManager.hyprland.settings.windowrulev2 = lib.lists.flatten [
(floatWindows {
# these won't auto-float unless it's the initial class
# https://github.com/hyprwm/Hyprland/issues/2687
titles = "Picture-in-Picture";
class = "firefox";
})
(noDimWindowsTitled {titles = ["YouTube" "Picture-in-Picture"];})
];
};
}
bind = $mainMod, Q, killactive,
bind = $mainMod + SHIFT, Q, exit,
bind = $mainMod + SHIFT, F, togglefloating,
bind = $mainMod, F, fullscreen,
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
# Move focus with mainMod + arrow keys
bind = $mainMod, h, movefocus, l
bind = $mainMod, j, movefocus, r
bind = $mainMod, k, movefocus, u
bind = $mainMod, l, movefocus, d
# Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
toggleDisplayWithLid = let
name = "disable-builtin-display-when-lid-closed";
script = pkgs.writeShellApplication {
inherit name;
runtimeInputs = [pkgs.coreutils];
text = ''
if grep open /proc/acpi/button/lid/LID0/state; then
hyprctl keyword monitor "eDP-1,preferred,auto,auto"
else
if [[ "$(hyprctl monitors | grep -c Monitor)" != "1" ]]; then
hyprctl keyword monitor "eDP-1,disable"
fi
fi
'';
};
in "${script}/bin/${name}";
in [
"$mainMod, T, exec, ${term}"
"$mainMod, R, exec, ${pkgs.wofi}/bin/wofi --show drun"
withSuper = with lib.strings;
lst: (map (rule:
if (hasPrefix "+" rule)
then "$mainMod ${rule}"
else "$mainMod, ${rule}")
lst);
in
withSuper [
# primary actions
"T, exec, ${term}"
"Q, killactive,"
"+SHIFT, Q, exit,"
"+SHIFT, F, togglefloating,"
"F, fullscreen,"
# "P, pseudo,"
# "J, togglesplit,"
"P, togglefloating"
"P, pin"
"SPACE, exec, ${pkgs.wofi}/bin/wofi --show drun"
# movement between windows
"h, movefocus, l"
"j, movefocus, d"
"k, movefocus, u"
"l, movefocus, r"
# Move active window to a workspace with mainMod + SHIFT + [0-9]
"+SHIFT, 1, movetoworkspace, 1"
"+SHIFT, 2, movetoworkspace, 2"
"+SHIFT, 3, movetoworkspace, 3"
"+SHIFT, 4, movetoworkspace, 4"
"+SHIFT, 5, movetoworkspace, 5"
"+SHIFT, 6, movetoworkspace, 6"
"+SHIFT, 7, movetoworkspace, 7"
"+SHIFT, 8, movetoworkspace, 8"
"+SHIFT, 9, movetoworkspace, 9"
"+SHIFT, 0, movetoworkspace, 10"
# change to workspace by number
"1, workspace, 1"
"2, workspace, 2"
"3, workspace, 3"
"4, workspace, 4"
"5, workspace, 5"
"6, workspace, 6"
"7, workspace, 7"
"8, workspace, 8"
"9, workspace, 9"
"0, workspace, 10"
# Scroll through existing workspaces with mainMod + scroll
"mouse_down, workspace, e+1"
"mouse_up, workspace, e-1"
# Move window to scratch pad
"+SHIFT, $dashKey, movetoworkspacesilent, special:scratchpad"
"$dashKey, togglespecialworkspace, scratchpad"
];
bindl = [
",switch:Lid Switch, exec, ${toggleDisplayWithLid}"
];
bindm = [
# Move/resize windows with mainMod + LMB/RMB and dragging
"$mainMod, mouse:272, movewindow"
"$mainMod, mouse:273, resizewindow"