Compare commits

...

3 commits

Author SHA1 Message Date
RingOfStorms (Joshua Bell)
c007bb72d2 persist workspaces 2025-08-26 23:00:45 -05:00
RingOfStorms (Joshua Bell)
8aebae3016 refactor hyprland monitor woes on lio 2025-08-26 17:34:13 -05:00
RingOfStorms (Joshua Bell)
f2aed4dc5f go back to waybar for now 2025-08-26 13:10:14 -05:00
9 changed files with 714 additions and 475 deletions

View file

@ -29,6 +29,12 @@ with lib;
default = { }; default = { };
description = "Extra options for Hyprland configuration."; description = "Extra options for Hyprland configuration.";
}; };
swaync = {
enable = lib.mkEnableOption "Enable Swaync (notification center for Hyprland)";
};
waybar = {
enable = lib.mkEnableOption "Enable Waybar (status bar for Hyprland)";
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {

View file

@ -3,6 +3,7 @@
imports = [ imports = [
./theme.nix ./theme.nix
./hyprland.nix ./hyprland.nix
# ./quickshell.nix
./waybar.nix ./waybar.nix
./hyprpolkitagent.nix ./hyprpolkitagent.nix
./wofi.nix ./wofi.nix

View file

@ -32,6 +32,15 @@ in
# Default monitor configuration # Default monitor configuration
monitor = "monitor = , preferred, auto, 1"; monitor = "monitor = , preferred, auto, 1";
# Make workspaces 7-10 always on MONITOR-2 (replace DP-2 if your secondary isn't DP-2)
# You can get the name of your monitor via `hyprctl monitors`
workspace = [
"7, monitor:DP-2, persistent:true"
"8, monitor:DP-2, persistent:true"
"9, monitor:DP-2, persistent:true"
"10, monitor:DP-2, persistent:true"
];
windowrulev2 = [ windowrulev2 = [
"float, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$" "float, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$"
"center, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$" "center, class:^(?i)chrome-nngceckbapebfimnlniiiahkandclblb-Default$, initialtitle:^_crx_nngceckbapebfimnlniiiahkandclblb$"

View file

@ -2,6 +2,7 @@
osConfig, osConfig,
lib, lib,
pkgs, pkgs,
upkgs,
... ...
}: }:
let let
@ -15,8 +16,7 @@ let
in in
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
quickshell upkgs.quickshell
pulseaudio pulseaudio
brightnessctl brightnessctl
networkmanager networkmanager
@ -27,4 +27,67 @@ in
systemd systemd
hyprlock hyprlock
]; ];
# Ensure CLI quickshell can resolve modules when not using --config-path
home.sessionVariables = {
QML_IMPORT_PATH = "$HOME/.config/quickshell";
QML2_IMPORT_PATH = "$HOME/.config/quickshell";
};
# install config files
home.file = {
".config/quickshell/shell.qml".source = ./quickshell/shell.qml;
".config/quickshell/panels/TopBar.qml".source = ./quickshell/panels/TopBar.qml;
".config/quickshell/notifications/NotificationServer.qml".source =
./quickshell/notifications/NotificationServer.qml;
".config/quickshell/notifications/NotificationPopup.qml".source =
./quickshell/notifications/NotificationPopup.qml;
".config/quickshell/notifications/NotificationCenter.qml".source =
./quickshell/notifications/NotificationCenter.qml;
".config/quickshell/widgets/status/Workspaces.qml".source =
./quickshell/widgets/status/Workspaces.qml;
".config/quickshell/widgets/status/Clock.qml".source = ./quickshell/widgets/status/Clock.qml;
".config/quickshell/widgets/status/SystemTrayWidget.qml".source =
./quickshell/widgets/status/SystemTrayWidget.qml;
".config/quickshell/widgets/status/Battery.qml".source = ./quickshell/widgets/status/Battery.qml;
".config/quickshell/widgets/controls/QuickSettings.qml".source =
./quickshell/widgets/controls/QuickSettings.qml;
".config/quickshell/widgets/controls/Audio.qml".source = ./quickshell/widgets/controls/Audio.qml;
".config/quickshell/widgets/controls/Network.qml".source =
./quickshell/widgets/controls/Network.qml;
".config/quickshell/widgets/controls/Bluetooth.qml".source =
./quickshell/widgets/controls/Bluetooth.qml;
".config/quickshell/widgets/controls/Brightness.qml".source =
./quickshell/widgets/controls/Brightness.qml;
".config/quickshell/widgets/controls/PowerProfilesWidget.qml".source =
./quickshell/widgets/controls/PowerProfilesWidget.qml;
".config/quickshell/panels/qmldir".source = ./quickshell/panels/qmldir;
".config/quickshell/notifications/qmldir".source = ./quickshell/notifications/qmldir;
".config/quickshell/widgets/status/qmldir".source = ./quickshell/widgets/status/qmldir;
".config/quickshell/widgets/controls/qmldir".source = ./quickshell/widgets/controls/qmldir;
# optional: .qmlls.ini should be gitignored; create empty to enable LSP
".config/quickshell/.qmlls.ini".text = "";
};
systemd.user.services.quickshell = {
Unit = {
Description = "Quickshell Desktop Shell";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${upkgs.quickshell}/bin/quickshell --config-path %h/.config/quickshell";
Restart = "on-failure";
RestartSec = 2;
Environment = [
"QML_IMPORT_PATH=%h/.config/quickshell"
"QT_QPA_PLATFORM=wayland"
# Ensure we find icons
"XDG_CURRENT_DESKTOP=quickshell"
];
};
Install = {
WantedBy = [ "graphical-session.target" ];
};
};
} }

View file

@ -1,7 +1,20 @@
{ {
lib,
osConfig,
... ...
}: }:
let
ccfg = import ../../../config.nix;
cfg_path = [
ccfg.custom_config_key
"desktopEnvironment"
"hyprland"
"swaync"
];
cfg = lib.attrsets.getAttrFromPath cfg_path osConfig;
in
{ {
config = lib.mkIf cfg.enable {
services.swaync = { services.swaync = {
enable = true; enable = true;
settings = { settings = {
@ -234,4 +247,5 @@
} }
''; '';
}; };
};
} }

View file

@ -1,7 +1,20 @@
{ {
lib,
osConfig,
... ...
}: }:
let
ccfg = import ../../../config.nix;
cfg_path = [
ccfg.custom_config_key
"desktopEnvironment"
"hyprland"
"waybar"
];
cfg = lib.attrsets.getAttrFromPath cfg_path osConfig;
in
{ {
config = lib.mkIf cfg.enable {
programs.waybar = { programs.waybar = {
enable = true; enable = true;
systemd.enable = true; systemd.enable = true;
@ -250,4 +263,5 @@
} }
''; '';
}; };
};
} }

6
common/flake.lock generated
View file

@ -85,11 +85,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1753592768, "lastModified": 1755928099,
"narHash": "sha256-oV695RvbAE4+R9pcsT9shmp6zE/+IZe6evHWX63f2Qg=", "narHash": "sha256-OILVkfhRCm8u18IZ2DKR8gz8CVZM2ZcJmQBXmjFLIfk=",
"owner": "rycee", "owner": "rycee",
"repo": "home-manager", "repo": "home-manager",
"rev": "fc3add429f21450359369af74c2375cb34a2d204", "rev": "4a44fb9f7555da362af9d499817084f4288a957f",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -29,7 +29,13 @@
nixosConfigurations = { nixosConfigurations = {
"${configuration_name}" = ( "${configuration_name}" = (
lib.nixosSystem { lib.nixosSystem {
specialArgs = { inherit inputs; }; specialArgs = {
inherit inputs;
upkgs = import inputs.nixpkgs-unstable {
system = "x86_64-linux";
config.allowUnfree = true;
};
};
modules = [ modules = [
common.nixosModules.default common.nixosModules.default
ros_neovim.nixosModules.default ros_neovim.nixosModules.default
@ -37,10 +43,12 @@
./hardware-configuration.nix ./hardware-configuration.nix
(import ./containers.nix { inherit inputs; }) (import ./containers.nix { inherit inputs; })
# ./jails_text.nix # ./jails_text.nix
./hyprland_customizations.nix
( (
{ {
config, config,
pkgs, pkgs,
upkgs,
lib, lib,
... ...
}: }:
@ -80,6 +88,11 @@
# Allow emulation of aarch64-linux binaries for cross compiling # Allow emulation of aarch64-linux binaries for cross compiling
boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
home-manager.extraSpecialArgs = {
inherit inputs;
inherit upkgs;
};
ringofstorms_common = { ringofstorms_common = {
systemName = configuration_name; systemName = configuration_name;
boot.systemd.enable = true; boot.systemd.enable = true;
@ -90,26 +103,8 @@
}; };
desktopEnvironment.hyprland = { desktopEnvironment.hyprland = {
enable = true; enable = true;
extraOptions = waybar.enable = true;
let swaync.enable = true;
main = "desc:ASUSTek COMPUTER INC ASUS PG43U 0x01010101";
secondary = "desc:Samsung Electric Company C34J79x HTRM900776";
in
{
# hyprctl monitors all
monitor = [
"${main},3840x2160@97.98,0x0,1,transform,0"
"${secondary},3440x1440@99.98,-1440x-640,1,transform,1"
];
# Pin workspaces 1-6 to main monitor and rest on other monitor
workspace =
let
inherit (builtins) map toString;
inherit (lib) range;
mkWs = monitor: i: "${toString i},monitor:${monitor}";
in
(map (mkWs main) (range 1 6)) ++ (map (mkWs secondary) (range 7 10));
};
}; };
programs = { programs = {
qFlipper.enable = true; qFlipper.enable = true;

View file

@ -0,0 +1,137 @@
{ 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 = {
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 16 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 710 on secondary
for ws in 7 8 9 10; do
''${HYPRCTL} dispatch moveworkspacetomonitor "${"$"}ws" "${"$"}secName" || true
done
else
# No secondary ➜ keep 710 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*)
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 ];
# Pass the options to home-manager for hyprland (as you already do)
ringofstorms_common.desktopEnvironment.hyprland.extraOptions = hyprlandExtraOptions;
# User-level systemd service that follows your Hyprland session and watches for monitor changes
systemd.user.services.hyprland-move-workspaces = {
description = "Keep workspaces 16 on main and 710 on secondary; react to monitor changes";
wants = [ "graphical-session.target" ];
after = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${moveScript}/bin/hyprland-move-workspaces";
Restart = "always";
RestartSec = "2s";
};
wantedBy = [ "graphical-session.target" ];
};
};
}