Kieran's opinionated (and probably slightly dumb) nix config

chore: Add hyprland-nix config taken from spikespaz/dotfiles

+3
flake.nix
···
# Home manager
home-manager.url = "github:nix-community/home-manager/release-23.11";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
+
+
# hyprland nix
+
hyprland-nix.url = "github:hyprland-community/hyprnix";
};
outputs = {
+158
moonlark/hyprland/config.nix
···
+
{ lib, ... }:
+
let
+
inherit (lib.birdos.colors) grayRGB;
+
hyprRGBA = rgb: a: "rgba(${lib.birdos.colors.hexRGBA rgb a})";
+
gb = (lib.birdos.colors.formats.custom hyprRGBA).gruvbox.dark;
+
shadow = hyprRGBA (grayRGB 6.0e-2); # 6% of each channel
+
in {
+
wayland.windowManager.hyprland = {
+
# <https://wiki.hyprland.org/Configuring/Variables/#general>
+
config.general = {
+
border_size = 2;
+
gaps_inside = 5;
+
gaps_outside = 10;
+
active_border_color = gb.fg3 1.0;
+
inactive_border_color = gb.bg3 1.0;
+
cursor_inactive_timeout = 10;
+
no_cursor_warps = true;
+
resize_on_border = true;
+
extend_border_grab_area = 10;
+
};
+
+
# <https://wiki.hyprland.org/Configuring/Variables/#decoration>
+
config.decoration = {
+
rounding = 0;
+
shadow_range = 8;
+
shadow_render_power = 2;
+
active_shadow_color = shadow 0.9;
+
inactive_shadow_color = shadow 0.6;
+
blur = {
+
size = 3; # 8
+
passes = 2; # 1
+
ignore_opacity = true; # false
+
xray = true; # false
+
noise = 6.5e-2; # 0.0117
+
contrast = 0.75; # 0.8916
+
brightness = 0.8; # 0.8172
+
};
+
};
+
+
# <https://wiki.hyprland.org/Configuring/Variables/#input>
+
config.input = let
+
DISABLED = 0;
+
LOOSE = 2;
+
in {
+
follow_mouse = LOOSE;
+
float_switch_override_focus = DISABLED;
+
};
+
+
# <https://wiki.hyprland.org/Configuring/Variables/#binds>
+
config.binds = let LONGEST_SHARED_SIDE = 1;
+
in {
+
pass_mouse_when_bound = false;
+
focus_preferred_method = LONGEST_SHARED_SIDE;
+
};
+
+
config.gestures = {
+
workspace_swipe = {
+
enable = true;
+
invert = false;
+
min_speed_to_force = 20;
+
cancel_ratio = 0.65;
+
create_new = false;
+
forever = true;
+
};
+
};
+
+
# <https://wiki.hyprland.org/Configuring/Variables/#misc>
+
config.misc = let FULLSCREEN_ONLY = 2;
+
in {
+
disable_hyprland_logo = true; # false
+
disable_splash_rendering = true; # false
+
force_default_wallpaper = 0; # disable weeb stuff
+
variable_framerate = true;
+
variable_refresh = FULLSCREEN_ONLY;
+
disable_autoreload = true; # false # nix takes care of that
+
+
# works well with swayidle
+
key_press_enables_dpms = true;
+
mouse_move_enables_dpms = true;
+
};
+
+
config.group = {
+
insert_after_current = true;
+
focus_removed_window = true;
+
+
active_border_color = gb.hl_yellow 1.0;
+
inactive_border_color = gb.bg3 1.0;
+
locked_active_border_color = gb.hl_blue 1.0;
+
locked_inactive_border_color = gb.bg3 1.0;
+
+
# These features are not polished yet:
+
# <https://github.com/hyprwm/Hyprland/issues/2415>
+
# @MightyPlaza is working on this, but not doing it how we expect.
+
# <https://github.com/hyprwm/Hyprland/pull/3197>
+
groupbar = rec {
+
font_size = 9;
+
gradients = false;
+
render_titles = true;
+
scrolling = true;
+
text_color = gb.fg0 1.0;
+
+
active_color = gb.fg3 1.0;
+
inactive_color = gb.bg1 0.6;
+
locked_active_color = active_color;
+
locked_inactive_color = inactive_color;
+
};
+
};
+
+
# <https://wiki.hyprland.org/Configuring/Dwindle-Layout/>
+
config.dwindle = let ALWAYS_EAST = 2;
+
in {
+
force_split = ALWAYS_EAST; # 0
+
preserve_split = true; # false
+
# no_gaps_when_only = true;
+
};
+
+
# <https://wiki.hyprland.org/Configuring/Animations/#curves>
+
animations.animation = {
+
# window creation
+
windowsIn = {
+
enable = true;
+
duration = 200;
+
curve = "easeOutCirc";
+
style = "popin 60%";
+
};
+
fadeIn = {
+
enable = true;
+
duration = 100;
+
curve = "easeOutCirc";
+
};
+
# window destruction
+
windowsOut = {
+
enable = true;
+
duration = 200;
+
curve = "easeOutCirc";
+
style = "popin 60%";
+
};
+
fadeOut = {
+
enable = true;
+
duration = 100;
+
curve = "easeOutCirc";
+
};
+
# window movement
+
windowsMove = {
+
enable = true;
+
duration = 300;
+
curve = "easeInOutCubic";
+
style = "popin";
+
};
+
workspaces = {
+
enable = true;
+
duration = 200;
+
curve = "easeOutCirc";
+
style = "slide";
+
};
+
};
+
};
+
}
+52
moonlark/hyprland/default.nix
···
+
{ self, config, lib, pkgs, inputs, ... }: {
+
imports = [
+
inputs.hyprland-nix.homeManagerModules.hyprland
+
# inputs.hyprland-nix.homeManagerModules.xdg-desktop-portals
+
./config.nix
+
./windowrules.nix
+
./keybinds.nix
+
./waybar.nix
+
];
+
+
home.packages = [
+
# Screen Capture
+
pkgs.prtsc
+
# xwayland perm for pkexec
+
pkgs.xorg.xhost
+
];
+
+
wayland.windowManager.hyprland = {
+
enable = true;
+
package = pkgs.hyprland;
+
reloadConfig = true;
+
systemdIntegration = true;
+
recommendedEnvironment = true;
+
+
xwayland.enable = true;
+
+
config.exec_once = [
+
# polkit agent, raises to root access with gui
+
"${lib.getExe pkgs.lxqt.lxqt-policykit}"
+
# allow apps with risen perms after agent to connect to local xwayland
+
"${lib.getExe pkgs.xorg.xhost} +local:"
+
];
+
};
+
+
# xdg.desktopPortals = {
+
# enable = true;
+
# extraPortals = [
+
# pkgs.xdg-desktop-portal-hyprland
+
# pkgs.xdg-desktop-portal-kde
+
# pkgs.xdg-desktop-portal-gtk
+
# ];
+
# configPackages = [ config.wayland.windowManager.hyprland.package ];
+
# config = {
+
# x-cinnamon = { default = [ "xapp" "gtk" ]; };
+
# pantheon = {
+
# default = [ "pantheon" "gtk" ];
+
# "org.freedesktop.impl.portal.Secret" = [ "gnome-keyring" ];
+
# };
+
# common = { default = [ "gtk" ]; };
+
# };
+
# };
+
}
+281
moonlark/hyprland/keybinds.nix
···
+
# Converted with regex from hyprland config
+
# search: ^(\s*)(bind[rwelm]*) = (|\w+), (|\$?\w+), (.+)$ /gm
+
# replace: $1$2."$3, $4" = "$5";
+
+
{ config, pkgs, lib, ... }: {
+
# <https://wiki.hyprland.org/Configuring/Dispatchers/>
+
wayland.windowManager.hyprland.keyBinds = let
+
MOUSE_LMB = "mouse:272";
+
MOUSE_RMB = "mouse:273";
+
# MOUSE_MMB = "mouse:274";
+
MOUSE_EX1 = "mouse:275";
+
MOUSE_EX2 = "mouse:276";
+
+
exec = {
+
screenshotWindow = pkgs.patchShellScript ./scripts/screenshot.sh {
+
runtimeInputs = with pkgs; [
+
jq
+
grim
+
wl-clipboard
+
libnotify
+
config.wayland.windowManager.hyprland.package
+
];
+
};
+
playerctl = lib.getExe pkgs.playerctl;
+
slight = lib.getExe pkgs.slight;
+
osdFunc = lib.getExe config.utilities.osd-functions.package;
+
airplaneMode = "sudo /run/current-system/sw/bin/airplane-mode";
+
toggleGroupOrLock =
+
pkgs.patchShellScript ./scripts/toggle-group-or-lock.sh {
+
runtimeInputs = with pkgs; [
+
jq
+
config.wayland.windowManager.hyprland.package
+
];
+
};
+
};
+
+
# Collections of keybinds common across multiple submaps are collected into
+
# groups, which can be merged together granularly.
+
groups = {
+
# Exit the submap and restore normal binds.
+
submapReset = {
+
bind.", escape" = "submap, reset";
+
bind."CTRL, C" = "submap, reset";
+
};
+
+
# Self-explanatory.
+
launchPrograms = {
+
# Launch the program with a shortcut.
+
bind."SUPER, E" = "exec, dolphin";
+
bind."SUPER, Enter" = "exec, alacritty";
+
};
+
+
# Kill the active window.
+
killWindow = { bind."SUPER, Q" = "killactive,"; };
+
+
# Either window focus or window movement.
+
moveFocusOrWindow = with groups;
+
lib.mkMerge [ moveFocus moveWindow mouseMoveWindow ];
+
+
# Focus on another window, in the specified direction.
+
moveFocus = {
+
bind."SUPER, left" = "movefocus, l";
+
bind."SUPER, right" = "movefocus, r";
+
bind."SUPER, up" = "movefocus, u";
+
bind."SUPER, down" = "movefocus, d";
+
};
+
+
# Swap the active window with another, in the specified direction.
+
moveWindow = {
+
bind."SUPER_SHIFT, left" = "movewindow, l";
+
bind."SUPER_SHIFT, right" = "movewindow, r";
+
bind."SUPER_SHIFT, up" = "movewindow, u";
+
bind."SUPER_SHIFT, down" = "movewindow, d";
+
};
+
+
# Translate the dragged window by mouse movement.
+
mouseMoveWindow = {
+
bindm."SUPER, ${MOUSE_LMB}" = "movewindow";
+
bindm.", ${MOUSE_EX2}" = "movewindow";
+
};
+
+
# Toggle between vertical and horizontal split for
+
# the active window and an adjacent one.
+
toggleSplit = { bind."SUPER, tab" = "togglesplit,"; };
+
+
# Resize a window with the mouse.
+
mouseResizeWindow = {
+
bindm."SUPER, ${MOUSE_RMB}" = "resizewindow";
+
bindm.", ${MOUSE_EX1}" = "resizewindow";
+
};
+
+
# Switch to the next/previous tab in the active group.
+
changeGroupActive = {
+
bind."ALT, tab" = "changegroupactive, f";
+
bind."ALT, grave" = "changegroupactive, b";
+
};
+
+
# Switch to another workspace.
+
switchWorkspace = with groups;
+
lib.mkMerge [ switchWorkspaceAbsolute switchWorkspaceRelative ];
+
+
# Switch to a workspace by absolute identifier.
+
switchWorkspaceAbsolute = {
+
# Switch to a primary workspace by index.
+
bind."SUPER, 1" = "workspace, 1";
+
bind."SUPER, 2" = "workspace, 2";
+
bind."SUPER, 3" = "workspace, 3";
+
bind."SUPER, 4" = "workspace, 4";
+
bind."SUPER, 5" = "workspace, 5";
+
bind."SUPER, 6" = "workspace, 6";
+
bind."SUPER, 7" = "workspace, 7";
+
bind."SUPER, 8" = "workspace, 8";
+
bind."SUPER, 9" = "workspace, 9";
+
bind."SUPER, 0" = "workspace, 10";
+
+
# Switch to an alternate workspace by index.
+
bind."SUPER_ALT, 1" = "workspace, 11";
+
bind."SUPER_ALT, 2" = "workspace, 12";
+
bind."SUPER_ALT, 3" = "workspace, 13";
+
bind."SUPER_ALT, 4" = "workspace, 14";
+
bind."SUPER_ALT, 5" = "workspace, 15";
+
bind."SUPER_ALT, 6" = "workspace, 16";
+
bind."SUPER_ALT, 7" = "workspace, 17";
+
bind."SUPER_ALT, 8" = "workspace, 18";
+
bind."SUPER_ALT, 9" = "workspace, 19";
+
bind."SUPER_ALT, 0" = "workspace, 20";
+
+
# TODO Bind the special workspace to `XF86Favorites`.
+
# TODO Create a bind for "insert after current workspace".
+
};
+
+
# Switch to workspaces relative to the current one.
+
switchWorkspaceRelative = {
+
# Switch to the next/previous used workspace with page keys.
+
bind."SUPER, page_down" = "workspace, m+1";
+
bind."SUPER, page_up" = "workspace, m-1";
+
+
# Switch to the next/previous used workspace
+
# with the right and left square brackets,
+
# while holding super and shift.
+
bind."SUPER, bracketright " = "workspace, m+1";
+
bind."SUPER, bracketleft" = "workspace, m-1";
+
+
# Switch to the next/previous used workspace with the mouse wheel.
+
bind."SUPER, mouse_up" = "workspace, m+1";
+
bind."SUPER, mouse_down" = "workspace, m-1";
+
};
+
+
# Send a window to another workspace.
+
sendWindow = with groups;
+
lib.mkMerge [ sendWindowAbsolute sendWindowRelative ];
+
+
# Send a window to a workspace by absolute identifier.
+
sendWindowAbsolute = {
+
# Move the active window or group to a primary workspace by index.
+
bind."SUPER_SHIFT, 1" = "movetoworkspacesilent, 1";
+
bind."SUPER_SHIFT, 2" = "movetoworkspacesilent, 2";
+
bind."SUPER_SHIFT, 3" = "movetoworkspacesilent, 3";
+
bind."SUPER_SHIFT, 4" = "movetoworkspacesilent, 4";
+
bind."SUPER_SHIFT, 5" = "movetoworkspacesilent, 5";
+
bind."SUPER_SHIFT, 6" = "movetoworkspacesilent, 6";
+
bind."SUPER_SHIFT, 7" = "movetoworkspacesilent, 7";
+
bind."SUPER_SHIFT, 8" = "movetoworkspacesilent, 8";
+
bind."SUPER_SHIFT, 9" = "movetoworkspacesilent, 9";
+
bind."SUPER_SHIFT, 0" = "movetoworkspacesilent, 10";
+
+
# Move the active window or group to an alternate workspace by index.
+
bind."SUPER_ALT_SHIFT, 1" = "movetoworkspacesilent, 11";
+
bind."SUPER_ALT_SHIFT, 2" = "movetoworkspacesilent, 12";
+
bind."SUPER_ALT_SHIFT, 3" = "movetoworkspacesilent, 13";
+
bind."SUPER_ALT_SHIFT, 4" = "movetoworkspacesilent, 14";
+
bind."SUPER_ALT_SHIFT, 5" = "movetoworkspacesilent, 15";
+
bind."SUPER_ALT_SHIFT, 6" = "movetoworkspacesilent, 16";
+
bind."SUPER_ALT_SHIFT, 7" = "movetoworkspacesilent, 17";
+
bind."SUPER_ALT_SHIFT, 8" = "movetoworkspacesilent, 18";
+
bind."SUPER_ALT_SHIFT, 9" = "movetoworkspacesilent, 19";
+
bind."SUPER_ALT_SHIFT, 0" = "movetoworkspacesilent, 20";
+
};
+
+
# Send windows to other workspaces, relative to the current one.
+
sendWindowRelative = {
+
# Move the active window or group to the next/previous
+
# workspace with page keys, while holding super and shift.
+
bind."SUPER_SHIFT, page_down" = "movetoworkspace, r+1";
+
bind."SUPER_SHIFT, page_up" = "movetoworkspace, r-1";
+
+
# Move the active window or group to the next/previous
+
# workspace with the right and left square brackets,
+
# while holding super and shift.
+
bind."SUPER_SHIFT, bracketright" = "movetoworkspace, r+1";
+
bind."SUPER_SHIFT, bracketleft" = "movetoworkspace, r-1";
+
+
# Move the active window or group to the next/previous
+
# workspace with the mouse wheel while holding super and shift.
+
bind."SUPER_SHIFT, mouse_up" = "movetoworkspace, r+1";
+
bind."SUPER_SHIFT, mouse_down" = "movetoworkspace, r-1";
+
};
+
};
+
in lib.mkMerge [
+
### ACTIVE WINDOW ACTIONS ###
+
groups.killWindow
+
{
+
# Toggle full-screen for the active window.
+
bind."SUPER_SHIFT, F" = "fullscreen, 0";
+
+
# Float/unfloat the active window.
+
bind."SUPER, F" = "togglefloating,";
+
}
+
### MISCELLANEOUS ###
+
{
+
# Lock the session immediately.
+
bind."SUPER, l" = "exec, loginctl lock-session";
+
+
# Kill the window manager.
+
bind."SUPER_SHIFT, M" = "exit,";
+
+
# Forcefully kill a program after selecting its window with the mouse.
+
bind."SUPER_SHIFT, Q" = "exec, hyprctl kill";
+
+
# Screenshot the currently focused window and copy to clipboard.
+
bind."SUPER, print" = "exec, ${exec.screenshotWindow}";
+
+
# Select a region and take a screenshot, saving to the clipboard.
+
bind."SUPER_SHIFT, print" = "exec, prtsc -c -m r -D -b 00000066";
+
+
# Bypass all binds for the window manager and pass key combinations
+
# directly to the active window.
+
bind."SUPER_SHIFT, K" = "submap, passthru";
+
submap.passthru = { bind."SUPER_SHIFT, K" = "submap, reset"; };
+
}
+
### PROGRAM LAUNCHING ###
+
groups.launchPrograms
+
{
+
# Open Rofi to launch a program.
+
bind."SUPER, Space" = "exec, rofi -show drun -show-icons";
+
# Open Rofi to run a command.
+
bind."SUPER, R" = "exec, rofi -show run";
+
}
+
### FUNCTION KEYS ###
+
{
+
# The names of these keys can be found at:
+
# <https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h>
+
+
bindl."SHIFT, XF86WLAN" = "exec, ${exec.airplaneMode}";
+
+
# Mute/unmute the active audio output.
+
bindl.", XF86AudioMute" = "exec, ${exec.osdFunc} output mute";
+
+
# Raise and lower the volume of the active audio output.
+
bindel.", XF86AudioRaiseVolume" = "exec, ${exec.osdFunc} output +0.05";
+
bindel.", XF86AudioLowerVolume" = "exec, ${exec.osdFunc} output -0.05";
+
+
# Mute the active microphone or audio source.
+
bindl.", XF86AudioMicMute" = "exec, ${exec.osdFunc} input mute";
+
+
# Raise and lower display brightness.
+
bindel.", XF86MonBrightnessUp" = "exec, ${exec.slight} inc 10 -t 300ms";
+
bindel.", XF86MonBrightnessDown" = "exec, ${exec.slight} dec 10 -t 300ms";
+
+
# Regular media control keys, if your laptop or bluetooth device has them.
+
bindl.", XF86AudioPlay" = "exec, ${exec.playerctl} play-pause";
+
bindl.", XF86AudioPrev" = "exec, ${exec.playerctl} previous";
+
bindl.", XF86AudioNext" = "exec, ${exec.playerctl} next";
+
+
# Poor-man's media player control keys.
+
bindl."SUPER, slash" = "exec, ${exec.playerctl} play-pause";
+
bindl."SUPER, comma" = "exec, ${exec.playerctl} previous";
+
bindl."SUPER, period" = "exec, ${exec.playerctl} next";
+
}
+
### WINDOW FOCUS & MOVEMENT ###
+
groups.moveFocusOrWindow
+
### WINDOW RESIZING ###
+
groups.toggleSplit
+
groups.mouseResizeWindow
+
}
+
### WORKSPACE SWITCHING ###
+
groups.switchWorkspace
+
### WORKSPACE WINDOW MOVEMENT ###
+
groups.sendWindow
+
];
+
}
+384
moonlark/hyprland/waybar.nix
···
+
{ config, lib, pkgs, ... }:
+
let
+
package = pkgs.waybar;
+
+
# the fonts that will be included with the waybar package
+
fontPackages = [ pkgs.ubuntu_font_family pkgs.material-design-icons ];
+
+
# patch those fonts in
+
package' = let super = package;
+
in pkgs.symlinkJoin {
+
inherit (super) name pname version meta;
+
paths = [ super ] ++ fontPackages;
+
};
+
+
compileSCSS = name: source:
+
"${
+
pkgs.runCommandLocal name { } ''
+
mkdir -p $out
+
${lib.getExe pkgs.sassc} -t expanded '${source}' > $out/${name}.css
+
''
+
}/${name}.css";
+
+
# TODO when using store paths to executables, they do not inherit the user's
+
# environment (at least with systemd) and therefore GUIs use the default theme
+
commands = let
+
slight = "${lib.getExe pkgs.slight}";
+
hyprctl = "${config.wayland.windowManager.hyprland.package}/bin/hyprctl";
+
# TODO this is duplicated from the hyprland config, make it a module
+
kbFns = lib.getExe config.utilities.osd-functions.package;
+
pavucontrol = lib.getExe pkgs.lxqt.pavucontrol-qt;
+
blueman-manager = "${pkgs.blueman}/bin/blueman-manager";
+
bluetoothctl = "${pkgs.bluez}/bin/bluetoothctl";
+
systemctl = "${pkgs.systemd}/bin/systemctl";
+
iwgtk = lib.getExe pkgs.iwgtk;
+
in {
+
backlightUp = "${slight} inc 5% -t 150ms";
+
backlightDown = "${slight} dec 5% -t 150ms";
+
# TODO --tab no longer works, what is the identifier to use?
+
outputSoundSettings = "${pavucontrol} --tab 'Output Devices'";
+
outputVolumeMute = "${kbFns} output mute";
+
outputVolumeUp = "${kbFns} output +0.05";
+
outputVolumeDown = "${kbFns} output -0.05";
+
# TODO --tab no longer works, what is the identifier to use?
+
inputSoundSettings = "${pavucontrol} --tab 'Input Devices'";
+
inputVolumeMute = "${kbFns} input mute";
+
# inputVolumeUp = "${kbFns} input +0.05";
+
# inputVolumeDown = "${kbFns} input -0.05";
+
bluetoothSettings = (pkgs.writeShellScript "waybar-bluetooth-settings" ''
+
set -eux
+
export PATH="${
+
lib.makeBinPath
+
(with pkgs; [ coreutils gawk util-linux bluez nettools blueman ])
+
}:$PATH"
+
is_powered_on="$(
+
bluetoothctl show | \
+
awk '/Name: '"$(hostname)"'$/{p=1} p && /Powered: yes/{print "true"; exit} END{if(!NR || !p) print "false"}'
+
)"
+
if [[ $is_powered_on == 'true' ]]; then
+
blueman-manager
+
else
+
rfkill unblock bluetooth && sleep 1 || true
+
bluetoothctl power on
+
sleep 0.5
+
blueman-manager
+
fi
+
'').outPath;
+
bluetoothToggle = (pkgs.writeShellScript "waybar-bluetooth-toggle" ''
+
set -eux
+
export PATH="${
+
lib.makeBinPath
+
(with pkgs; [ coreutils gawk util-linux bluez nettools ])
+
}:$PATH"
+
is_powered_on="$(
+
bluetoothctl show | \
+
awk '/Name: '"$(hostname)"'$/{p=1} p && /Powered: yes/{print "true"; exit} END{if(!NR || !p) print "false"}'
+
)"
+
if [[ $is_powered_on == 'true' ]]; then
+
bluetoothctl power off
+
else
+
rfkill unblock bluetooth && sleep 1 || true
+
bluetoothctl power on
+
fi
+
'').outPath;
+
bluetoothKill =
+
"rfkill block bluetooth && ${systemctl} restart bluetooth.service";
+
bluetoothOff = "${bluetoothctl} power off";
+
wirelessSettings = iwgtk;
+
workspaceSwitchPrev = "${hyprctl} dispatch workspace m-1";
+
workspaceSwitchNext = "${hyprctl} dispatch workspace m+1";
+
};
+
in {
+
programs.waybar.enable = true;
+
programs.waybar.package = package';
+
+
programs.waybar.systemd.enable = true;
+
+
programs.waybar.style =
+
builtins.readFile (compileSCSS "waybar-style" ./waybar.scss);
+
+
programs.waybar.settings = {
+
mainBar = {
+
layer = "top";
+
position = "top";
+
# Causes tooltips to be shown behind windows.
+
# mode = "dock";
+
height = 26;
+
+
modules-left = [ # #
+
"clock#time"
+
"clock#date"
+
# "wlr/workspaces"
+
"tray"
+
"mpris"
+
];
+
+
modules-center = [ # #
+
"hyprland/workspaces"
+
];
+
+
modules-right = [
+
"hyprland/submap"
+
"pulseaudio#output"
+
"pulseaudio#input"
+
"backlight"
+
"memory"
+
"cpu"
+
"temperature"
+
"battery"
+
"network"
+
"bluetooth"
+
"idle_inhibitor"
+
];
+
+
## MODULES-LEFT ##
+
+
# Hyprland dropped support unfortunately.
+
+
# "wlr/workspaces" = {
+
# sort-by-number = true;
+
+
# on-click = "activate";
+
# on-scroll-up = commands.workspaceSwitchPrev;
+
# on-scroll-down = commands.workspaceSwitchNext;
+
# };
+
+
"hyprland/workspaces" = {
+
format = "{name}";
+
# sort-by-number = true;
+
+
# on-click = "activate";
+
on-scroll-up = commands.workspaceSwitchPrev;
+
on-scroll-down = commands.workspaceSwitchNext;
+
};
+
+
tray = {
+
show-passive-items = true;
+
icon-size = 12;
+
spacing = 16;
+
};
+
+
mpris = {
+
player = "playerctld";
+
interval = 1;
+
+
format = "{status_icon} {dynamic}";
+
dynamic-len = 70;
+
dynamic-separator = " — ";
+
dynamic-order = [ "title" "artist" "position" "length" ];
+
dynamic-importance = [ "position" "title" "artist" ];
+
status-icons = {
+
playing = "󰐊";
+
paused = "󰏤";
+
stopped = "󰓛";
+
};
+
+
tooltip-format = lib.trim ''
+
<b>Player:</b> {player} ({status})
+
<b>Title:</b> {title}
+
<b>Artist:</b> {artist}
+
<b>Album:</b> {album}
+
<b>Length:</b> {position}/{length}
+
'';
+
};
+
+
"hyprland/submap" = {
+
format = "󰘳 {}";
+
tooltip = false;
+
};
+
+
"hyprland/window" = { max-length = 50; };
+
+
## MODULES-CENTER ##
+
+
"clock#time" = { format = "{:%I:%M %p}"; };
+
+
"clock#date" = { format = "{:%A, %B %d}"; };
+
+
## MODULES-RIGHT ##
+
+
"pulseaudio#output" = {
+
format = "{icon} {volume}%";
+
format-muted = "󰖁 {volume}%";
+
format-icons = {
+
headphone = "󰋋";
+
# speaker = "󰓃";
+
hdmi = "󰽟";
+
headset = "󰋎";
+
# hands-free = "󰋎";
+
# portable = "";
+
# car = "󰄋";
+
# hifi = "󰓃";
+
# phone = "󰏲";
+
default = [ "󰕿" "󰖀" "󰕾" ];
+
};
+
+
# anything below 100% is "safe" volume levels,
+
# the default style will be used,
+
# anything higher than this will have no CSS class,
+
# that will be considered "warning" state
+
# `#pulseaudio.output:not(.safe)`
+
states = { safe = 100; };
+
+
ignored-sinks = [ "Easy Effects Sink" ];
+
+
on-click = commands.outputSoundSettings;
+
on-click-right = commands.outputVolumeMute;
+
on-scroll-up = commands.outputVolumeUp;
+
on-scroll-down = commands.outputVolumeDown;
+
};
+
+
# TODO volume
+
"pulseaudio#input" = {
+
format = "{format_source}";
+
# format-source = "󰍬 {volume}%";
+
# format-source-muted = "󰍭 {volume}%";
+
format-source = "󰍬";
+
format-source-muted = "󰍭";
+
+
on-click = commands.inputSoundSettings;
+
on-click-right = commands.inputVolumeMute;
+
# on-scroll-up = commands.inputVolumeUp;
+
# on-scroll-down = commands.inputVolumeDown;
+
};
+
+
backlight = {
+
device = "amdgpu_bl0";
+
format = "{icon} {percent}%";
+
# format-icons = ["󰃜" "󰃛" "󰃝" "󰃟" "󰃠"];
+
format-icons = [ "󱩎" "󱩏" "󱩐" "󱩑" "󱩒" "󱩓" "󱩔" "󱩕" "󱩖" "󰛨" ];
+
+
on-scroll-up = commands.backlightUp;
+
on-scroll-down = commands.backlightDown;
+
};
+
+
memory = {
+
interval = 10;
+
format = "󰆼 {used:.2g}/{total:.2g}GiB";
+
};
+
+
cpu = {
+
interval = 5;
+
format = "󰘚 {usage}%";
+
};
+
+
temperature = {
+
interval = 5;
+
hwmon-path-abs = "/sys/devices/pci0000:00/0000:00:18.3/hwmon";
+
input-filename = "temp1_input";
+
critical-threshold =
+
90; # 15C lower than Tjmax <https://www.amd.com/en/product/9686>
+
format = "{icon} {temperatureC}°C";
+
format-critical = "󰈸 {temperatureC}°C";
+
# 4x low, 2x mid, 3x high, for 0-90
+
format-icons = [ "󱃃" "󱃃" "󱃃" "󱃃" "󰔏" "󰔏" "󱃂" "󱃂" "󱃂" ];
+
};
+
+
network = let
+
tooltip = ''
+
<b>Address:</b> {ipaddr}
+
<b>Netmask:</b> {netmask}
+
<b>Gateway:</b> {gwaddr}
+
<b>Speeds:</b> {bandwidthUpBytes} UL, {bandwidthDownBytes} DL
+
'';
+
in {
+
format-ethernet = "󰈀 {bandwidthDownBytes}";
+
format-wifi = "{icon} {bandwidthDownBytes}";
+
format-linked = "󱫱 {bandwidthDownBytes}";
+
format-disconnected = "󰲛";
+
format-icons = [ "󰤟" "󰤢" "󰤥" "󰤨" ];
+
+
tooltip-format = lib.trim ''
+
<b>Interface</b>: {ifname}
+
${tooltip}
+
'';
+
tooltip-format-wifi = lib.trim ''
+
<b>SSID:</b> {essid}
+
<b>Strength:</b> {signaldBm} dBmW ({signalStrength}%)
+
<b>Frequency:</b> {frequency} GHz
+
${tooltip}
+
'';
+
tooltip-format-disconnected = "Network disconnected.";
+
+
on-click = commands.wirelessSettings;
+
};
+
+
bluetooth = {
+
controller = "C0:3C:59:02:25:C3";
+
format-on = "󰂯";
+
format-off = "󰂲";
+
format-disabled = "󰂲";
+
format-connected = "󰂱 {num_connections}";
+
format-connected-battery =
+
"󰂱 {device_alias} ({device_battery_percentage}%) ({num_connections})";
+
+
on-click = commands.bluetoothSettings;
+
on-click-middle = commands.bluetoothKill;
+
on-click-right = commands.bluetoothToggle;
+
};
+
+
battery = {
+
interval = 5;
+
bat = "BAT0";
+
# full-at = 94;
+
format = "{icon} {capacity}%";
+
format-icons = [ "󰁺" "󰁻" "󰁼" "󰁽" "󰁾" "󰁿" "󰂀" "󰂁" "󰂂" "󰁹" ];
+
states = {
+
battery-10 = 10;
+
battery-20 = 20;
+
battery-30 = 30;
+
battery-40 = 40;
+
battery-50 = 50;
+
battery-60 = 60;
+
battery-70 = 70;
+
battery-80 = 80;
+
battery-90 = 90;
+
battery-100 = 100;
+
};
+
# <https://github.com/Alexays/Waybar/issues/1938>
+
# the wiki lies about this, does not match
+
# /sys/class/power_supply/BAT0/status
+
format-plugged = "󰚥 AC";
+
format-charging-battery-10 = "󰢜 {capacity}%";
+
format-charging-battery-20 = "󰂆 {capacity}%";
+
format-charging-battery-30 = "󰂇 {capacity}%";
+
format-charging-battery-40 = "󰂈 {capacity}%";
+
format-charging-battery-50 = "󰢝 {capacity}%";
+
format-charging-battery-60 = "󰂉 {capacity}%";
+
format-charging-battery-70 = "󰢞 {capacity}%";
+
format-charging-battery-80 = "󰂊 {capacity}%";
+
format-charging-battery-90 = "󰂋 {capacity}%";
+
format-charging-battery-100 = "󰂅 {capacity}%";
+
};
+
+
idle_inhibitor = {
+
format = "{icon}";
+
format-icons = {
+
activated = "󰈈";
+
deactivated = "󱎫";
+
};
+
tooltip-format-activated =
+
"Idle timer inhibited, device will not sleep.";
+
tooltip-format-deactivated =
+
"Idle timer enabled, device will sleep when not in use.";
+
};
+
};
+
};
+
+
imports = [
+
(lib.mkIf config.programs.waybar.systemd.enable {
+
xdg.configFile."waybar/config".onChange = lib.mkOverride 90 ''
+
if [ -z "''${_reloaded_waybar-}" ]; then
+
_reloaded_waybar=1
+
${pkgs.systemd}/bin/systemctl --user restart waybar.service
+
fi
+
'';
+
xdg.configFile."waybar/style.css".onChange = lib.mkOverride 90 ''
+
if [ -z "''${_reloaded_waybar-}" ]; then
+
_reloaded_waybar=1
+
${pkgs.systemd}/bin/systemctl --user restart waybar.service
+
fi
+
'';
+
})
+
];
+
}
+236
moonlark/hyprland/waybar.scss
···
+
$default-foreground: #ebdbb2;
+
$highlight-foreground: #fbf1c7;
+
+
* {
+
all: unset;
+
font-family: Ubuntu, "Material Design Icons";
+
font-size: 10.5pt;
+
color: $default-foreground;
+
}
+
+
@mixin oscillate-highlight($function, $stop, $background, $duration) {
+
$name: inline-#{unique-id()};
+
+
@keyframes #{$name} {
+
#{$stop} {
+
background: $background;
+
color: $highlight-foreground;
+
}
+
}
+
+
animation-name: $name;
+
animation-duration: $duration;
+
animation-iteration-count: infinite;
+
animation-timing-function: $function;
+
}
+
+
@mixin breathe-highlight($background, $duration) {
+
@include oscillate-highlight(ease-in-out, 50%, $background, $duration);
+
}
+
+
@mixin pulse-highlight($stop, $background, $duration) {
+
@include oscillate-highlight(ease-out, $stop, $background, $duration);
+
}
+
+
@mixin indicate-active($color, $selector) {
+
transition:
+
box-shadow 300ms ease-in,
+
background 300ms ease-in;
+
+
#{$selector} {
+
transition:
+
box-shadow 600ms ease-out,
+
background 600ms ease-out;
+
box-shadow: 0 2px 0 0 $color inset;
+
background: #3c3836;
+
}
+
}
+
+
@mixin indicate-hover($color) {
+
transition:
+
background 120ms ease-in;
+
+
&:hover {
+
transition:
+
background 120ms ease-out;
+
background: $color;
+
}
+
}
+
+
#clock,
+
#submap,
+
#backlight,
+
#network,
+
#bluetooth,
+
#cpu,
+
#temperature,
+
#pulseaudio,
+
#memory,
+
#battery,
+
#idle_inhibitor,
+
#tray,
+
#mpris,
+
#window {
+
padding-left: 8px;
+
padding-right: 8px;
+
}
+
+
window#waybar {
+
// background: #1d2021;
+
background: #000000;
+
// border-bottom: 1px solid #3c3836;
+
}
+
+
tooltip,
+
window.popup {
+
background: #282828;
+
border: 1px solid #665c54;
+
// border-radius: 3px;
+
}
+
+
window.popup {
+
menu {
+
padding: 5px 0;
+
+
arrow {
+
min-width: 16px;
+
min-height: 16px;
+
+
&.top {
+
-gtk-icon-source: -gtk-icontheme("pan-up-symbolic");
+
}
+
+
&.bottom {
+
-gtk-icon-source: -gtk-icontheme("pan-down-symbolic");
+
}
+
+
&.right {
+
-gtk-icon-source: -gtk-icontheme("pan-end-symbolic");
+
}
+
+
&.left {
+
-gtk-icon-source: -gtk-icontheme("pan-start-symbolic");
+
}
+
}
+
+
menuitem {
+
padding: 4px 8px;
+
+
transition:
+
color 66ms ease-in,
+
background 66ms ease-in;
+
+
&:hover {
+
transition:
+
color 100ms ease-out,
+
background 100ms ease-out;
+
+
color: $highlight-foreground;
+
background: #689d6a;
+
}
+
}
+
+
separator {
+
min-height: 1px;
+
background: #665c54;
+
margin: 4px 0;
+
}
+
}
+
}
+
+
#clock.time {
+
font-weight: bold;
+
}
+
+
#tray {
+
&>* {
+
@include indicate-hover(#282828);
+
}
+
}
+
+
#mpris {
+
@include indicate-hover(#282828);
+
}
+
+
#submap {
+
@include indicate-active(#d3869b, "&");
+
}
+
+
#workspaces {
+
button {
+
min-width: 26px;
+
padding: 6px;
+
+
@include indicate-hover(#282828);
+
@include indicate-active(#f38019, "&.active");
+
+
&.urgent {
+
animation-delay: 5s;
+
@include pulse-highlight(10%, #458588, 1.5s);
+
}
+
}
+
}
+
+
#network {
+
@include indicate-hover(#282828);
+
@include indicate-active(#689d6a, "&.wifi");
+
@include indicate-active(#458588, "&.ethernet");
+
@include indicate-active(#b16286, "&.linked");
+
}
+
+
#bluetooth {
+
@include indicate-hover(#282828);
+
@include indicate-active(#458588, "&.on");
+
@include indicate-active(#98971a, "&.connected");
+
+
&.on {
+
@include breathe-highlight(#458588, 5s);
+
}
+
+
// &.discoverable {
+
// @include breathe-highlight(#b16286, 5s);
+
// }
+
+
// &.discovering {
+
// @include breathe-highlight(#b16286, 5s);
+
// }
+
+
// &.pairable:not(.connected) {
+
// @include breathe-highlight(#b16286, 5s);
+
// }
+
}
+
+
#battery {
+
&.battery-30:not(.charging) {
+
@include breathe-highlight(#d64d0e, 10s);
+
}
+
+
&.battery-20:not(.charging) {
+
@include pulse-highlight(10%, #d64d0e, 5s);
+
}
+
+
&.battery-10:not(.charging) {
+
@include pulse-highlight(30%, #cc241d, 750ms);
+
}
+
}
+
+
#temperature.critical {
+
@include pulse-highlight(30%, #cc241d, 750ms);
+
}
+
+
#idle_inhibitor {
+
@include indicate-hover(#282828);
+
@include indicate-active(#d79921, "&.activated");
+
+
&.activated {
+
@include pulse-highlight(10%, #d79921, 5s);
+
}
+
}
+
+
#pulseaudio {
+
@include indicate-hover(#282828);
+
+
&.output:not(.safe) {
+
@include breathe-highlight(#cc241d, 10s);
+
}
+
}
+132
moonlark/hyprland/windowrules.nix
···
+
# <https://wiki.hyprland.org/Configuring/Window-Rules/#window-rules-v2>
+
{ lib, ... }:
+
let
+
# I recommend using this factory function for creating window rules.
+
rule = rules: attrs: attrs // { inherit rules; };
+
in {
+
wayland.windowManager.hyprland.layerRules = [{
+
namespace = [ "rofi" "notification" ];
+
rules = [ "blur" "ignorezero" ];
+
}];
+
+
wayland.windowManager.hyprland.windowRules = let
+
### SYSTEM CONTROL ###
+
printerConfig.class = [ "system-config-printer" ];
+
audioControl.class = [ "pavucontrol-qt" ];
+
wifiControl.class = [ "org.twosheds.iwgtk" "iwgtk" ];
+
bluetoothControl = {
+
class = [ ".*blueman-manager.*" ];
+
title = [ "Bluetooth Devices" ];
+
};
+
kvantumConfig.class = [ "kvantummanager" ];
+
+
### SYSTEM MODALS ###
+
filePickerPortal = {
+
# I'm guessing that almost all portal interfaces are going to be modals
+
class =
+
[ "xdg-desktop-portal-gtk" "org.freedesktop.impl.portal.desktop.kde" ];
+
# title = ["Open Files.+Portal"];
+
};
+
polkitAgent.class = [ "lxqt-policykit-agent" ];
+
mountDialog.class = [ "udiskie" ];
+
+
### DESKTOP APPLICATIONS ###
+
vscode = {
+
title = [ ".*Visual Studio Code" ];
+
# class = ["code-url-handler"];
+
};
+
discord = {
+
class = [ "vesktop" "ArmCord" "WebCord" "discord" ];
+
title = [
+
"(\\[\\d+\\] )?Discord |.*"
+
".*ArmCord"
+
"(\\[\\d+\\] )?WebCord.*"
+
".*Discord"
+
];
+
};
+
tidal.class = [ "tidal-hifi" ];
+
calculator.class = [ "qalculate-gtk" ];
+
# obsStudio = {
+
# class = [ "com.obsproject.Studio" ];
+
# title = [ "OBS\\s[\\d\\.]+.*" ];
+
# };
+
steam = {
+
class = [ "Steam" ];
+
# title = ["Steam"];
+
};
+
minecraft = {
+
class = [ "Minecraft.+" ];
+
title = [ "Minecraft.+" ];
+
};
+
virtManagerConsole = {
+
class = [ "virt-manager" ];
+
title = [ ".+on.+" ];
+
};
+
+
### DESKTOP APPLICATION MODALS ###
+
discordModal = {
+
class = [ "WebCord" ];
+
title = [ "WebCord.+Settings" ];
+
};
+
tidalModal = {
+
class = [ "tidal-hifi" ];
+
title = [ "Tidal Hi-Fi settings" ];
+
};
+
keePassModal = {
+
class = [ "org.keepassxc.KeePassXC" ];
+
title = [
+
"Unlock Database.+KeePassXC"
+
"Generate Password"
+
"KeePassXC.+Browser Access Request"
+
];
+
};
+
firefoxModal = {
+
class = [ "firefox" ];
+
title = [ "Extension.+Mozilla Firefox.*" "Picture-in-Picture" ];
+
};
+
lxImageModal = {
+
class = [ "lximage-qt" ];
+
title = [ "Print" ];
+
};
+
fileZillaModal = {
+
class = [ "filezilla" ];
+
title = [ "Site Manager" ];
+
};
+
in lib.concatLists [
+
[
+
(rule [ "size 740 460" ] filePickerPortal)
+
(rule [ "size 950 700" ] kvantumConfig)
+
]
+
# Because it can be shown and hidden with a systray icon.
+
(map (rule [ "float" "pin" "move 10% 10%" "size 80% 80%" ]) [ tidal ])
+
#
+
(map (rule [ "idleinhibit focus" ]) [ minecraft virtManagerConsole ])
+
(map (rule [ "float" ]) [
+
kvantumConfig
+
keePassModal
+
lxImageModal
+
firefoxModal
+
fileZillaModal
+
discordModal
+
tidalModal
+
])
+
# Barely translucent
+
(map (rule [ "opacity 0.97 0.97" ]) [ ])
+
(map (rule [ "opacity 0.97 0.97" "float" ]) [
+
printerConfig
+
audioControl
+
bluetoothControl
+
polkitAgent
+
mountDialog
+
])
+
# More translucent
+
(map (rule [ "opacity 0.92 0.92" ]) [ vscode steam tidal discord ])
+
(map (rule [ "opacity 0.92 0.92" "float" ]) [
+
filePickerPortal
+
wifiControl
+
])
+
# Super translucent
+
(map (rule [ "opacity 0.87 0.87" ]) [ ])
+
(map (rule [ "opacity 0.87 0.87" "float" ]) [ calculator ])
+
];
+
}