Compare commits

..

No commits in common. "c007bb72d2ef201dcfbb854656f6810d448d85bf" and "208e16e66685f4d9a56b32c51bf2588c458f591f" have entirely different histories.

9 changed files with 475 additions and 714 deletions

View file

@ -29,12 +29,6 @@ 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,7 +3,6 @@
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

@ -29,17 +29,8 @@ in
# "waybar" # "waybar"
# ]; # ];
# 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$"

View file

@ -2,7 +2,6 @@
osConfig, osConfig,
lib, lib,
pkgs, pkgs,
upkgs,
... ...
}: }:
let let
@ -16,7 +15,8 @@ let
in in
{ {
home.packages = with pkgs; [ home.packages = with pkgs; [
upkgs.quickshell quickshell
pulseaudio pulseaudio
brightnessctl brightnessctl
networkmanager networkmanager
@ -27,67 +27,4 @@ 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,251 +1,237 @@
{ {
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 = { ignore = [
ignore = [ "com.spotify.Client"
"com.spotify.Client" ];
];
positionX = "right"; positionX = "right";
positionY = "top"; positionY = "top";
layer = "overlay"; layer = "overlay";
control-center-layer = "top"; control-center-layer = "top";
layer-shell = true; layer-shell = true;
cssPriority = "application"; cssPriority = "application";
control-center-margin-top = 0; control-center-margin-top = 0;
control-center-margin-bottom = 0; control-center-margin-bottom = 0;
control-center-margin-right = 0; control-center-margin-right = 0;
control-center-margin-left = 0; control-center-margin-left = 0;
notification-2fa-action = true; notification-2fa-action = true;
notification-inline-replies = false; notification-inline-replies = false;
notification-icon-size = 64; notification-icon-size = 64;
notification-body-image-height = 100; notification-body-image-height = 100;
notification-body-image-width = 200; notification-body-image-width = 200;
timeout = 10; timeout = 10;
timeout-low = 5; timeout-low = 5;
timeout-critical = 0; timeout-critical = 0;
control-center-width = 500; control-center-width = 500;
control-center-height = 600; control-center-height = 600;
notification-window-width = 500; notification-window-width = 500;
keyboard-shortcuts = true; keyboard-shortcuts = true;
image-visibility = "when-available"; image-visibility = "when-available";
transition-time = 200; transition-time = 200;
hide-on-clear = false; hide-on-clear = false;
hide-on-action = true; hide-on-action = true;
script-fail-notify = true; script-fail-notify = true;
widgets = [ widgets = [
"inhibitors" "inhibitors"
"title" "title"
"dnd" "dnd"
"volume" "volume"
"backlight" "backlight"
"mpris" "mpris"
"buttons-grid#quick" "buttons-grid#quick"
"notifications" "notifications"
]; ];
# Widget configurations # Widget configurations
widget-config = { widget-config = {
inhibitors = { inhibitors = {
text = "Inhibitors"; text = "Inhibitors";
button-text = "Clear All"; button-text = "Clear All";
clear-all-button = true; clear-all-button = true;
}; };
title = { title = {
text = "Notifications"; text = "Notifications";
clear-all-button = true; clear-all-button = true;
button-text = "Clear All"; button-text = "Clear All";
}; };
dnd.text = "Do Not Disturb"; dnd.text = "Do Not Disturb";
mpris = { mpris = {
image-size = 96; image-size = 96;
image-radius = 12; image-radius = 12;
}; };
volume = { volume = {
label = "󰕾"; label = "󰕾";
show-per-app = true; show-per-app = true;
}; };
backlight = { backlight = {
label = "󰃟"; label = "󰃟";
device = "intel_backlight"; device = "intel_backlight";
}; };
"buttons-grid#quick" = { "buttons-grid#quick" = {
columns = 4; # adjust: 3/4/5 columns = 4; # adjust: 3/4/5
icon-size = 20; # tweak to taste icon-size = 20; # tweak to taste
actions = [ actions = [
# Power # Power
{ {
label = "󰐥"; label = "󰐥";
tooltip = "Shutdown"; tooltip = "Shutdown";
command = "confirm-action 'systemctl poweroff' 'Shutdown?'"; command = "confirm-action 'systemctl poweroff' 'Shutdown?'";
} }
{ {
label = "󰜉"; label = "󰜉";
tooltip = "Reboot"; tooltip = "Reboot";
command = "confirm-action 'systemctl reboot' 'Reboot?'"; command = "confirm-action 'systemctl reboot' 'Reboot?'";
} }
{ {
label = "󰍃"; label = "󰍃";
tooltip = "Logout"; tooltip = "Logout";
command = "confirm-action 'hyprctl dispatch exit' 'Logout?'"; command = "confirm-action 'hyprctl dispatch exit' 'Logout?'";
} }
]; ];
};
}; };
}; };
# Custom CSS for the control center
style = ''
.control-center {
background: #1a1b26;
border: 2px solid #7dcae4;
border-radius: 12px;
}
.control-center-list {
background: transparent;
}
.control-center .notification-row:focus,
.control-center .notification-row:hover {
opacity: 1;
background: #24283b;
}
.notification {
border-radius: 8px;
margin: 6px 12px;
box-shadow: 0 0 0 1px rgba(125, 196, 228, 0.3), 0 1px 3px 1px rgba(0, 0, 0, 0.7), 0 2px 6px 2px rgba(0, 0, 0, 0.3);
padding: 0;
}
/* Widget styling */
.widget-title {
margin: 8px;
font-size: 1.5rem;
color: #c0caf5;
}
.widget-dnd {
margin: 8px;
font-size: 1.1rem;
color: #c0caf5;
}
.widget-dnd > switch {
font-size: initial;
border-radius: 8px;
background: #414868;
border: 1px solid #7dcae4;
}
.widget-dnd > switch:checked {
background: #7dcae4;
}
.widget-mpris {
color: #c0caf5;
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
}
.widget-mpris-player {
padding: 8px;
margin: 8px;
}
.widget-mpris-title {
font-weight: bold;
font-size: 1.25rem;
}
.widget-mpris-subtitle {
font-size: 1.1rem;
color: #9ece6a;
}
.widget-volume {
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
color: #c0caf5;
}
.widget-backlight {
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
color: #c0caf5;
}
.widget-menubar {
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
color: #c0caf5;
}
.widget-menubar .menu-item button {
background: #1f2335;
color: #c0caf5;
border-radius: 8px;
padding: 6px 10px;
margin: 4px;
border: 1px solid #2e3440;
font-family: "JetBrainsMonoNL Nerd Font";
}
.widget-menubar .menu-item button:hover {
background: #414868;
border-color: #7dcae4;
}
.topbar-buttons button {
border: none;
background: transparent;
color: #c0caf5;
font-size: 1.1rem;
border-radius: 8px;
margin: 0 4px;
padding: 8px;
}
.topbar-buttons button:hover {
background: #414868;
}
.topbar-buttons button:active {
background: #7dcae4;
color: #1a1b26;
}
'';
}; };
# Custom CSS for the control center
style = ''
.control-center {
background: #1a1b26;
border: 2px solid #7dcae4;
border-radius: 12px;
}
.control-center-list {
background: transparent;
}
.control-center .notification-row:focus,
.control-center .notification-row:hover {
opacity: 1;
background: #24283b;
}
.notification {
border-radius: 8px;
margin: 6px 12px;
box-shadow: 0 0 0 1px rgba(125, 196, 228, 0.3), 0 1px 3px 1px rgba(0, 0, 0, 0.7), 0 2px 6px 2px rgba(0, 0, 0, 0.3);
padding: 0;
}
/* Widget styling */
.widget-title {
margin: 8px;
font-size: 1.5rem;
color: #c0caf5;
}
.widget-dnd {
margin: 8px;
font-size: 1.1rem;
color: #c0caf5;
}
.widget-dnd > switch {
font-size: initial;
border-radius: 8px;
background: #414868;
border: 1px solid #7dcae4;
}
.widget-dnd > switch:checked {
background: #7dcae4;
}
.widget-mpris {
color: #c0caf5;
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
}
.widget-mpris-player {
padding: 8px;
margin: 8px;
}
.widget-mpris-title {
font-weight: bold;
font-size: 1.25rem;
}
.widget-mpris-subtitle {
font-size: 1.1rem;
color: #9ece6a;
}
.widget-volume {
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
color: #c0caf5;
}
.widget-backlight {
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
color: #c0caf5;
}
.widget-menubar {
background: #24283b;
padding: 8px;
margin: 8px;
border-radius: 8px;
color: #c0caf5;
}
.widget-menubar .menu-item button {
background: #1f2335;
color: #c0caf5;
border-radius: 8px;
padding: 6px 10px;
margin: 4px;
border: 1px solid #2e3440;
font-family: "JetBrainsMonoNL Nerd Font";
}
.widget-menubar .menu-item button:hover {
background: #414868;
border-color: #7dcae4;
}
.topbar-buttons button {
border: none;
background: transparent;
color: #c0caf5;
font-size: 1.1rem;
border-radius: 8px;
margin: 0 4px;
padding: 8px;
}
.topbar-buttons button:hover {
background: #414868;
}
.topbar-buttons button:active {
background: #7dcae4;
color: #1a1b26;
}
'';
}; };
} }

View file

@ -1,267 +1,253 @@
{ {
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; settings = {
settings = { mainBar = {
mainBar = { layer = "top";
layer = "top"; position = "top";
position = "top"; height = 30;
height = 30; spacing = 6;
spacing = 6; margin-top = 0;
margin-top = 0; margin-bottom = 0;
margin-bottom = 0; margin-left = 10;
margin-left = 10; margin-right = 10;
margin-right = 10;
modules-left = [ modules-left = [
"hyprland/workspaces" "hyprland/workspaces"
]; ];
modules-center = [ modules-center = [
"clock" "clock"
"temperature" "temperature"
"cpu" "cpu"
"memory" "memory"
"disk" "disk"
]; ];
modules-right = [ modules-right = [
"pulseaudio" "pulseaudio"
"network" "network"
"bluetooth" "bluetooth"
"custom/notifications" "custom/notifications"
"hyprland/language" "hyprland/language"
]; ];
# Workspaces configuration # Workspaces configuration
"hyprland/workspaces" = { "hyprland/workspaces" = {
format = "{icon}"; format = "{icon}";
format-icons = { format-icons = {
"1" = ""; "1" = "";
"2" = ""; "2" = "";
"3" = ""; "3" = "";
"4" = ""; "4" = "";
"5" = ""; "5" = "";
"6" = ""; "6" = "";
"7" = ""; "7" = "";
"8" = ""; "8" = "";
"9" = ""; "9" = "";
"10" = ""; "10" = "";
"11" = ""; "11" = "";
"12" = ""; "12" = "";
"13" = ""; "13" = "";
"14" = ""; "14" = "";
"15" = ""; "15" = "";
"16" = ""; "16" = "";
"17" = ""; "17" = "";
"18" = ""; "18" = "";
"19" = ""; "19" = "";
"20" = ""; "20" = "";
};
show-special = false;
}; };
show-special = false;
};
pulseaudio = { pulseaudio = {
format = "{icon} {volume}%"; format = "{icon} {volume}%";
format-bluetooth = "󰂰 {volume}%"; format-bluetooth = "󰂰 {volume}%";
format-bluetooth-muted = "󰂲 "; format-bluetooth-muted = "󰂲 ";
format-muted = "󰖁 "; format-muted = "󰖁 ";
format-source = "󰍬 {volume}%"; format-source = "󰍬 {volume}%";
format-source-muted = "󰍭 "; format-source-muted = "󰍭 ";
format-icons = { format-icons = {
headphone = "󰋋"; headphone = "󰋋";
hands-free = "󰂑"; hands-free = "󰂑";
headset = "󰂑"; headset = "󰂑";
phone = "󰏲"; phone = "󰏲";
portable = "󰦧"; portable = "󰦧";
car = "󰄋"; car = "󰄋";
default = [ default = [
"󰕿" "󰕿"
"󰖀" "󰖀"
"󰕾" "󰕾"
]; ];
};
scroll-step = 5;
on-click = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
on-click-right = "swaync-client -t -sw";
}; };
scroll-step = 5;
on-click = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
on-click-right = "swaync-client -t -sw";
};
"custom/notifications" = { "custom/notifications" = {
format = "{icon} {}"; format = "{icon} {}";
format-icons = { format-icons = {
notification = ""; notification = "";
none = ""; none = "";
dnd-notification = "󰂛"; dnd-notification = "󰂛";
dnd-none = "󰂛"; dnd-none = "󰂛";
inhibited-notification = ""; inhibited-notification = "";
inhibited-none = ""; inhibited-none = "";
dnd-inhibited-notification = "󰂛"; dnd-inhibited-notification = "󰂛";
dnd-inhibited-none = "󰂛"; dnd-inhibited-none = "󰂛";
};
return-type = "json";
exec-if = "which swaync-client";
exec = "swaync-client -swb";
on-click = "swaync-client -t -sw";
on-click-right = "swaync-client -d -sw";
escape = true;
tooltip = false;
}; };
return-type = "json";
exec-if = "which swaync-client";
exec = "swaync-client -swb";
on-click = "swaync-client -t -sw";
on-click-right = "swaync-client -d -sw";
escape = true;
tooltip = false;
};
# Clock # Clock
clock = { clock = {
format = "{:%b %d, %H:%M}"; format = "{:%b %d, %H:%M}";
}; };
temperature = { temperature = {
thermal-zone = 2; thermal-zone = 2;
hwmon-path = "/sys/class/hwmon/hwmon2/temp1_input"; hwmon-path = "/sys/class/hwmon/hwmon2/temp1_input";
critical-threshold = 80; critical-threshold = 80;
format-critical = "󰔏 {temperatureC}°C"; format-critical = "󰔏 {temperatureC}°C";
format = "󰔏 {temperatureC}°C"; format = "󰔏 {temperatureC}°C";
}; };
cpu = { cpu = {
format = "󰻠 {usage}%"; format = "󰻠 {usage}%";
tooltip = false; tooltip = false;
on-click = "btop"; on-click = "btop";
}; };
memory = { memory = {
format = "󰍛 {}%"; format = "󰍛 {}%";
on-click = "btop"; on-click = "btop";
}; };
disk = { disk = {
interval = 30; interval = 30;
format = "󰋊 {percentage_used}%"; format = "󰋊 {percentage_used}%";
path = "/"; path = "/";
on-click = "btop"; on-click = "btop";
}; };
network = { network = {
format-wifi = "󰤨 {essid} ({signalStrength}%)"; format-wifi = "󰤨 {essid} ({signalStrength}%)";
format-ethernet = "󰈀 {ipaddr}/{cidr}"; format-ethernet = "󰈀 {ipaddr}/{cidr}";
tooltip-format = "{ifname} via {gwaddr} "; tooltip-format = "{ifname} via {gwaddr} ";
format-linked = "󰈀 {ifname} (No IP)"; format-linked = "󰈀 {ifname} (No IP)";
format-disconnected = "󰖪 Disconnected"; format-disconnected = "󰖪 Disconnected";
on-click = "wofi-wifi-menu"; on-click = "wofi-wifi-menu";
on-click-right = "nmcli radio wifi toggle"; on-click-right = "nmcli radio wifi toggle";
}; };
bluetooth = { bluetooth = {
format = "󰂯 {status}"; format = "󰂯 {status}";
format-connected = "󰂱 {device_alias}"; format-connected = "󰂱 {device_alias}";
format-connected-battery = "󰂱 {device_alias} {device_battery_percentage}%"; format-connected-battery = "󰂱 {device_alias} {device_battery_percentage}%";
tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected"; tooltip-format = "{controller_alias}\t{controller_address}\n\n{num_connections} connected";
tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}"; tooltip-format-connected = "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}";
tooltip-format-enumerate-connected = "{device_alias}\t{device_address}"; tooltip-format-enumerate-connected = "{device_alias}\t{device_address}";
tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%"; tooltip-format-enumerate-connected-battery = "{device_alias}\t{device_address}\t{device_battery_percentage}%";
on-click = "wofi-bluetooth-menu"; on-click = "wofi-bluetooth-menu";
on-click-right = "bluetoothctl power toggle"; on-click-right = "bluetoothctl power toggle";
}; };
# Keyboard input (language) # Keyboard input (language)
"hyprland/language" = { "hyprland/language" = {
format = "{}"; format = "{}";
format-en = "EN"; format-en = "EN";
format-ja = "JP"; format-ja = "JP";
};
}; };
}; };
style = ''
* {
font-family: "JetBrainsMonoNL Nerd Font";
font-size: 12px;
border: none;
border-radius: 0;
min-height: 0;
}
window#waybar {
background: transparent;
border-radius: 10px;
margin: 0px;
}
.modules-left,
.modules-center,
.modules-right {
background: rgba(26, 27, 38, 0.8);
border-radius: 10px;
margin: 4px;
padding: 0 10px;
}
#workspaces {
padding: 0 5px;
}
#workspaces button {
padding: 0 8px;
background: transparent;
color: #c0caf5;
border-radius: 5px;
margin: 2px;
}
#workspaces button:hover {
background: rgba(125, 196, 228, 0.2);
color: #7dcae4;
}
#workspaces button.active {
background: #7dcae4;
color: #1a1b26;
}
#pulseaudio,
#custom-notifications,
#clock,
#temperature,
#cpu,
#memory,
#disk,
#network,
#bluetooth,
#language {
padding: 0 8px;
color: #c0caf5;
margin: 2px;
}
#temperature.critical {
color: #f7768e;
}
#network.disconnected {
color: #f7768e;
}
#bluetooth.disabled {
color: #565f89;
}
#pulseaudio.muted {
color: #565f89;
}
'';
}; };
style = ''
* {
font-family: "JetBrainsMonoNL Nerd Font";
font-size: 12px;
border: none;
border-radius: 0;
min-height: 0;
}
window#waybar {
background: transparent;
border-radius: 10px;
margin: 0px;
}
.modules-left,
.modules-center,
.modules-right {
background: rgba(26, 27, 38, 0.8);
border-radius: 10px;
margin: 4px;
padding: 0 10px;
}
#workspaces {
padding: 0 5px;
}
#workspaces button {
padding: 0 8px;
background: transparent;
color: #c0caf5;
border-radius: 5px;
margin: 2px;
}
#workspaces button:hover {
background: rgba(125, 196, 228, 0.2);
color: #7dcae4;
}
#workspaces button.active {
background: #7dcae4;
color: #1a1b26;
}
#pulseaudio,
#custom-notifications,
#clock,
#temperature,
#cpu,
#memory,
#disk,
#network,
#bluetooth,
#language {
padding: 0 8px;
color: #c0caf5;
margin: 2px;
}
#temperature.critical {
color: #f7768e;
}
#network.disconnected {
color: #f7768e;
}
#bluetooth.disabled {
color: #565f89;
}
#pulseaudio.muted {
color: #565f89;
}
'';
}; };
} }

6
common/flake.lock generated
View file

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

View file

@ -29,13 +29,7 @@
nixosConfigurations = { nixosConfigurations = {
"${configuration_name}" = ( "${configuration_name}" = (
lib.nixosSystem { lib.nixosSystem {
specialArgs = { specialArgs = { inherit inputs; };
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
@ -43,12 +37,10 @@
./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,
... ...
}: }:
@ -88,11 +80,6 @@
# 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;
@ -103,8 +90,26 @@
}; };
desktopEnvironment.hyprland = { desktopEnvironment.hyprland = {
enable = true; enable = true;
waybar.enable = true; extraOptions =
swaync.enable = true; let
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

@ -1,137 +0,0 @@
{ 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" ];
};
};
}