new wm, hyprland gone

This commit is contained in:
Reid 2025-05-18 23:05:26 -07:00
parent 003f37bfbd
commit cb4b22b4e5
Signed by: reidlab
GPG key ID: DAF5EAF6665839FD
41 changed files with 1145 additions and 1364 deletions

421
modules/desktop/niri.nix Normal file
View file

@ -0,0 +1,421 @@
{ inputs, lib, config, system, pkgs, ... }:
with lib;
let
cfg = config.modules.desktop.niri;
in {
options.modules.desktop.niri = {
enable = mkEnableOption "Enable niri, a scrolling wayland compositor";
package = mkOption {
type = types.package;
default = pkgs.niri-unstable;
example = "pkgs.niri";
};
};
config = mkIf cfg.enable {
services.displayManager.sessionPackages = [ cfg.package ];
programs.niri = {
enable = true;
package = cfg.package;
};
systemd.user.services.niri-flake-polkit.enable = false; # niri-flake has its own polkit agent, disable it
hm.programs.niri = {
package = cfg.package;
settings = let
allCorners = r: { bottom-left = r; bottom-right = r; top-left = r; top-right = r; };
in {
input = {
power-key-handling.enable = false;
focus-follows-mouse.enable = true;
focus-follows-mouse.max-scroll-amount = "0%";
# TODO: uhm?? why do i have to do this here. should be automatic from libinput
# whatever. ill just hardcode for now
touchpad = {
click-method = "button-areas";
tap = true;
natural-scroll = true;
};
mouse = {
accel-profile = "flat";
};
};
clipboard = {
disable-primary = true;
};
cursor = {
theme = config.modules.desktop.themes.cursorTheme.name;
size = config.modules.desktop.themes.cursorTheme.size;
};
environment = {
DISPLAY = ":0";
};
prefer-no-csd = true;
layout = {
gaps = 6;
center-focused-column = "on-overflow";
focus-ring = {
enable = false;
width = 1;
active.color = config.modules.desktop.themes.niri.accent;
inactive.color = config.modules.desktop.themes.niri.inactive;
};
border = {
enable = true;
width = 1;
active.color = config.modules.desktop.themes.niri.accent;
inactive.color = config.modules.desktop.themes.niri.inactive;
};
shadow = {
enable = true;
# TODO: remove this?
# this is a way to make the shadow appear on rounded corners
# see: https://github.com/YaLTeR/niri/blob/e251ca7340bc71870c3a81a7ffc3d9bde58e685a/resources/default-config.kdl#L201
draw-behind-window = true;
offset.x = 0;
offset.y = 0;
softness = 30;
spread = 2;
color = config.modules.desktop.themes.niri.shadow;
};
};
hotkey-overlay.skip-at-startup = true;
screenshot-path = null;
animations = {
shaders.window-resize = ''
vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) {
vec3 coords_next_geo = niri_curr_geo_to_next_geo * coords_curr_geo;
vec3 coords_stretch = niri_geo_to_tex_next * coords_curr_geo;
vec3 coords_crop = niri_geo_to_tex_next * coords_next_geo;
// We can crop if the current window size is smaller than the next window
// size. One way to tell is by comparing to 1.0 the X and Y scaling
// coefficients in the current-to-next transformation matrix.
bool can_crop_by_x = niri_curr_geo_to_next_geo[0][0] <= 1.0;
bool can_crop_by_y = niri_curr_geo_to_next_geo[1][1] <= 1.0;
vec3 coords = coords_stretch;
if (can_crop_by_x)
coords.x = coords_crop.x;
if (can_crop_by_y)
coords.y = coords_crop.y;
vec4 color = texture2D(niri_tex_next, coords.st);
// However, when we crop, we also want to crop out anything outside the
// current geometry. This is because the area of the shader is unspecified
// and usually bigger than the current geometry, so if we don't fill pixels
// outside with transparency, the texture will leak out.
//
// When stretching, this is not an issue because the area outside will
// correspond to client-side decoration shadows, which are already supposed
// to be outside.
if (can_crop_by_x && (coords_curr_geo.x < 0.0 || 1.0 < coords_curr_geo.x))
color = vec4(0.0);
if (can_crop_by_y && (coords_curr_geo.y < 0.0 || 1.0 < coords_curr_geo.y))
color = vec4(0.0);
return color;
}
'';
window-close = {
easing = {
curve = "linear";
duration-ms = 600;
};
};
shaders.window-close = ''
vec4 fall_and_rotate(vec3 coords_geo, vec3 size_geo) {
float progress = niri_clamped_progress * niri_clamped_progress;
vec2 coords = (coords_geo.xy - vec2(0.5, 1.0)) * size_geo.xy;
coords.y -= progress * 1440.0;
float random = (niri_random_seed - 0.5) / 2.0;
random = sign(random) - random;
float max_angle = 0.5 * random;
float angle = progress * max_angle;
mat2 rotate = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
coords = rotate * coords;
coords_geo = vec3(coords / size_geo.xy + vec2(0.5, 1.0), 1.0);
vec3 coords_tex = niri_geo_to_tex * coords_geo;
vec4 color = texture2D(niri_tex, coords_tex.st);
return color;
}
vec4 close_color(vec3 coords_geo, vec3 size_geo) {
return fall_and_rotate(coords_geo, size_geo);
}
'';
};
window-rules = [
{
geometry-corner-radius = allCorners 10.0;
clip-to-geometry = true;
}
{
matches = [
{ app-id = "^org\.wezfurlong\.wezterm$"; }
];
# see earlier shadow config; this is here because it's a transparent window, special case
shadow.draw-behind-window = false;
}
{
matches = [
{ app-id = "^gcr-prompter$"; }
{ app-id = "^.*pinentry-.*$"; }
{ app-id = "^polkit-.*$"; }
{ app-id = "^org.gnome.seahorse.Application$"; }
];
block-out-from = "screen-capture";
}
{
matches = [
{ app-id = "^gcr-prompter$"; }
{ app-id = "^.*pinentry-.*$"; }
{ app-id = "^polkit-.*$"; }
{ app-id = "^org\.gnome\.Loupe$"; }
{ title = "^Open Folder$"; }
{ title = "^Open Files$"; }
{ title = "^Open File$"; }
{ title = "^Open$"; }
{ title = "^Save$"; }
{ title = "^Save As$"; }
];
open-floating = true;
focus-ring = {
enable = true;
width = 4000;
active.color = "${config.modules.desktop.themes.niri.shadow}65";
inactive.color = "${config.modules.desktop.themes.niri.shadow}65";
};
}
{
matches = [
{ app-id = "firefox$"; title = "^Picture-in-Picture$"; }
{ title = "^Picture in picture$"; }
{ title = "^Discord Popout$"; }
];
open-floating = true;
default-floating-position = {
x = 15;
y = 15;
relative-to = "top-right";
};
}
{
matches = [
{ app-id = "^gcr-prompter$"; }
{ app-id = "^.*pinentry-.*$"; }
{ app-id = "^polkit-.*$"; }
{ app-id = "^file-roller$"; }
{ app-id = "^org\.gnome\.FileRoller$"; }
{ app-id = "^org\.gnome\.Loupe$"; }
{ title = "^Open Folder$"; }
{ title = "^Open Files$"; }
{ title = "^Open File$"; }
{ title = "^Open$"; }
{ title = "^Save$"; }
{ title = "^Save As$"; }
];
open-floating = true;
default-column-width.proportion = 0.6;
default-window-height.proportion = 0.8;
}
];
layer-rules = [
{
matches = [
{ namespace = "^notifications$"; }
{ namespace = "^rofi$"; } # a bit silly, but we use rofi for clipboard history
];
block-out-from = "screencast";
}
{
matches = [
{ namespace = "^launcher$"; }
{ namespace = "^notifications$"; }
{ namespace = "^rofi$"; }
{ namespace = "^waybar$"; }
{ namespace = "^wob$"; }
];
shadow = {
enable = true;
};
}
{
matches = [
{ namespace = "^launcher$"; }
{ namespace = "^wob$"; }
];
# see earlier shadow config; this is here because it's a transparent window, special case
shadow.draw-behind-window = false;
}
];
binds = with config.hm.lib.niri.actions; let
sh = spawn "sh" "-c";
in {
"Mod+Shift+Slash".action = show-hotkey-overlay;
"Mod+D".action = spawn "fuzzel";
"Mod+Q".action = close-window;
"Mod+H".action = toggle-window-floating;
"Mod+Shift+H".action = switch-focus-between-floating-and-tiling;
"Mod+Left".action = focus-column-left;
"Mod+Down".action = focus-window-down;
"Mod+Up".action = focus-window-up;
"Mod+Right".action = focus-column-right;
"Mod+Shift+Left".action = move-column-left;
"Mod+Shift+Down".action = move-window-down;
"Mod+Shift+Up".action = move-window-up;
"Mod+Shift+Right".action = move-column-right;
"Mod+Ctrl+Left".action = focus-monitor-left;
"Mod+Ctrl+Down".action = focus-monitor-down;
"Mod+Ctrl+Up".action = focus-monitor-up;
"Mod+Ctrl+Right".action = focus-monitor-right;
"Mod+Home".action = focus-column-first;
"Mod+End".action = focus-column-last;
"Mod+Shift+Home".action = move-column-to-first;
"Mod+Shift+End".action = move-column-to-last;
"Mod+Page_Down".action = focus-workspace-down;
"Mod+Page_Up".action = focus-workspace-up;
"Mod+Shift+Page_Down".action = move-column-to-workspace-down;
"Mod+Shift+Page_Up".action = move-column-to-workspace-up;
"Mod+Ctrl+Page_Down".action = move-workspace-down;
"Mod+Ctrl+Page_Up".action = move-workspace-up;
"Mod+1".action = focus-workspace 1;
"Mod+2".action = focus-workspace 2;
"Mod+3".action = focus-workspace 3;
"Mod+4".action = focus-workspace 4;
"Mod+5".action = focus-workspace 5;
"Mod+6".action = focus-workspace 6;
"Mod+7".action = focus-workspace 7;
"Mod+8".action = focus-workspace 8;
"Mod+9".action = focus-workspace 9;
"Mod+0".action = focus-workspace 10;
"Mod+Shift+1".action = move-column-to-workspace 1;
"Mod+Shift+2".action = move-column-to-workspace 2;
"Mod+Shift+3".action = move-column-to-workspace 3;
"Mod+Shift+4".action = move-column-to-workspace 4;
"Mod+Shift+5".action = move-column-to-workspace 5;
"Mod+Shift+6".action = move-column-to-workspace 6;
"Mod+Shift+7".action = move-column-to-workspace 7;
"Mod+Shift+8".action = move-column-to-workspace 8;
"Mod+Shift+9".action = move-column-to-workspace 9;
"Mod+Shift+0".action = move-column-to-workspace 10;
"Mod+Comma".action = consume-window-into-column;
"Mod+Period".action = expel-window-from-column;
"Mod+BracketLeft".action = consume-or-expel-window-left;
"Mod+BracketRight".action = consume-or-expel-window-right;
"Mod+R".action = switch-preset-column-width;
"Mod+Shift+R".action = switch-preset-window-height;
"Mod+Ctrl+R".action = reset-window-height;
"Mod+F".action = maximize-column;
"Mod+Shift+F".action = fullscreen-window;
"Mod+C".action = center-column;
"Mod+Minus".action = set-column-width "-10%";
"Mod+Equal".action = set-column-width "+10%";
"Mod+Shift+Minus".action = set-window-height "-10%";
"Mod+Shift+Equal".action = set-window-height "+10%";
"Print".action = screenshot;
"Mod+Shift+E".action = quit;
"XF86AudioMicMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle";
"XF86AudioMicMute".allow-when-locked = true;
"XF86LaunchA".action = screenshot;
"XF86LaunchB".action = sh "${lib.getExe pkgs.rofi-rbw-wayland} -a copy -t password --clear-after 20";
"XF86ScreenSaver".action = sh "${pkgs.systemd}/bin/loginctl lock-session";
# substitutions for when not on laptop
"Mod+Shift+S".action = screenshot;
"Mod+Shift+P".action = sh "${lib.getExe pkgs.rofi-rbw-wayland} -a copy -t password --clear-after 20";
"Mod+L".action = sh "${pkgs.systemd}/bin/loginctl lock-session";
"Mod+T".action = spawn "wezterm";
"Mod+E".action = spawn "nautilus";
"XF86AudioPrev".action = sh "${lib.getExe pkgs.playerctl} previous";
"XF86AudioPlay".action = sh "${lib.getExe pkgs.playerctl} play-pause";
"XF86AudioNext".action = sh "${lib.getExe pkgs.playerctl} next";
"Mod+V".action = sh "${config.modules.desktop.cliphist.summonScript}";
"Mod+Shift+Control+T".action = toggle-debug-tint;
"Mod+Shift+Control+O".action = debug-toggle-opaque-regions;
"Mod+Shift+Control+D".action = debug-toggle-damage;
} // (if config.modules.desktop.wob.enable then let
wobSock = config.modules.desktop.wob.sockPath;
in {
"XF86AudioRaiseVolume".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+ && wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/[^0-9]//g' > ${wobSock}";
"XF86AudioRaiseVolume".allow-when-locked = true;
"XF86AudioLowerVolume".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%- && wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/[^0-9]//g' > ${wobSock}";
"XF86AudioLowerVolume".allow-when-locked = true;
"XF86AudioMute".action = sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle && (wpctl get-volume @DEFAULT_AUDIO_SINK@ | grep -q MUTED && echo 0 > ${wobSock}) || wpctl get-volume @DEFAULT_AUDIO_SINK@ | sed 's/[^0-9]//g' > ${wobSock}";
"XF86AudioMute".allow-when-locked = true;
"XF86MonBrightnessUp".action = sh "${lib.getExe pkgs.brightnessctl} -c backlight s +5% | sed -n 's/.*(\\([0-9]*\\)%).*/\\1/p' > ${wobSock}";
"XF86MonBrightnessUp".allow-when-locked = true;
"XF86MonBrightnessDown".action = sh "${lib.getExe pkgs.brightnessctl} -c backlight s 5%- | sed -n 's/.*(\\([0-9]*\\)%).*/\\1/p' > ${wobSock}";
"XF86MonBrightnessDown".allow-when-locked = true;
"XF86KbdBrightnessUp".action = sh "${lib.getExe pkgs.brightnessctl} -d '*:kbd_backlight' s +5% | sed -n 's/.*(\\([0-9]*\\)%).*/\\1/p' > ${wobSock}";
"XF86KbdBrightnessUp".allow-when-locked = true;
"XF86KbdBrightnessDown".action = sh "${lib.getExe pkgs.brightnessctl} -d '*:kbd_backlight' s 5%- | sed -n 's/.*(\\([0-9]*\\)%).*/\\1/p' > ${wobSock}";
"XF86KbdBrightnessDown".allow-when-locked = true;
} else {
"XF86AudioRaiseVolume".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+";
"XF86AudioRaiseVolume".allow-when-locked = true;
"XF86AudioLowerVolume".action = sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-";
"XF86AudioLowerVolume".allow-when-locked = true;
"XF86AudioMute".action = sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
"XF86AudioMute".allow-when-locked = true;
"XF86MonBrightnessUp".action = sh "${lib.getExe pkgs.brightnessctl} -c backlight s +5%";
"XF86MonBrightnessUp".allow-when-locked = true;
"XF86MonBrightnessDown".action = sh "${lib.getExe pkgs.brightnessctl} -c backlight s 5%-";
"XF86MonBrightnessDown".allow-when-locked = true;
"XF86KbdBrightnessUp".action = sh "${lib.getExe pkgs.brightnessctl} -d '*:kbd_backlight' s +5%";
"XF86KbdBrightnessUp".allow-when-locked = true;
"XF86KbdBrightnessDown".action = sh "${lib.getExe pkgs.brightnessctl} -d '*:kbd_backlight' s 5%-";
"XF86KbdBrightnessDown".allow-when-locked = true;
});
};
};
};
}