diff --git a/home/.chezmoiignore.tmpl b/home/.chezmoiignore.tmpl index 36781b6..8052f49 100644 --- a/home/.chezmoiignore.tmpl +++ b/home/.chezmoiignore.tmpl @@ -61,6 +61,7 @@ vim:ft=gotmpl .config/bat .config/krunnerrc .config/fcitx5 + .config/niri .local/share/** {{ end }} @@ -136,4 +137,5 @@ vim:ft=gotmpl {{/* Secret Management */}} {{ if not .manageSecret }} .config/aichat + .config/pdf2zh {{ end }} diff --git a/nixcfgs/flake.lock b/nixcfgs/flake.lock index 5bfa77d..d53c1a0 100644 --- a/nixcfgs/flake.lock +++ b/nixcfgs/flake.lock @@ -105,6 +105,62 @@ "type": "github" } }, + "niri-flake": { + "inputs": { + "niri-stable": "niri-stable", + "niri-unstable": "niri-unstable", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable", + "xwayland-satellite-stable": "xwayland-satellite-stable", + "xwayland-satellite-unstable": "xwayland-satellite-unstable" + }, + "locked": { + "lastModified": 1762540449, + "narHash": "sha256-AZ/xrJ5JXvpRQYyiVf8Hx4lzFBQAaH9l0utOfvAA28I=", + "owner": "sodiboo", + "repo": "niri-flake", + "rev": "75bacb66302bca38fa6e0c180f1e5369a8115454", + "type": "github" + }, + "original": { + "owner": "sodiboo", + "repo": "niri-flake", + "type": "github" + } + }, + "niri-stable": { + "flake": false, + "locked": { + "lastModified": 1756556321, + "narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=", + "owner": "YaLTeR", + "repo": "niri", + "rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294", + "type": "github" + }, + "original": { + "owner": "YaLTeR", + "ref": "v25.08", + "repo": "niri", + "type": "github" + } + }, + "niri-unstable": { + "flake": false, + "locked": { + "lastModified": 1762492604, + "narHash": "sha256-cjXYF5+gGaapr6d1Jz70GZQVzK4qzwDUwU86p9+H2mM=", + "owner": "YaLTeR", + "repo": "niri", + "rev": "2144f9a6ae7b675213f9bd86d0989c334baa1c00", + "type": "github" + }, + "original": { + "owner": "YaLTeR", + "repo": "niri", + "type": "github" + } + }, "nix-darwin": { "inputs": { "nixpkgs": [ @@ -143,21 +199,37 @@ }, "nixpkgs": { "locked": { - "lastModified": 1761880412, - "narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=", + "lastModified": 1762363567, + "narHash": "sha256-YRqMDEtSMbitIMj+JLpheSz0pwEr0Rmy5mC7myl17xs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386", + "rev": "ae814fd3904b621d8ab97418f1d0f2eb0d3716f4", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-stable": { + "locked": { + "lastModified": 1762498405, + "narHash": "sha256-Zg/SCgCaAioc0/SVZQJxuECGPJy+OAeBcGeA5okdYDc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6faeb062ee4cf4f105989d490831713cc5a43ee1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { "locked": { "lastModified": 1761999846, "narHash": "sha256-IYlYnp4O4dzEpL77BD/lj5NnJy2J8qbHkNSFiPBCbqo=", @@ -174,6 +246,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1761880412, + "narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1761907660, "narHash": "sha256-kJ8lIZsiPOmbkJypG+B5sReDXSD1KGu2VEPNqhRa/ew=", @@ -192,7 +280,7 @@ "nur": { "inputs": { "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_3" }, "locked": { "lastModified": 1762155241, @@ -257,10 +345,11 @@ "caelestia-shell": "caelestia-shell", "flake-utils": "flake-utils", "home-manager": "home-manager", + "niri-flake": "niri-flake", "nix-darwin": "nix-darwin", "nix-flatpak": "nix-flatpak", - "nixpkgs": "nixpkgs", - "nixpkgs-stable": "nixpkgs-stable", + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable_2", "nur": "nur", "plasma-manager": "plasma-manager", "sops-nix": "sops-nix" @@ -300,6 +389,39 @@ "repo": "default", "type": "github" } + }, + "xwayland-satellite-stable": { + "flake": false, + "locked": { + "lastModified": 1755491097, + "narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=", + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "rev": "388d291e82ffbc73be18169d39470f340707edaa", + "type": "github" + }, + "original": { + "owner": "Supreeeme", + "ref": "v0.7", + "repo": "xwayland-satellite", + "type": "github" + } + }, + "xwayland-satellite-unstable": { + "flake": false, + "locked": { + "lastModified": 1762488100, + "narHash": "sha256-pD8YqwP0/irHWzJtVElnVljR+OaJPAVbJBwqix+uB5A=", + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "rev": "3cd3edffe1be197326e9314816b16bb4e3d685b1", + "type": "github" + }, + "original": { + "owner": "Supreeeme", + "repo": "xwayland-satellite", + "type": "github" + } } }, "root": "root", diff --git a/nixcfgs/flake.nix b/nixcfgs/flake.nix index 047c9f4..f4b03e0 100644 --- a/nixcfgs/flake.nix +++ b/nixcfgs/flake.nix @@ -29,6 +29,7 @@ url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + niri-flake.url = "github:sodiboo/niri-flake"; }; outputs = { @@ -42,6 +43,7 @@ nur, caelestia-shell, sops-nix, + niri-flake, ... } @ inputs: let overlays = [ @@ -102,6 +104,7 @@ plasma-manager.homeModules.plasma-manager nix-flatpak.homeManagerModules.nix-flatpak sops-nix.homeManagerModules.sops + niri-flake.homeModules.niri ]; }; "js0ny@nixvirt" = home-manager.lib.homeManagerConfiguration { diff --git a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri.nix b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri.nix index 26d96fb..ab5a932 100644 --- a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri.nix +++ b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/niri.nix @@ -2,33 +2,262 @@ config, pkgs, ... -}: { +}: let + term = config.currentUser.defaultTerminal; + termRunner = config.currentUser.defaultTerminalRunner; + iconTheme = config.currentUser.iconTheme; + explorer = config.currentUser.defaultExplorer; + explorerTerm = config.currentUser.defaultTerminalExplorer; + launcher = "rofi"; +in { imports = [ ./packages.nix ]; - home.file."${config.xdg.configHome}/niri/config.kdl" = { - text = '' - spawn-at-startup "waybar" // Status Bar - spawn-at-startup "dunst" // Notifications - spawn-at-startup "fcitx5" // Input Method - spawn-at-startup "${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent" - screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" - prefer-no-csd // client-side decorations (window decorations) + programs.niri = { + enable = true; + package = pkgs.niri; - input { - keyboard { - xkb {} - numlock + settings = { + prefer-no-csd = true; + screenshot-path = "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"; + + spawn-at-startup = [ + {argv = ["waybar"];} + {argv = ["dunst"];} + {argv = ["fcitx5"];} + # polkit/portal helpers + {argv = ["${pkgs.kdePackages.xdg-desktop-portal-kde}/libexec/xdg-desktop-portal-kde"];} + {argv = ["${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent"];} + ]; + + input = { + keyboard = { + xkb = {}; + numlock = true; + }; + + touchpad = { + tap = true; + natural-scroll = true; + }; + + mouse = {}; + trackpoint = {}; + }; + + layout = { + gaps = 16; + center-focused-column = "never"; + + preset-column-widths = [ + {proportion = 0.33333;} + {proportion = 0.5;} + {proportion = 0.66667;} + ]; + + default-column-width = {proportion = 0.5;}; + + focus-ring = { + enable = true; + width = 4; + active.color = "#7fc8ff"; + inactive.color = "#505050"; + }; + + border = { + enable = false; + width = 4; + active.color = "#ffc87f"; + inactive.color = "#505050"; + urgent.color = "#9b0000"; + }; + + shadow = { + enable = false; + softness = 30; + spread = 5; + offset = { + x = 0; + y = 5; + }; + color = "#0007"; + }; + }; + + window-rules = [ + { + matches = [ + { + app-id = "firefox$"; + title = "^Picture-in-Picture$"; + } + ]; + open-floating = true; } - touchpad { - tap - naturalscroll - } - mouse {} - trackpoint {} - } - ''; - enable = false; # TODO: + ]; + + binds = with config.lib.niri.actions; { + "Mod+Shift+Slash".action = show-hotkey-overlay; + + "Mod+Return".hotkey-overlay.title = "Open a Terminal: ${term}"; + "Mod+Return".action = spawn "${term}"; + + "Mod+D".hotkey-overlay.title = "Run an Application: rofi"; + "Mod+D".action = + spawn "${launcher}" "-show" "drun" "-icon-theme" "${iconTheme}" "-show-icons"; + + "Alt+Space".hotkey-overlay.title = "Run an Application: rofi"; + "Alt+Space".action = + spawn "${launcher}" "-show" "drun" "-icon-theme" "${iconTheme}" "-show-icons"; + + "Mod+Shift+W".hotkey-overlay.title = "Search open Window: rofi"; + "Mod+Shift+W".action = + spawn "${launcher}" "-show" "window" "-icon-theme" "${iconTheme}" "-show-icons"; + + "Mod+E".hotkey-overlay.title = "Run file explorer"; + "Mod+E".action = spawn "${explorer}"; + "Mod+Shift+E".hotkey-overlay.title = "Run terminal explorer"; + "Mod+Shift+E".action = spawn "${termRunner}" "${explorerTerm}"; + + "XF86AudioRaiseVolume".allow-when-locked = true; + "XF86AudioRaiseVolume".action = + spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; + "XF86AudioLowerVolume".allow-when-locked = true; + "XF86AudioLowerVolume".action = + spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; + "XF86AudioMute".allow-when-locked = true; + "XF86AudioMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; + "XF86AudioMicMute".allow-when-locked = true; + "XF86AudioMicMute".action = spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; + + "Mod+Tab".action = toggle-overview; + "Mod+Q".action = close-window; + + "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-left; + "Mod+J".action = focus-window-down; + "Mod+K".action = focus-window-up; + "Mod+L".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+Shift+H".action = move-column-left; + "Mod+Shift+J".action = move-window-down; + "Mod+Shift+K".action = move-window-up; + "Mod+Shift+L".action = move-column-right; + + "Mod+Home".action = focus-column-first; + "Mod+End".action = focus-column-last; + "Mod+Ctrl+Home".action = move-column-to-first; + "Mod+Ctrl+End".action = move-column-to-last; + + "Mod+Alt+Left".action = focus-monitor-left; + "Mod+Alt+Down".action = focus-monitor-down; + "Mod+Alt+Up".action = focus-monitor-up; + "Mod+Alt+Right".action = focus-monitor-right; + "Mod+Alt+H".action = focus-monitor-left; + "Mod+Alt+J".action = focus-monitor-down; + "Mod+Alt+K".action = focus-monitor-up; + "Mod+Alt+L".action = focus-monitor-right; + + "Mod+Shift+Ctrl+Left".action = move-column-to-monitor-left; + "Mod+Shift+Ctrl+Down".action = move-column-to-monitor-down; + "Mod+Shift+Ctrl+Up".action = move-column-to-monitor-up; + "Mod+Shift+Ctrl+Right".action = move-column-to-monitor-right; + "Mod+Shift+Ctrl+H".action = move-column-to-monitor-left; + "Mod+Shift+Ctrl+J".action = move-column-to-monitor-down; + "Mod+Shift+Ctrl+K".action = move-column-to-monitor-up; + "Mod+Shift+Ctrl+L".action = move-column-to-monitor-right; + + "Mod+Page_Down".action = focus-workspace-down; + "Mod+Page_Up".action = focus-workspace-up; + "Mod+U".action = focus-workspace-down; + "Mod+I".action = focus-workspace-up; + "Mod+Ctrl+Page_Down".action = move-column-to-workspace-down; + "Mod+Ctrl+Page_Up".action = move-column-to-workspace-up; + "Mod+Ctrl+U".action = move-column-to-workspace-down; + "Mod+Ctrl+I".action = move-column-to-workspace-up; + + "Mod+Shift+Page_Down".action = move-workspace-down; + "Mod+Shift+Page_Up".action = move-workspace-up; + "Mod+Shift+U".action = move-workspace-down; + "Mod+Shift+I".action = move-workspace-up; + + "Mod+WheelScrollDown".cooldown-ms = 150; + "Mod+WheelScrollDown".action = focus-workspace-down; + "Mod+WheelScrollUp".cooldown-ms = 150; + "Mod+WheelScrollUp".action = focus-workspace-up; + "Mod+Ctrl+WheelScrollDown".cooldown-ms = 150; + "Mod+Ctrl+WheelScrollDown".action = move-column-to-workspace-down; + "Mod+Ctrl+WheelScrollUp".cooldown-ms = 150; + "Mod+Ctrl+WheelScrollUp".action = move-column-to-workspace-up; + + "Mod+WheelScrollRight".action = focus-column-right; + "Mod+WheelScrollLeft".action = focus-column-left; + "Mod+Ctrl+WheelScrollRight".action = move-column-right; + "Mod+Ctrl+WheelScrollLeft".action = move-column-left; + + "Mod+Shift+WheelScrollDown".action = focus-column-right; + "Mod+Shift+WheelScrollUp".action = focus-column-left; + "Mod+Ctrl+Shift+WheelScrollDown".action = move-column-right; + "Mod+Ctrl+Shift+WheelScrollUp".action = move-column-left; + + "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+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+BracketLeft".action = consume-or-expel-window-left; + "Mod+BracketRight".action = consume-or-expel-window-right; + "Mod+Comma".action = consume-window-into-column; + "Mod+Period".action = expel-window-from-column; + + "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+M".action = fullscreen-window; + "Mod+Ctrl+F".action = expand-column-to-available-width; + "Mod+C".action = center-column; + "Mod+Ctrl+C".action = center-visible-columns; + "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%"; + "Mod+V".action = toggle-window-floating; + "Mod+Shift+V".action = switch-focus-between-floating-and-tiling; + "Mod+W".action = toggle-column-tabbed-display; + + "Mod+Shift+S".action.screenshot = {show-pointer = true;}; + "Print".action.screenshot = {show-pointer = true;}; + # "Ctrl+Print".action.screenshot-screen = {true}; + "Alt+Print".action.screenshot-window = {write-to-disk = true;}; + + "Mod+Escape".allow-inhibiting = false; + "Mod+Escape".action = toggle-keyboard-shortcuts-inhibit; + + "Ctrl+Alt+Delete".action = quit; + }; + }; }; } diff --git a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/packages.nix b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/packages.nix index 5f26780..efb906d 100644 --- a/nixcfgs/users/js0ny/programs/desktop/wayland-wm/packages.nix +++ b/nixcfgs/users/js0ny/programs/desktop/wayland-wm/packages.nix @@ -1,4 +1,11 @@ -{pkgs, ...}: { +{pkgs, ...}: let + swayidleWrapper = pkgs.writeShellScriptBin "swayidle-wrapper" '' + ${pkgs.swayidle}/bin/swayidle -w \ + timeout 300 'swaylock -f' \ + timeout 600 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \ + before-sleep 'swaylock -f -c 000000' + ''; +in { imports = [ ../../rofi.nix ./waybar.nix @@ -6,9 +13,13 @@ home.packages = with pkgs; [ swayidle # Screensaver dunst # Notification daemon - swaylock-effects # Screensaver cliphist # Clipboard daemon swww # Wallpaper daemon wmname + swayidleWrapper ]; + programs.swaylock = { + enable = true; + package = pkgs.swaylock-effects; + }; } diff --git a/nixcfgs/users/js0ny/programs/pdf2zh.nix b/nixcfgs/users/js0ny/programs/pdf2zh.nix index df224fb..75dd442 100644 --- a/nixcfgs/users/js0ny/programs/pdf2zh.nix +++ b/nixcfgs/users/js0ny/programs/pdf2zh.nix @@ -7,6 +7,10 @@ IMAGE_TAG="${imageTag}" + OPENROUTER_API_KEY="$OPENROUTER_API_KEY" + OPENROUTER_API_BASE="https://openrouter.ai/api/v1" + OPENROUTER_DEFAULT_MODEL="google/gemini-2.5-flash" + if ! podman image exists "$IMAGE_TAG"; then echo "[pdf2zh] Pulling image $IMAGE_TAG ..." podman pull "$IMAGE_TAG" @@ -16,7 +20,7 @@ -p 7860:7860 \ -v "$(pwd):/data" \ -w /data \ - "$IMAGE_TAG" "pdf2zh" "$@" + "$IMAGE_TAG" "pdf2zh" --openai-compatible-model $OPENROUTER_DEFAULT_MODEL --openai-compatible-base-url $OPENROUTER_API_BASE --openai-compatible-api-key $OPENROUTER_API_KEY "$@" ''; descEn = "PDF scientific paper translation with preserved formats"; descZh = "基于 AI 完整保留排版的 PDF 文档全文双语翻译"; @@ -32,7 +36,7 @@ in { home.packages = [pdf2zhRunner]; home.file.".local/share/kio/servicemenus/pdf2zh.desktop" = { - enable = true; + enable = false; # TODO: Write a wrapper for status tracking executable = true; text = '' [Desktop Entry]