diff --git a/flakes/common/hm_modules/git.nix b/flakes/common/hm_modules/git.nix index 828da11b..aebc5418 100644 --- a/flakes/common/hm_modules/git.nix +++ b/flakes/common/hm_modules/git.nix @@ -12,8 +12,8 @@ # TODO make configurable settings = { user = { - email = "abc@joshuabell.xyz"; - name = "Joshua Bell"; + email = "ringofstorms@gmail.com"; + name = "RingOfStorms (Joshua Bell)"; }; core.pager = "bat"; core.editor = "vi"; diff --git a/flakes/de_plasma/de_plasma.nix b/flakes/de_plasma/de_plasma.nix index 6f42c5a5..c67974fd 100644 --- a/flakes/de_plasma/de_plasma.nix +++ b/flakes/de_plasma/de_plasma.nix @@ -150,7 +150,7 @@ in # kdePackages.plasma-workspace-wallpapers # On-screen keyboard (Plasma Wayland) - # kdePackages.plasma-keyboard + kdePackages.plasma-keyboard # Panel applets required for widgets kdePackages.plasma-nm # org.kde.plasma.networkmanagement diff --git a/flakes/de_plasma/home_manager/default.nix b/flakes/de_plasma/home_manager/default.nix index 44ccf9e9..4153b9da 100644 --- a/flakes/de_plasma/home_manager/default.nix +++ b/flakes/de_plasma/home_manager/default.nix @@ -6,6 +6,8 @@ let cfg = osConfig.ringofstorms.dePlasma; inherit (lib) mkIf optionalAttrs; + # Get the first wallpaper from the list if available + wallpaper = if (builtins.length cfg.wallpapers) > 0 then builtins.head cfg.wallpapers else null; in { imports = [ @@ -294,8 +296,8 @@ in lookAndFeel = "org.kde.breezedark.desktop"; theme = "breeze-dark"; cursor.theme = "breeze_cursors"; - } // optionalAttrs ((builtins.length cfg.wallpapers) > 0) { - wallpaper = cfg.wallpapers; + } // optionalAttrs (wallpaper != null) { + wallpaper = wallpaper; }; configFile = { diff --git a/flakes/de_plasma/home_manager/shortcuts.nix b/flakes/de_plasma/home_manager/shortcuts.nix index e4b46222..4342b441 100644 --- a/flakes/de_plasma/home_manager/shortcuts.nix +++ b/flakes/de_plasma/home_manager/shortcuts.nix @@ -6,9 +6,9 @@ let workspaceLetters = [ "n" "m" - "," - "." - "/" + "Comma" + "Period" + "Slash" ]; kwinWorkspace = builtins.listToAttrs ( map (i: { @@ -85,12 +85,6 @@ in "Lock Session" = "none"; }; - # Disable Plasma emojier shortcuts which conflict with workspace switching - # (Meta+. is bound by default in org.kde.plasma.emojier.desktop) - "org.kde.plasma.emojier.desktop" = { - "_launch" = [ ]; - }; - # "KDE Keyboard Layout Switcher"."Switch to Next Keyboard Layout" = "Meta+K"; }; diff --git a/hosts/lio/flake.lock b/hosts/lio/flake.lock index d21410d5..14de2ed1 100644 --- a/hosts/lio/flake.lock +++ b/hosts/lio/flake.lock @@ -63,20 +63,14 @@ }, "common": { "locked": { - "dir": "flakes/common", - "lastModified": 1768586643, - "narHash": "sha256-FPRn8Ea7h+209KQvdy2FCAaMK7iMbxHvIEb/1Flt9wc=", - "ref": "refs/heads/master", - "rev": "28656f137da6f102749b39b4bcb03c04c7107d2d", - "revCount": 1145, - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" + "path": "../../flakes/common", + "type": "path" }, "original": { - "dir": "flakes/common", - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" - } + "path": "../../flakes/common", + "type": "path" + }, + "parent": [] }, "crane": { "locked": { @@ -137,20 +131,14 @@ "plasma-manager": "plasma-manager" }, "locked": { - "dir": "flakes/de_plasma", - "lastModified": 1768586643, - "narHash": "sha256-FPRn8Ea7h+209KQvdy2FCAaMK7iMbxHvIEb/1Flt9wc=", - "ref": "refs/heads/master", - "rev": "28656f137da6f102749b39b4bcb03c04c7107d2d", - "revCount": 1145, - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" + "path": "../../flakes/de_plasma", + "type": "path" }, "original": { - "dir": "flakes/de_plasma", - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" - } + "path": "../../flakes/de_plasma", + "type": "path" + }, + "parent": [] }, "flake-utils": { "inputs": { @@ -354,11 +342,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1768456270, - "narHash": "sha256-NgaL2CCiUR6nsqUIY4yxkzz07iQUlUCany44CFv+OxY=", + "lastModified": 1768302833, + "narHash": "sha256-h5bRFy9bco+8QcK7rGoOiqMxMbmn21moTACofNLRMP4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f4606b01b39e09065df37905a2133905246db9ed", + "rev": "61db79b0c6b838d9894923920b612048e1201926", "type": "github" }, "original": { @@ -1285,11 +1273,11 @@ "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1768623515, - "narHash": "sha256-7rfFPs9rBXpNmnK77Lc8PBbdTQt6ITotwbJkL85qLIA=", + "lastModified": 1768396176, + "narHash": "sha256-JqLZY6/s3O5IVNjZs4vi4BGQhA730aLLMA7DgENCTTU=", "owner": "anomalyco", "repo": "opencode", - "rev": "85ab9798c65dfb36b0f47de3b1fd786e7751f761", + "rev": "ee6ca104e5eb1693b63901128ea315754f88f595", "type": "github" }, "original": { @@ -1493,20 +1481,14 @@ }, "secrets-bao": { "locked": { - "dir": "flakes/secrets-bao", - "lastModified": 1768586643, - "narHash": "sha256-FPRn8Ea7h+209KQvdy2FCAaMK7iMbxHvIEb/1Flt9wc=", - "ref": "refs/heads/master", - "rev": "28656f137da6f102749b39b4bcb03c04c7107d2d", - "revCount": 1145, - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" + "path": "../../flakes/secrets-bao", + "type": "path" }, "original": { - "dir": "flakes/secrets-bao", - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" - } + "path": "../../flakes/secrets-bao", + "type": "path" + }, + "parent": [] }, "stt_ime": { "inputs": { @@ -1515,20 +1497,14 @@ "nixpkgs": "nixpkgs_7" }, "locked": { - "dir": "flakes/stt_ime", - "lastModified": 1768586643, - "narHash": "sha256-FPRn8Ea7h+209KQvdy2FCAaMK7iMbxHvIEb/1Flt9wc=", - "ref": "refs/heads/master", - "rev": "28656f137da6f102749b39b4bcb03c04c7107d2d", - "revCount": 1145, - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" + "path": "../../flakes/stt_ime", + "type": "path" }, "original": { - "dir": "flakes/stt_ime", - "type": "git", - "url": "https://git.joshuabell.xyz/ringofstorms/dotfiles" - } + "path": "../../flakes/stt_ime", + "type": "path" + }, + "parent": [] }, "systems": { "locked": { diff --git a/hosts/lio/flake.nix b/hosts/lio/flake.nix index be43e776..5de6921a 100644 --- a/hosts/lio/flake.nix +++ b/hosts/lio/flake.nix @@ -6,20 +6,20 @@ nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; # Use relative to get current version for testing - # common.url = "path:../../flakes/common"; - common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common"; + common.url = "path:../../flakes/common"; + # common.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/common"; # secrets.url = "path:../../flakes/secrets"; secrets.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/secrets"; - # secrets-bao.url = "path:../../flakes/secrets-bao"; - secrets-bao.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/secrets-bao"; + secrets-bao.url = "path:../../flakes/secrets-bao"; + # secrets-bao.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/secrets-bao"; # flatpaks.url = "path:../../flakes/flatpaks"; flatpaks.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/flatpaks"; # beszel.url = "path:../../flakes/beszel"; beszel.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/beszel"; - # de_plasma.url = "path:../../flakes/de_plasma"; - de_plasma.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/de_plasma"; - # stt_ime.url = "path:../../flakes/stt_ime"; - stt_ime.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/stt_ime"; + de_plasma.url = "path:../../flakes/de_plasma"; + # de_plasma.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/de_plasma"; + stt_ime.url = "path:../../flakes/stt_ime"; + # stt_ime.url = "git+https://git.joshuabell.xyz/ringofstorms/dotfiles?dir=flakes/stt_ime"; opencode.url = "github:anomalyco/opencode"; ros_neovim.url = "git+https://git.joshuabell.xyz/ringofstorms/nvim"; diff --git a/hosts/lio/home_manager.nix b/hosts/lio/home_manager.nix new file mode 100644 index 00000000..f42762b7 --- /dev/null +++ b/hosts/lio/home_manager.nix @@ -0,0 +1,10 @@ +{ + config, + lib, + pkgs, + modulesPath, + ... +}: +{ + +} diff --git a/hosts/lio/hyprland_customizations.nix b/hosts/lio/hyprland_customizations.nix new file mode 100644 index 00000000..7629e2e8 --- /dev/null +++ b/hosts/lio/hyprland_customizations.nix @@ -0,0 +1,157 @@ +{ lib, pkgs, ... }: +let + # Exact descriptions as reported by: hyprctl -j monitors | jq '.[].description' + mainDesc = "ASUSTek COMPUTER INC ASUS PG43U 0x01010101"; + secondaryDesc = "Samsung Electric Company C34J79x HTRM900776"; + + mainMonitor = "desc:${mainDesc}"; + secondaryMonitor = "desc:${secondaryDesc}"; + + hyprlandExtraOptions = { + exec-once = [ + # Wait a moment for monitors/workspaces to settle, then "prime" 6 and return to 1 + "sh -lc 'sleep 0.2; hyprctl dispatch workspace 7; sleep 0.02; hyprctl dispatch workspace 1'" + + ]; + monitor = [ + "${mainMonitor},3840x2160@97.98,0x0,1,transform,0" + "${secondaryMonitor},3440x1440@99.98,-1440x-640,1,transform,1" + ]; + workspace = + let + inherit (builtins) map toString; + inherit (lib) range; + mkWs = monitor: i: "${toString i},monitor:${monitor},persistent:true"; + in + (map (mkWs mainMonitor) (range 1 6)) ++ (map (mkWs secondaryMonitor) (range 7 10)); + }; + + moveScript = pkgs.writeShellScriptBin "hyprland-move-workspaces" '' + #!/usr/bin/env bash + set -euo pipefail + + HYPRCTL='${pkgs.hyprland}/bin/hyprctl' + JQ='${pkgs.jq}/bin/jq' + SOCAT='${pkgs.socat}/bin/socat' + + MAIN_DESC='${mainDesc}' + SEC_DESC='${secondaryDesc}' + + get_socket() { + # socket2 carries the event stream + echo "${"$"}{XDG_RUNTIME_DIR}/hypr/${"$"}{HYPRLAND_INSTANCE_SIGNATURE}/.socket2.sock" + } + + wait_for_hypr() { + # Wait until hyprctl works (Hyprland is up) + until ''${HYPRCTL} -j monitors >/dev/null 2>&1; do + sleep 0.5 + done + } + + mon_name_by_desc() { + # Resolve Hyprland "name" (e.g., DP-2) from human-friendly description + local desc="${"$"}1" + ''${HYPRCTL} -j monitors \ + | ''${JQ} -r --arg d "${"$"}desc" '.[] | select(.description == $d) | .name' \ + | head -n1 + } + + place_workspaces() { + local mainName secName + mainName="$(mon_name_by_desc "${"$"}MAIN_DESC")" + secName="$(mon_name_by_desc "${"$"}SEC_DESC" || true)" + + # Always keep 1–6 on the main monitor + for ws in 1 2 3 4 5 6; do + ''${HYPRCTL} dispatch moveworkspacetomonitor "${"$"}ws" "${"$"}mainName" || true + done + + if [ -n "${"$"}{secName:-}" ]; then + # Secondary is present ➜ put 7–10 on secondary + for ws in 7 8 9 10; do + ''${HYPRCTL} dispatch moveworkspacetomonitor "${"$"}ws" "${"$"}secName" || true + done + else + # No secondary ➜ keep 7–10 on main + for ws in 7 8 9 10; do + ''${HYPRCTL} dispatch moveworkspacetomonitor "${"$"}ws" "${"$"}mainName" || true + done + fi + } + + watch_events() { + local sock + sock="$(get_socket)" + + # If socket2 is missing for some reason, fall back to polling + if [ ! -S "${"$"}sock" ]; then + while :; do + place_workspaces + sleep 5 + done + return + fi + + # Subscribe to Hyprland events and react to monitor changes + ''${SOCAT} - "UNIX-CONNECT:${"$"}sock" | while IFS= read -r line; do + case "${"$"}line" in + monitoradded*|monitorremoved*|activemonitor*|layoutchange*|createworkspace*) + place_workspaces + ;; + esac + done + } + + if [ "${"$"}{1:-}" = "--oneshot" ]; then + wait_for_hypr + place_workspaces + else + wait_for_hypr + place_workspaces + watch_events + fi + ''; +in +{ + options = { }; + + config = { + environment.systemPackages = [ moveScript ]; + + ringofstorms_common.desktopEnvironment.hyprland.extraOptions = hyprlandExtraOptions; + + ringofstorms_common.desktopEnvironment.hyprland.hyprpaperSettings = { + mode = "fill"; # Wallpaper display mode: fill, fit, stretch, center, tile + + preload = [ + "${../_shared_assets/wallpapers/pixel_neon.png}" + ]; + + wallpaper = [ + "${mainMonitor},${../_shared_assets/wallpapers/pixel_neon.png}" + "${secondaryMonitor},${../_shared_assets/wallpapers/pixel_neon_v.png}" + ]; + }; + + # User-level systemd service that follows your Hyprland session and watches for monitor changes + # systemd.user.services.hyprland-move-workspaces = { + # description = "Keep workspaces 1–6 on main and 7–10 on secondary; react to monitor changes"; + # + # # Start/stop with Hyprland specifically + # wantedBy = [ "hyprland-session.target" ]; + # after = [ "hyprland-session.target" ]; + # partOf = [ "hyprland-session.target" ]; + # bindsTo = [ "hyprland-session.target" ]; + # # Only start once Hyprland's event socket exists + # unitConfig.ConditionPathExistsGlob = "%t/hypr/*/.socket2.sock"; + # + # serviceConfig = { + # Type = "simple"; + # ExecStart = "${moveScript}/bin/hyprland-move-workspaces"; + # Restart = "always"; + # RestartSec = "2s"; + # }; + # }; + }; +} diff --git a/hosts/lio/i3_customizations.nix b/hosts/lio/i3_customizations.nix new file mode 100644 index 00000000..4f294e5b --- /dev/null +++ b/hosts/lio/i3_customizations.nix @@ -0,0 +1,51 @@ +{ pkgs, ... }: +let + assignLines = '' + workspace 1 output DP-1 + workspace 2 output DP-1 + workspace 3 output DP-1 + workspace 4 output DP-1 + workspace 5 output DP-1 + workspace 6 output DP-1 + workspace 7 output DP-2 + workspace 8 output DP-2 + workspace 9 output DP-2 + workspace 10 output DP-2 + ''; + bg1 = ../_shared_assets/wallpapers/pixel_neon.png; + bg2 = ../_shared_assets/wallpapers/pixel_neon_v.png; + # xrSetup = "xrandr --output DP-1 --mode 3840x2160 --rate 119.88 --pos 0x0 --primary; sleep 0.2; xrandr --output DP-2 --mode 3440x1440 --rate 99.98 --rotate left --left-of DP-1"; + xrSetup = "xrandr --output DP-1 --mode 3840x2160 --rate 60 --pos 0x0 --primary; sleep 0.2; xrandr --output DP-2 --mode 3440x1440 --rate 99.98 --rotate left --left-of DP-1"; + xwallpaperCmd = "xwallpaper --output DP-1 --zoom ${bg1} --output DP-2 --zoom ${bg2}"; + startupCmd = "sh -c 'sleep 0.2; i3-msg workspace number 7; sleep 0.2; i3-msg workspace number 1'"; + i3ExtraOptions = { + startup = [ + { command = "${xrSetup}"; } + { command = "sh -c 'sleep 1; ${xwallpaperCmd}'"; } + { command = "${startupCmd}"; } + ]; + }; +in +{ + options = { }; + config = { + home-manager.sharedModules = [ + ( + { lib, pkgs, ... }: + let + inherit (lib) mkAfter; + in + { + xsession.windowManager.i3.config.startup = mkAfter (i3ExtraOptions.startup ++ [ + { command = "nm-applet"; } + { command = "blueman-applet"; } + { command = "xfce4-power-manager"; } + { command = "sh -c 'xset s off -dpms; xset s noblank'"; } + ]); + xsession.windowManager.i3.extraConfig = mkAfter assignLines; + home.packages = [ pkgs.xwallpaper pkgs.xorg.xrandr pkgs.xorg.xset ]; + } + ) + ]; + }; +} diff --git a/hosts/lio/sway_customizations.nix b/hosts/lio/sway_customizations.nix new file mode 100644 index 00000000..a58f2e22 --- /dev/null +++ b/hosts/lio/sway_customizations.nix @@ -0,0 +1,88 @@ +{ ... }: +let + swayExtraOptions = { + startup = [ + { + command = "exec sh -c 'sleep 0.01; swaymsg workspace number 7; sleep 0.02; swaymsg workspace number 1'"; + } + ]; + + # Example: map workspaces 1–6 to DP-1 and 7–10 to HDMI-A-1 + workspaceOutputAssign = [ + { + workspace = "1"; + output = "DP-1"; + } + { + workspace = "2"; + output = "DP-1"; + } + { + workspace = "3"; + output = "DP-1"; + } + { + workspace = "4"; + output = "DP-1"; + } + { + workspace = "5"; + output = "DP-1"; + } + { + workspace = "6"; + output = "DP-1"; + } + { + workspace = "7"; + output = "DP-2"; + } + { + workspace = "8"; + output = "DP-2"; + } + { + workspace = "9"; + output = "DP-2"; + } + { + workspace = "10"; + output = "DP-2"; + } + ]; + + # Optional output settings + output = { + "DP-1" = { + scale = "1"; + pos = "0 0"; + mode = "3840x2160@97.983Hz"; + bg = "${../_shared_assets/wallpapers/pixel_neon.png} fill"; + }; + "DP-2" = { + scale = "1"; + transform = "270"; + pos = "-1440 -640"; + mode = "3440x1440@99.982Hz"; + bg = "${../_shared_assets/wallpapers/pixel_neon_v.png} fill"; + }; + }; + }; + +in +{ + options = { }; + + config = { + # ringofstorms_common.desktopEnvironment.sway.extraOptions = swayExtraOptions; + + home-manager.sharedModules = [ + ( + { ... }: + { + wayland.windowManager.sway.config = swayExtraOptions; + } + ) + ]; + }; +}