mirror of
https://github.com/EdenQwQ/nixos.git
synced 2026-02-22 21:05:50 +08:00
init
This commit is contained in:
commit
96895ec3aa
100 changed files with 6349 additions and 0 deletions
231
home/programs/desktop/niri/animations.nix
Normal file
231
home/programs/desktop/niri/animations.nix
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
{
|
||||
programs.niri.settings.animations = {
|
||||
window-open = {
|
||||
spring = {
|
||||
damping-ratio = 0.7;
|
||||
stiffness = 300;
|
||||
epsilon = 0.001;
|
||||
};
|
||||
};
|
||||
window-close = {
|
||||
easing = {
|
||||
curve = "ease-out-quad";
|
||||
duration-ms = 500;
|
||||
};
|
||||
};
|
||||
workspace-switch = {
|
||||
spring = {
|
||||
damping-ratio = 0.8;
|
||||
stiffness = 600;
|
||||
epsilon = 0.001;
|
||||
};
|
||||
};
|
||||
horizontal-view-movement = {
|
||||
spring = {
|
||||
damping-ratio = 1.0;
|
||||
stiffness = 600;
|
||||
epsilon = 0.001;
|
||||
};
|
||||
};
|
||||
window-movement = {
|
||||
spring = {
|
||||
damping-ratio = 1.0;
|
||||
stiffness = 600;
|
||||
epsilon = 0.001;
|
||||
};
|
||||
};
|
||||
shaders = {
|
||||
window-open =
|
||||
# glsl
|
||||
''
|
||||
// Example: fill the current geometry with a solid vertical gradient and
|
||||
// gradually make opaque.
|
||||
vec4 solid_gradient(vec3 coords_geo, vec3 size_geo) {
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
// Paint only the area inside the current geometry.
|
||||
if (0.0 <= coords_geo.x && coords_geo.x <= 1.0
|
||||
&& 0.0 <= coords_geo.y && coords_geo.y <= 1.0)
|
||||
{
|
||||
vec4 from = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
vec4 to = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
color = mix(from, to, coords_geo.y);
|
||||
}
|
||||
|
||||
// Make it opaque.
|
||||
color *= niri_clamped_progress;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Example: gradually scale up and make opaque, equivalent to the default
|
||||
// opening animation.
|
||||
vec4 default_open(vec3 coords_geo, vec3 size_geo) {
|
||||
// Scale up the window.
|
||||
float scale = max(0.0, (niri_progress / 2.0 + 0.5));
|
||||
coords_geo = vec3((coords_geo.xy - vec2(0.5)) / scale + vec2(0.5), 1.0);
|
||||
|
||||
// Get color from the window texture.
|
||||
vec3 coords_tex = niri_geo_to_tex * coords_geo;
|
||||
vec4 color = texture2D(niri_tex, coords_tex.st);
|
||||
|
||||
// Make the window opaque.
|
||||
color *= niri_clamped_progress;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Example: show the window as an expanding circle.
|
||||
// Recommended setting: duration-ms 250
|
||||
vec4 expanding_circle(vec3 coords_geo, vec3 size_geo) {
|
||||
vec3 coords_tex = niri_geo_to_tex * coords_geo;
|
||||
vec4 color = texture2D(niri_tex, coords_tex.st);
|
||||
|
||||
vec2 coords = (coords_geo.xy - vec2(0.5, 0.5)) * size_geo.xy * 2.0;
|
||||
coords = coords / length(size_geo.xy);
|
||||
float p = niri_clamped_progress;
|
||||
if (p * p <= dot(coords, coords))
|
||||
color = vec4(0.0);
|
||||
|
||||
return color * p;
|
||||
}
|
||||
|
||||
// This is the function that you must define.
|
||||
vec4 open_color(vec3 coords_geo, vec3 size_geo) {
|
||||
// You can pick one of the example functions or write your own.
|
||||
return default_open(coords_geo, size_geo);
|
||||
}
|
||||
'';
|
||||
window-resize =
|
||||
# glsl
|
||||
''
|
||||
// Example: fill the current geometry with a solid vertical gradient.
|
||||
vec4 solid_gradient(vec3 coords_curr_geo, vec3 size_curr_geo) {
|
||||
vec3 coords = coords_curr_geo;
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
// Paint only the area inside the current geometry.
|
||||
if (0.0 <= coords.x && coords.x <= 1.0
|
||||
&& 0.0 <= coords.y && coords.y <= 1.0)
|
||||
{
|
||||
vec4 from = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
vec4 to = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
color = mix(from, to, coords.y);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Example: crossfade between previous and next texture, stretched to the
|
||||
// current geometry.
|
||||
vec4 crossfade(vec3 coords_curr_geo, vec3 size_curr_geo) {
|
||||
// Convert coordinates into the texture space for sampling.
|
||||
vec3 coords_tex_prev = niri_geo_to_tex_prev * coords_curr_geo;
|
||||
vec4 color_prev = texture2D(niri_tex_prev, coords_tex_prev.st);
|
||||
|
||||
// Convert coordinates into the texture space for sampling.
|
||||
vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo;
|
||||
vec4 color_next = texture2D(niri_tex_next, coords_tex_next.st);
|
||||
|
||||
vec4 color = mix(color_prev, color_next, niri_clamped_progress);
|
||||
return color;
|
||||
}
|
||||
|
||||
// Example: next texture, stretched to the current geometry.
|
||||
vec4 stretch_next(vec3 coords_curr_geo, vec3 size_curr_geo) {
|
||||
vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo;
|
||||
vec4 color = texture2D(niri_tex_next, coords_tex_next.st);
|
||||
return color;
|
||||
}
|
||||
|
||||
// Example: next texture, stretched to the current geometry if smaller, and
|
||||
// cropped if bigger.
|
||||
vec4 stretch_or_crop_next(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;
|
||||
}
|
||||
|
||||
// Example: cropped next texture if it's bigger than the current geometry, and
|
||||
// crossfade between previous and next texture otherwise.
|
||||
vec4 crossfade_or_crop_next(vec3 coords_curr_geo, vec3 size_curr_geo) {
|
||||
vec3 coords_next_geo = niri_curr_geo_to_next_geo * coords_curr_geo;
|
||||
vec3 coords_prev_geo = niri_curr_geo_to_prev_geo * coords_curr_geo;
|
||||
|
||||
vec3 coords_crop = niri_geo_to_tex_next * coords_next_geo;
|
||||
vec3 coords_stretch = niri_geo_to_tex_next * coords_curr_geo;
|
||||
vec3 coords_stretch_prev = niri_geo_to_tex_prev * coords_curr_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;
|
||||
bool crop = can_crop_by_x && can_crop_by_y;
|
||||
|
||||
vec4 color;
|
||||
|
||||
if (crop) {
|
||||
// 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 crossfading, this is not an issue because the area outside will
|
||||
// correspond to client-side decoration shadows, which are already supposed
|
||||
// to be outside.
|
||||
if (coords_curr_geo.x < 0.0 || 1.0 < coords_curr_geo.x ||
|
||||
coords_curr_geo.y < 0.0 || 1.0 < coords_curr_geo.y) {
|
||||
color = vec4(0.0);
|
||||
} else {
|
||||
color = texture2D(niri_tex_next, coords_crop.st);
|
||||
}
|
||||
} else {
|
||||
// If we can't crop, then crossfade.
|
||||
color = texture2D(niri_tex_next, coords_stretch.st);
|
||||
vec4 color_prev = texture2D(niri_tex_prev, coords_stretch_prev.st);
|
||||
color = mix(color_prev, color, niri_clamped_progress);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// This is the function that you must define.
|
||||
vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) {
|
||||
// You can pick one of the example functions or write your own.
|
||||
return crossfade_or_crop_next(coords_curr_geo, size_curr_geo);
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
158
home/programs/desktop/niri/autostart.nix
Normal file
158
home/programs/desktop/niri/autostart.nix
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
user,
|
||||
...
|
||||
}:
|
||||
let
|
||||
niri-autostart = pkgs.writeShellApplication {
|
||||
name = "niri-autostart";
|
||||
runtimeInputs = with pkgs; [
|
||||
niri-blur-wallpaper
|
||||
swww
|
||||
clash-meta
|
||||
wlsunset
|
||||
];
|
||||
extraShellCheckFlags = [ ];
|
||||
bashOptions = [ ];
|
||||
text =
|
||||
# bash
|
||||
''
|
||||
swww kill
|
||||
swww-daemon &
|
||||
clash-meta -d ~/.config/clash &
|
||||
wlsunset -s 00:00 -S 00:00 -t 5000 -T 5001 &
|
||||
niri-blur-wallpaper &
|
||||
'';
|
||||
};
|
||||
niri-blur-wallpaper = pkgs.writers.writePython3Bin "niri-blur-wallpaper" { doCheck = false; } ''
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
wallpapers_path = "/home/${user}/Pictures/Wallpapers/generated/"
|
||||
wallpapers_cache_path = "/home/${user}/.cache/swww/"
|
||||
events_of_interest = [
|
||||
"Workspace changed",
|
||||
"Workspace focused",
|
||||
"Window opened",
|
||||
"Window closed",
|
||||
]
|
||||
|
||||
|
||||
def get_niri_msg_output(msg):
|
||||
output = subprocess.check_output(["niri", "msg", "-j", msg])
|
||||
output = json.loads(output)
|
||||
return output
|
||||
|
||||
|
||||
def get_current_wallpaper(monitor):
|
||||
with open(os.path.join(wallpapers_cache_path, monitor)) as f:
|
||||
wallpaper = str(f.read())
|
||||
return wallpaper
|
||||
|
||||
|
||||
def set_wallpaper(monitor, wallpaper):
|
||||
subprocess.run(
|
||||
[
|
||||
"swww",
|
||||
"img",
|
||||
"--transition-type",
|
||||
"fade",
|
||||
"--transition-duration",
|
||||
"0.5",
|
||||
"-o",
|
||||
monitor,
|
||||
wallpaper,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def get_wallpaper_name(wallpaper_path):
|
||||
current_wallpaper_is_blurred = "blurred" in wallpaper_path
|
||||
if current_wallpaper_is_blurred:
|
||||
wallpaper_name = "-".join(wallpaper_path.split("-")[1:-1])
|
||||
else:
|
||||
wallpaper_name = "-".join(wallpaper_path.split("-")[1:])
|
||||
wallpaper_name = ".".join(wallpaper_name.split(".")[:-1])
|
||||
return wallpaper_name
|
||||
|
||||
|
||||
def set_wallpaper_if_needed(active_workspace, init):
|
||||
active_workspace_monitor = active_workspace["output"]
|
||||
current_wallpaper = get_current_wallpaper(active_workspace_monitor)
|
||||
current_wallpaper_is_live = current_wallpaper.endswith(".gif")
|
||||
if current_wallpaper_is_live:
|
||||
return
|
||||
wallpaper_name = get_wallpaper_name(current_wallpaper)
|
||||
active_workspace_is_empty = active_workspace["active_window_id"] is None
|
||||
if active_workspace_is_empty:
|
||||
wallpaper = os.path.join(wallpapers_path, f"{wallpaper_name}.jpg")
|
||||
else:
|
||||
wallpaper = os.path.join(wallpapers_path, f"{wallpaper_name}-blurred.jpg")
|
||||
real_wallpaper = os.path.realpath(wallpaper)
|
||||
if current_wallpaper == real_wallpaper and not init:
|
||||
return
|
||||
set_wallpaper(active_workspace_monitor, wallpaper)
|
||||
|
||||
|
||||
def change_wallpaper(init=False):
|
||||
workspaces = get_niri_msg_output("workspaces")
|
||||
active_workspaces = [
|
||||
workspace for workspace in workspaces if workspace["is_active"]
|
||||
]
|
||||
for active_workspace in active_workspaces:
|
||||
set_wallpaper_if_needed(active_workspace, init)
|
||||
|
||||
|
||||
def main():
|
||||
change_wallpaper(init=True)
|
||||
event_stream = subprocess.Popen(
|
||||
["niri", "msg", "event-stream"], stdout=subprocess.PIPE
|
||||
)
|
||||
if not event_stream.stdout:
|
||||
return
|
||||
for line in iter(event_stream.stdout.readline, ""):
|
||||
if any(event in line.decode() for event in events_of_interest):
|
||||
change_wallpaper()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
'';
|
||||
in
|
||||
{
|
||||
systemd.user.services.niri-blur-wallpaper = {
|
||||
Unit = {
|
||||
Description = "Niri Blur Wallpaper";
|
||||
BindsTo = [ "graphical-session.target" ];
|
||||
Before = [ "graphical-session.target" ];
|
||||
Wants = [ "graphical-session-pre.target" ];
|
||||
After = [ "graphical-session-pre.target" ];
|
||||
};
|
||||
Install = {
|
||||
WantedBy = [ "graphical-session.target" ];
|
||||
Wants = [ "xdg-desktop-autostart.target" ];
|
||||
After = [ "xdg-desktop-autostart.target" ];
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = "${niri-blur-wallpaper}/bin/niri-blur-wallpaper";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
};
|
||||
};
|
||||
home.activation.restart-niri-blur-wallpaper =
|
||||
lib.hm.dag.entryAfter [ "reload-waybar" ]
|
||||
# bash
|
||||
''run --quiet ${pkgs.systemd}/bin/systemctl --user restart niri-blur-wallpaper'';
|
||||
programs.niri.settings.spawn-at-startup = [
|
||||
{ command = [ "${niri-autostart}/bin/niri-autostart" ]; }
|
||||
{
|
||||
command = [
|
||||
"fcitx5"
|
||||
"-d"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
117
home/programs/desktop/niri/binds.nix
Normal file
117
home/programs/desktop/niri/binds.nix
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
{ config, user, ... }:
|
||||
{
|
||||
programs.niri.settings.binds = with config.lib.niri.actions; {
|
||||
"Mod+Return".action = spawn "kitty";
|
||||
"Mod+X".action = spawn "/home/${user}/scripts/tofi/powermenu";
|
||||
"Mod+Shift+C".action = spawn "/home/${user}/scripts/tofi/colorscheme";
|
||||
"Mod+P".action = spawn "sh" "-c" "$(tofi-run)";
|
||||
"Mod+Shift+P".action = spawn "tofi-drun" "--drun-launch=true";
|
||||
"Mod+Shift+W".action = spawn "/home/${user}/scripts/change-wal-niri";
|
||||
"Mod+B".action = spawn "pkill" "-USR1" ".waybar-wrapped";
|
||||
"Mod+Q".action = close-window;
|
||||
"Mod+E".action = expand-column-to-available-width;
|
||||
"Mod+ALt+C".action = spawn "wl-color-picker";
|
||||
"Mod+N".action =
|
||||
spawn "wayneko" "--layer" "top" "--follow-pointer" "true" "--survive-close" "--background-colour"
|
||||
"0x${config.lib.stylix.colors.base0E}dd"
|
||||
"--outline-colour"
|
||||
"0x${config.lib.stylix.colors.base01}dd";
|
||||
|
||||
"Mod+Shift+Slash".action = show-hotkey-overlay;
|
||||
"Mod+T".action = toggle-column-tabbed-display;
|
||||
|
||||
"XF86AudioMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle";
|
||||
"XF86AudioMicMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle";
|
||||
"XF86AudioRaiseVolume".action = spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+";
|
||||
"XF86AudioLowerVolume".action = spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-";
|
||||
|
||||
"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+H".action = focus-column-or-monitor-left;
|
||||
"Mod+J".action = focus-window-or-workspace-down;
|
||||
"Mod+K".action = focus-window-or-workspace-up;
|
||||
"Mod+L".action = focus-column-or-monitor-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+Shift+H".action = move-column-left-or-to-monitor-left;
|
||||
"Mod+Shift+J".action = move-window-down-or-to-workspace-down;
|
||||
"Mod+Shift+K".action = move-window-up-or-to-workspace-up;
|
||||
"Mod+Shift+L".action = move-column-right-or-to-monitor-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+Ctrl+H".action = focus-monitor-left;
|
||||
"Mod+Ctrl+J".action = focus-monitor-down;
|
||||
"Mod+Ctrl+K".action = focus-monitor-up;
|
||||
"Mod+Ctrl+L".action = focus-monitor-right;
|
||||
|
||||
"Mod+Shift+Ctrl+Left".action = move-window-to-monitor-left;
|
||||
"Mod+Shift+Ctrl+Down".action = move-window-to-monitor-down;
|
||||
"Mod+Shift+Ctrl+Up".action = move-window-to-monitor-up;
|
||||
"Mod+Shift+Ctrl+Right".action = move-window-to-monitor-right;
|
||||
"Mod+Shift+Ctrl+H".action = move-window-to-monitor-left;
|
||||
"Mod+Shift+Ctrl+J".action = move-window-to-monitor-down;
|
||||
"Mod+Shift+Ctrl+K".action = move-window-to-monitor-up;
|
||||
"Mod+Shift+Ctrl+L".action = move-window-to-monitor-right;
|
||||
|
||||
"Mod+Shift+Space".action = toggle-window-floating;
|
||||
"Mod+Space".action = switch-focus-between-floating-and-tiling;
|
||||
|
||||
"Mod+TouchpadScrollDown" = {
|
||||
action = focus-workspace-down;
|
||||
cooldown-ms = 150;
|
||||
};
|
||||
"Mod+TouchpadScrollUp" = {
|
||||
action = focus-workspace-up;
|
||||
cooldown-ms = 150;
|
||||
};
|
||||
|
||||
"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+Ctrl+1".action = move-window-to-workspace 1;
|
||||
"Mod+Ctrl+2".action = move-window-to-workspace 2;
|
||||
"Mod+Ctrl+3".action = move-window-to-workspace 3;
|
||||
"Mod+Ctrl+4".action = move-window-to-workspace 4;
|
||||
"Mod+Ctrl+5".action = move-window-to-workspace 5;
|
||||
"Mod+Ctrl+6".action = move-window-to-workspace 6;
|
||||
"Mod+Ctrl+7".action = move-window-to-workspace 7;
|
||||
"Mod+Ctrl+8".action = move-window-to-workspace 8;
|
||||
"Mod+Ctrl+9".action = move-window-to-workspace 9;
|
||||
|
||||
"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-left;
|
||||
|
||||
"Mod+R".action = switch-preset-column-width;
|
||||
"Mod+Shift+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;
|
||||
"Ctrl+Print".action = screenshot-screen;
|
||||
"Alt+Print".action = screenshot-window;
|
||||
|
||||
"Mod+Shift+E".action = quit;
|
||||
};
|
||||
}
|
||||
169
home/programs/desktop/niri/default.nix
Normal file
169
home/programs/desktop/niri/default.nix
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./binds.nix
|
||||
./animations.nix
|
||||
./waybar.nix
|
||||
./autostart.nix
|
||||
./override-config.nix
|
||||
];
|
||||
|
||||
programs.niri = {
|
||||
# home.file.".config/niri/config.kdl".source = ./config.kdl;
|
||||
enable = true;
|
||||
package = pkgs.niri-unstable;
|
||||
settings =
|
||||
with config.lib.stylix.colors.withHashtag;
|
||||
let
|
||||
shadowConfig = {
|
||||
enable = true;
|
||||
spread = 0;
|
||||
softness = 10;
|
||||
color = "#000000dd";
|
||||
};
|
||||
in
|
||||
{
|
||||
hotkey-overlay.skip-at-startup = true;
|
||||
prefer-no-csd = true;
|
||||
input = {
|
||||
focus-follows-mouse.enable = true;
|
||||
touchpad.natural-scroll = false;
|
||||
keyboard.xkb.options = "caps:escape";
|
||||
};
|
||||
outputs = builtins.mapAttrs (name: value: {
|
||||
inherit (value) scale mode position;
|
||||
transform.rotation = value.rotation;
|
||||
background-color = base01;
|
||||
}) config.monitors;
|
||||
window-rules = [
|
||||
{
|
||||
geometry-corner-radius = {
|
||||
bottom-left = 10.0;
|
||||
bottom-right = 10.0;
|
||||
top-left = 10.0;
|
||||
top-right = 10.0;
|
||||
};
|
||||
clip-to-geometry = true;
|
||||
draw-border-with-background = false;
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ app-id = "yad"; }
|
||||
];
|
||||
open-floating = true;
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ app-id = "firefox"; }
|
||||
{ app-id = "org.qutebrowser.qutebrowser"; }
|
||||
{ app-id = "kitty"; }
|
||||
{ app-id = "evince"; }
|
||||
{ app-id = "zathura"; }
|
||||
];
|
||||
default-column-width = {
|
||||
proportion = 1.0;
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ is-focused = true; }
|
||||
];
|
||||
opacity = 0.95;
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ is-focused = false; }
|
||||
];
|
||||
opacity = 0.85;
|
||||
}
|
||||
];
|
||||
layer-rules = [
|
||||
{
|
||||
matches = [ { namespace = "launcher"; } ];
|
||||
geometry-corner-radius = {
|
||||
bottom-left = 15.0;
|
||||
bottom-right = 15.0;
|
||||
top-left = 15.0;
|
||||
top-right = 15.0;
|
||||
};
|
||||
shadow = shadowConfig;
|
||||
}
|
||||
];
|
||||
gestures = {
|
||||
dnd-edge-view-scroll = {
|
||||
trigger-width = 60;
|
||||
delay-ms = 100;
|
||||
max-speed = 1500;
|
||||
};
|
||||
};
|
||||
workspaces = {
|
||||
"1" = {
|
||||
open-on-output = config.mainMonitorName;
|
||||
name = "coding";
|
||||
};
|
||||
"2" = {
|
||||
open-on-output = config.mainMonitorName;
|
||||
name = "browsing";
|
||||
};
|
||||
"3" = {
|
||||
open-on-output = builtins.head config.otherMonitorsNames;
|
||||
name = "reading";
|
||||
};
|
||||
"4" = {
|
||||
open-on-output = config.mainMonitorName;
|
||||
name = "music";
|
||||
};
|
||||
};
|
||||
layout = {
|
||||
gaps = 12;
|
||||
border = {
|
||||
enable = true;
|
||||
width = 4;
|
||||
active = {
|
||||
gradient = {
|
||||
from = base07;
|
||||
to = base0E;
|
||||
angle = 45;
|
||||
in' = "oklab";
|
||||
# relative-to = "workspace-view";
|
||||
};
|
||||
};
|
||||
# inactive.color = "#585b70";
|
||||
inactive.color = base02;
|
||||
};
|
||||
focus-ring.enable = false;
|
||||
struts = {
|
||||
left = 2;
|
||||
right = 2;
|
||||
top = 0;
|
||||
bottom = 2;
|
||||
};
|
||||
insert-hint = {
|
||||
enable = true;
|
||||
display = {
|
||||
gradient = {
|
||||
# from = "#f9e2af";
|
||||
from = base0A;
|
||||
# to = "#eba0ac";
|
||||
to = base09;
|
||||
angle = 45;
|
||||
};
|
||||
};
|
||||
};
|
||||
shadow = shadowConfig;
|
||||
tab-indicator = {
|
||||
hide-when-single-tab = true;
|
||||
gap = 5;
|
||||
width = 6;
|
||||
length.total-proportion = 0.5;
|
||||
position = "right";
|
||||
gaps-between-tabs = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
48
home/programs/desktop/niri/override-config.nix
Normal file
48
home/programs/desktop/niri/override-config.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
# tabIndicatorConfig = # kdl
|
||||
# ''
|
||||
# tab-indicator {
|
||||
# hide-when-single-tab
|
||||
# gap 5
|
||||
# width 6
|
||||
# length total-proportion=0.5
|
||||
# position "right"
|
||||
# gaps-between-tabs 2
|
||||
# }
|
||||
# '';
|
||||
# shadowConfig =
|
||||
# # kdl
|
||||
# ''
|
||||
# shadow {
|
||||
# on
|
||||
# spread 0
|
||||
# softness 10
|
||||
# color "#000000dd"
|
||||
# }
|
||||
# '';
|
||||
# tabBinds = # kdl
|
||||
# ''
|
||||
# Mod+T { toggle-column-tabbed-display; }
|
||||
# '';
|
||||
extraConfig =
|
||||
# kdl
|
||||
'''';
|
||||
finalNiriConfig =
|
||||
# builtins.replaceStrings
|
||||
# [ "layout {" ]
|
||||
# [
|
||||
# ("layout {\n" + shadowConfig + "\n" + tabIndicatorConfig)
|
||||
# ]
|
||||
# (config.programs.niri.finalConfig + "\n" + extraConfig)
|
||||
# |>
|
||||
# builtins.replaceStrings
|
||||
# [ "binds {" ]
|
||||
# [
|
||||
# ("binds {\n" + tabBinds)
|
||||
# ];
|
||||
config.programs.niri.finalConfig + "\n" + extraConfig;
|
||||
in
|
||||
{
|
||||
home.file.".config/niri/config-override.kdl".text = finalNiriConfig;
|
||||
}
|
||||
420
home/programs/desktop/niri/waybar.nix
Normal file
420
home/programs/desktop/niri/waybar.nix
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
moduleConfiguration =
|
||||
# jsonc
|
||||
''
|
||||
// Modules configuration
|
||||
"niri/workspaces": {
|
||||
"format": "{icon}",
|
||||
"format-icons": {
|
||||
// "coding": " ",
|
||||
// "browsing": " ",
|
||||
// "reading": "",
|
||||
// "default": " ",
|
||||
// "default": " ",
|
||||
// "active": " "
|
||||
"default": ""
|
||||
},
|
||||
},
|
||||
"niri/window": {
|
||||
"format": "{}",
|
||||
"separate-outputs": true,
|
||||
"icon": true,
|
||||
"icon-size": 18
|
||||
},
|
||||
"memory": {
|
||||
"interval": 30,
|
||||
"format": "<span foreground='#${config.lib.stylix.colors.base0E}'> </span> {used:0.1f}G/{total:0.1f}G",
|
||||
"on-click": "kitty --class=htop,htop -e htop"
|
||||
},
|
||||
"backlight": {
|
||||
"device": "intel_backlight",
|
||||
"on-scroll-up": "light -A 1",
|
||||
"on-scroll-down": "light -U 1",
|
||||
"format": "<span size='13000' foreground='#${config.lib.stylix.colors.base0D}'>{icon} </span> {percent}%",
|
||||
"format-icons": [
|
||||
"",
|
||||
""
|
||||
]
|
||||
},
|
||||
"tray": {
|
||||
"icon-size": 16,
|
||||
"spacing": 10
|
||||
},
|
||||
"clock": {
|
||||
"format": "<span foreground='#${config.lib.stylix.colors.base0E}'> </span> {:%a %d %H:%M}",
|
||||
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>",
|
||||
"on-click": "kitty --class=clock,clock --title=clock -o remember_window_size=no -o initial_window_width=600 -o initial_window_height=200 -e tty-clock -s -c -C 5"
|
||||
},
|
||||
"battery": {
|
||||
"states": {
|
||||
"warning": 30,
|
||||
"critical": 15,
|
||||
},
|
||||
"format": "<span size='13000' foreground='#${config.lib.stylix.colors.base0E}'>{icon} </span>{capacity}%",
|
||||
"format-warning": "<span size='13000' foreground='#${config.lib.stylix.colors.base0E}'>{icon} </span>{capacity}%",
|
||||
"format-critical": "<span size='13000' foreground='#${config.lib.stylix.colors.base08}'>{icon} </span>{capacity}%",
|
||||
"format-charging": "<span size='13000' foreground='#${config.lib.stylix.colors.base0E}'> </span>{capacity}%",
|
||||
"format-plugged": "<span size='13000' foreground='#${config.lib.stylix.colors.base0E}'> </span>{capacity}%",
|
||||
"format-alt": "<span size='13000' foreground='#${config.lib.stylix.colors.base0E}'>{icon} </span>{time}",
|
||||
"format-full": "<span size='13000' foreground='#${config.lib.stylix.colors.base0E}'> </span>{capacity}%",
|
||||
"format-icons": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"tooltip-format": "{time}",
|
||||
"interval": 5
|
||||
},
|
||||
"network": {
|
||||
"format-wifi": "<span size='13000' foreground='#${config.lib.stylix.colors.base06}'> </span>{essid}",
|
||||
"format-ethernet": "<span size='13000' foreground='#${config.lib.stylix.colors.base06}'></span> Disconnected",
|
||||
"format-linked": "{ifname} (No IP) ",
|
||||
"format-disconnected": "<span size='13000' foreground='#${config.lib.stylix.colors.base06}'> </span>Disconnected",
|
||||
"tooltip-format-wifi": "Signal Strenght: {signalStrength}%",
|
||||
"on-click": "kitty --class nmtui,nmtui --title=nmtui -o remember_window_size=no -o initial_window_width=400 -o initial_window_height=400 -e doas nmtui"
|
||||
},
|
||||
"pulseaudio": {
|
||||
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
|
||||
"on-scroll-up": "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.01+",
|
||||
"on-scroll-down": "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.01-",
|
||||
"format": "<span size='13000' foreground='#${config.lib.stylix.colors.base0A}'>{icon} </span>{volume}%",
|
||||
"format-muted": "<span size='13000' foreground='#${config.lib.stylix.colors.base0A}'> </span>Muted",
|
||||
"format-icons": {
|
||||
"headphone": "",
|
||||
"hands-free": "",
|
||||
"headset": "",
|
||||
"phone": "",
|
||||
"portable": "",
|
||||
"car": "",
|
||||
"default": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
}
|
||||
},
|
||||
"group/meters": {
|
||||
"orientation": "inherit",
|
||||
"drawer": {
|
||||
"transition-duration": 500,
|
||||
"transition-left-to-right": false,
|
||||
},
|
||||
"modules": [
|
||||
"battery",
|
||||
"memory",
|
||||
"network",
|
||||
"pulseaudio",
|
||||
"backlight"
|
||||
]
|
||||
}
|
||||
'';
|
||||
trayBackgroundColor = if config.stylix.polarity == "dark" then "@base00" else "@base05";
|
||||
colors = {
|
||||
inherit (config.lib.stylix.colors.withHashtag)
|
||||
base00
|
||||
base01
|
||||
base04
|
||||
base05
|
||||
base06
|
||||
base07
|
||||
base08
|
||||
base0A
|
||||
base0D
|
||||
base0E
|
||||
base0F
|
||||
;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [ ../../../../lib/monitors.nix ];
|
||||
|
||||
programs.waybar = {
|
||||
enable = true;
|
||||
systemd = {
|
||||
enable = true;
|
||||
target = config.wayland.systemd.target;
|
||||
};
|
||||
};
|
||||
home.file = {
|
||||
".config/waybar/config.jsonc".text =
|
||||
let
|
||||
otherMonitorsConfig =
|
||||
map (
|
||||
name:
|
||||
# json
|
||||
''
|
||||
{
|
||||
"position": "top",
|
||||
"layer": "top",
|
||||
"output": "${name}",
|
||||
"modules-left": [
|
||||
"niri/workspaces",
|
||||
"niri/window"
|
||||
],
|
||||
"modules-right": [
|
||||
"tray",
|
||||
"group/meters"
|
||||
],
|
||||
${moduleConfiguration}
|
||||
},
|
||||
'') config.otherMonitorsNames
|
||||
|> builtins.concatStringsSep "\n";
|
||||
in
|
||||
# json
|
||||
''
|
||||
[
|
||||
${otherMonitorsConfig}
|
||||
{
|
||||
"position": "top",
|
||||
"layer": "top",
|
||||
"output": "${config.mainMonitorName}",
|
||||
"modules-left": [
|
||||
"niri/workspaces",
|
||||
"tray",
|
||||
"niri/window"
|
||||
],
|
||||
"modules-center": [
|
||||
"clock",
|
||||
"memory"
|
||||
],
|
||||
"modules-right": [
|
||||
"network",
|
||||
"pulseaudio",
|
||||
"backlight",
|
||||
"battery",
|
||||
],
|
||||
${moduleConfiguration}
|
||||
}
|
||||
]
|
||||
|
||||
'';
|
||||
".config/waybar/colors.css".text =
|
||||
# css
|
||||
(builtins.mapAttrs (name: value: "@define-color ${name} ${value};") colors)
|
||||
|> builtins.attrValues
|
||||
|> builtins.concatStringsSep "\n";
|
||||
".config/waybar/tray.css".text =
|
||||
# css
|
||||
''
|
||||
#tray {
|
||||
background: shade(alpha(${trayBackgroundColor}, 0.9), 1);
|
||||
}
|
||||
'';
|
||||
".config/waybar/style.css".text =
|
||||
# css
|
||||
''
|
||||
@import "animation.css";
|
||||
@import "colors.css";
|
||||
@import "tray.css";
|
||||
|
||||
* {
|
||||
/* all: unset; */
|
||||
font-size: 14px;
|
||||
/* font-family: "Comic Mono Nerd Font"; */
|
||||
font-family: "Hug Me Tight", "Xiaolai SC";
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
/* border-radius: 15px; */
|
||||
/* color: @base04; */
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
tooltip {
|
||||
background: @base01;
|
||||
border-radius: 5px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: @base07;
|
||||
}
|
||||
|
||||
#network,
|
||||
#clock,
|
||||
#battery,
|
||||
#pulseaudio,
|
||||
#workspaces,
|
||||
#backlight,
|
||||
#memory,
|
||||
#tray,
|
||||
#window {
|
||||
padding: 4px 10px;
|
||||
background: shade(alpha(@base00, 0.9), 1);
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.377);
|
||||
color: @base05;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
box-shadow: 1px 2px 2px #101010;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#workspaces {
|
||||
margin-left: 15px;
|
||||
font-size: 0px;
|
||||
padding: 6px 3px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
font-size: 0px;
|
||||
background-color: @base07;
|
||||
padding: 0px 1px;
|
||||
margin: 0px 4px;
|
||||
border-radius: 20px;
|
||||
transition: all 0.25s cubic-bezier(0.55, -0.68, 0.48, 1.682);
|
||||
}
|
||||
|
||||
#workspaces button.active {
|
||||
font-size: 1px;
|
||||
background-color: @base0E;
|
||||
border-radius: 20px;
|
||||
min-width: 30px;
|
||||
background-size: 400% 400%;
|
||||
}
|
||||
|
||||
#workspaces button.empty {
|
||||
font-size: 1px;
|
||||
background-color: @base04;
|
||||
}
|
||||
|
||||
#window {
|
||||
color: @base00;
|
||||
background: radial-gradient(circle, @base05 0%, @base07 100%);
|
||||
background-size: 400% 400%;
|
||||
animation: gradient_f 40s ease-in-out infinite;
|
||||
transition: all 0.3s cubic-bezier(0.55, -0.68, 0.48, 1.682);
|
||||
}
|
||||
|
||||
window#waybar.empty #window {
|
||||
background: none;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#battery {
|
||||
margin-right: 15px;
|
||||
background: @base0F;
|
||||
/* background: linear-gradient(118deg, @base07 0%, @base0F 25%, @base07 50%, @base0F 75%, @base07 100%); */
|
||||
/* background: linear-gradient(118deg, @base07 5%, @base0F 5%, @base0F 20%, @base07 20%, @base07 40%, @base0F 40%, @base0F 60%, @base07 60%, @base07 80%, @base0F 80%, @base0F 95%, @base07 95%); */
|
||||
background: linear-gradient(
|
||||
118deg,
|
||||
@base0B 5%,
|
||||
@base0F 5%,
|
||||
@base0F 20%,
|
||||
@base0B 20%,
|
||||
@base0B 40%,
|
||||
@base0F 40%,
|
||||
@base0F 60%,
|
||||
@base0B 60%,
|
||||
@base0B 80%,
|
||||
@base0F 80%,
|
||||
@base0F 95%,
|
||||
@base0B 95%
|
||||
);
|
||||
background-size: 200% 300%;
|
||||
animation: gradient_f_nh 4s linear infinite;
|
||||
color: @base01;
|
||||
}
|
||||
|
||||
#battery.charging,
|
||||
#battery.plugged {
|
||||
background: linear-gradient(
|
||||
118deg,
|
||||
@base0E 5%,
|
||||
@base0D 5%,
|
||||
@base0D 20%,
|
||||
@base0E 20%,
|
||||
@base0E 40%,
|
||||
@base0D 40%,
|
||||
@base0D 60%,
|
||||
@base0E 60%,
|
||||
@base0E 80%,
|
||||
@base0D 80%,
|
||||
@base0D 95%,
|
||||
@base0E 95%
|
||||
);
|
||||
background-size: 200% 300%;
|
||||
animation: gradient_rv 4s linear infinite;
|
||||
}
|
||||
|
||||
#battery.full {
|
||||
background: linear-gradient(
|
||||
118deg,
|
||||
@base0E 5%,
|
||||
@base0D 5%,
|
||||
@base0D 20%,
|
||||
@base0E 20%,
|
||||
@base0E 40%,
|
||||
@base0D 40%,
|
||||
@base0D 60%,
|
||||
@base0E 60%,
|
||||
@base0E 80%,
|
||||
@base0D 80%,
|
||||
@base0D 95%,
|
||||
@base0E 95%
|
||||
);
|
||||
background-size: 200% 300%;
|
||||
animation: gradient_rv 20s linear infinite;
|
||||
}
|
||||
|
||||
#tray > .passive {
|
||||
-gtk-icon-effect: dim;
|
||||
}
|
||||
|
||||
#tray > .needs-attention {
|
||||
-gtk-icon-effect: highlight;
|
||||
}
|
||||
'';
|
||||
".config/waybar/animation.css".text =
|
||||
# css
|
||||
''
|
||||
@keyframes gradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 30%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradient_f {
|
||||
0% {
|
||||
background-position: 0% 200%;
|
||||
}
|
||||
50% {
|
||||
background-position: 200% 0%;
|
||||
}
|
||||
100% {
|
||||
background-position: 400% 200%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradient_f_nh {
|
||||
0% {
|
||||
background-position: 0% 200%;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% 200%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradient_rv {
|
||||
0% {
|
||||
background-position: 200% 200%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 200%;
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue