From 6ce385c2be62492d43ef90b9525d38edc7cd8190 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 24 Jan 2026 18:37:14 -0600 Subject: feat(archsetup): add Hyprland/Wayland desktop environment support - Add DESKTOP_ENV config variable (dwm/hyprland/none, default: hyprland) - Create wayland() and hyprland() installation functions - Add display_server/window_manager conditional step wrappers - Create dotfiles/hyprland/ with full config suite: - hyprland.conf with keybindings translated from DWM + sxhkd - waybar config matching conky status bar - hypridle/hyprlock for screen locking - wofi config matching rofi theme - gammastep config for Wayland (replaces redshift) - Add Hyprland validation tests to validation.sh - Update archsetup.conf.example with DESKTOP_ENV option --- dotfiles/hyprland/.config/gammastep/config.ini | 25 +++ dotfiles/hyprland/.config/hypr/hypridle.conf | 34 +++ dotfiles/hyprland/.config/hypr/hyprland.conf | 287 +++++++++++++++++++++++++ dotfiles/hyprland/.config/hypr/hyprlock.conf | 75 +++++++ dotfiles/hyprland/.config/waybar/config | 50 +++++ dotfiles/hyprland/.config/waybar/style.css | 68 ++++++ dotfiles/hyprland/.config/wofi/config | 12 ++ dotfiles/hyprland/.config/wofi/style.css | 59 +++++ 8 files changed, 610 insertions(+) create mode 100644 dotfiles/hyprland/.config/gammastep/config.ini create mode 100644 dotfiles/hyprland/.config/hypr/hypridle.conf create mode 100644 dotfiles/hyprland/.config/hypr/hyprland.conf create mode 100644 dotfiles/hyprland/.config/hypr/hyprlock.conf create mode 100644 dotfiles/hyprland/.config/waybar/config create mode 100644 dotfiles/hyprland/.config/waybar/style.css create mode 100644 dotfiles/hyprland/.config/wofi/config create mode 100644 dotfiles/hyprland/.config/wofi/style.css (limited to 'dotfiles/hyprland') diff --git a/dotfiles/hyprland/.config/gammastep/config.ini b/dotfiles/hyprland/.config/gammastep/config.ini new file mode 100644 index 0000000..f50a701 --- /dev/null +++ b/dotfiles/hyprland/.config/gammastep/config.ini @@ -0,0 +1,25 @@ +[gammastep] +; Color temperature in Kelvin (same as redshift) +temp-day=6500 +temp-night=4500 + +; Brightness (1.0 = full, 0.8 = 20% dimmed) +brightness-day=1.0 +brightness-night=1.0 + +; Gamma correction +gamma=1.0 + +; Fade between day/night +fade=1 + +; Wayland adjustment method (not randr) +adjustment-method=wayland + +; Location for sunrise/sunset calculation +location-provider=manual + +[manual] +; New Orleans, LA +lat=29.951065 +lon=-90.071533 diff --git a/dotfiles/hyprland/.config/hypr/hypridle.conf b/dotfiles/hyprland/.config/hypr/hypridle.conf new file mode 100644 index 0000000..681c741 --- /dev/null +++ b/dotfiles/hyprland/.config/hypr/hypridle.conf @@ -0,0 +1,34 @@ +# Hypridle configuration +# Replaces xautolock -time 5 -locker slock + +general { + lock_cmd = pidof hyprlock || hyprlock + before_sleep_cmd = loginctl lock-session + after_sleep_cmd = hyprctl dispatch dpms on +} + +# Screen dim after 4.5 minutes +listener { + timeout = 270 + on-timeout = brightnessctl -s set 10% + on-resume = brightnessctl -r +} + +# Lock screen after 5 minutes (matching xautolock -time 5) +listener { + timeout = 300 + on-timeout = loginctl lock-session +} + +# Turn off screen after 10 minutes +listener { + timeout = 600 + on-timeout = hyprctl dispatch dpms off + on-resume = hyprctl dispatch dpms on +} + +# Suspend after 30 minutes +listener { + timeout = 1800 + on-timeout = systemctl suspend +} diff --git a/dotfiles/hyprland/.config/hypr/hyprland.conf b/dotfiles/hyprland/.config/hypr/hyprland.conf new file mode 100644 index 0000000..ce45088 --- /dev/null +++ b/dotfiles/hyprland/.config/hypr/hyprland.conf @@ -0,0 +1,287 @@ +# Hyprland Configuration +# Translated from DWM config.def.h and sxhkdrc +# Craig Jennings + +# ============================================================================ +# Monitor Configuration +# ============================================================================ +monitor=,preferred,auto,auto + +# ============================================================================ +# Startup Applications +# ============================================================================ +exec-once = waybar +exec-once = swww-daemon && sleep 1 && swww img ~/pictures/wallpaper/dark-lion.jpg +exec-once = dunst +exec-once = hypridle +exec-once = gammastep +exec-once = nm-applet +exec-once = blueman-applet +exec-once = /usr/bin/gnome-keyring-daemon --start --components=pkcs11,secrets,ssh +exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP +exec-once = mpd +exec-once = signal-desktop --start-in-tray --ozone-platform=wayland +exec-once = protonmail-bridge --no-window +exec-once = insync start + +# ============================================================================ +# Environment Variables +# ============================================================================ +env = XCURSOR_SIZE,24 +env = XDG_CURRENT_DESKTOP,Hyprland +env = XDG_SESSION_TYPE,wayland +env = XDG_SESSION_DESKTOP,Hyprland +env = _JAVA_AWT_WM_NONREPARENTING,1 + +# ============================================================================ +# Appearance (matching DWM colors) +# ============================================================================ +# DWM colors: gray1=#222222, gray2=#444444, gray3=#bbbbbb, gray4=#eeeeee, cyan=#daa520 + +general { + gaps_in = 5 + gaps_out = 10 + border_size = 3 + col.active_border = rgba(daa520ff) + col.inactive_border = rgba(444444ff) + layout = master + resize_on_border = true +} + +decoration { + rounding = 0 + blur { + enabled = false + } + shadow { + enabled = false + } +} + +animations { + enabled = true + bezier = myBezier, 0.05, 0.9, 0.1, 1.05 + animation = windows, 1, 3, myBezier + animation = windowsOut, 1, 3, default, popin 80% + animation = fade, 1, 3, default + animation = workspaces, 1, 3, default +} + +# ============================================================================ +# Layout (master-stack like DWM tile) +# ============================================================================ +master { + new_status = slave + mfact = 0.55 +} + +dwindle { + pseudotile = true + preserve_split = true +} + +# ============================================================================ +# Input +# ============================================================================ +input { + kb_layout = us + kb_options = ctrl:nocaps + follow_mouse = 1 + touchpad { + natural_scroll = true + } +} + +# ============================================================================ +# Misc +# ============================================================================ +misc { + force_default_wallpaper = 0 + disable_hyprland_logo = true +} + +# ============================================================================ +# XWayland +# ============================================================================ +xwayland { + force_zero_scaling = true +} + +# ============================================================================ +# Window Rules +# ============================================================================ +# Floating windows (from DWM rules) +windowrulev2 = float, class:^(Gimp)$ +windowrulev2 = float, class:^(caffeine)$ +windowrulev2 = float, class:^(blueman-services)$ +windowrulev2 = float, class:^(Blueman-manager)$ +windowrulev2 = float, class:^(qalculate-gtk)$ +windowrulev2 = float, title:^(Event Tester)$ + +# ============================================================================ +# Key Bindings +# ============================================================================ +$mod = SUPER + +# Terminal and core apps (from DWM) +bind = $mod, T, exec, st +bind = $mod, E, exec, emacsclient -c -a "" || emacs +bind = $mod, W, exec, $BROWSER +bind = $mod, P, exec, wofi --show drun + +# From sxhkdrc +bind = $mod, SPACE, exec, wofi --show drun +bind = $mod SHIFT, S, exec, wofi --show ssh +bind = $mod SHIFT, W, exec, $ALTBROWSER +bind = CTRL ALT, W, exec, tor-browser +bind = CTRL ALT, F, exec, thunar +bind = $mod, V, exec, virtualbox +bind = $mod SHIFT, L, exec, calibre +bind = $mod SHIFT, R, exec, shortwave + +# Window management (from DWM) +bind = $mod, J, layoutmsg, cyclenext +bind = $mod, K, layoutmsg, cycleprev +bind = $mod SHIFT, J, layoutmsg, swapnext +bind = $mod SHIFT, K, layoutmsg, swapprev +bind = $mod, H, resizeactive, -50 0 +bind = $mod, L, resizeactive, 50 0 +bind = $mod, RETURN, layoutmsg, swapwithmaster +bind = $mod, G, centerwindow +bind = $mod, TAB, workspace, previous +bind = $mod SHIFT, C, killactive + +# Layouts (from DWM) +bind = $mod SHIFT, M, exec, hyprctl keyword general:layout master +bind = $mod SHIFT, T, exec, hyprctl keyword general:layout master +bind = $mod SHIFT, F, togglefloating +bind = $mod SHIFT, SPACE, togglefloating + +# Master layout adjustments +bind = $mod, I, layoutmsg, addmaster +bind = $mod, D, layoutmsg, removemaster + +# Gaps (from DWM) +bind = $mod, MINUS, exec, hyprctl keyword general:gaps_out $(( $(hyprctl getoption general:gaps_out -j | jq '.int') - 5 )) +bind = $mod, EQUAL, exec, hyprctl keyword general:gaps_out $(( $(hyprctl getoption general:gaps_out -j | jq '.int') + 5 )) +bind = $mod SHIFT, EQUAL, exec, hyprctl keyword general:gaps_out 10 + +# Toggle bar +bind = $mod, B, exec, killall -SIGUSR1 waybar + +# Fullscreen +bind = $mod, F11, fullscreen, 0 + +# Workspaces 1-9 (from DWM TAGKEYS) +bind = $mod, 1, workspace, 1 +bind = $mod, 2, workspace, 2 +bind = $mod, 3, workspace, 3 +bind = $mod, 4, workspace, 4 +bind = $mod, 5, workspace, 5 +bind = $mod, 6, workspace, 6 +bind = $mod, 7, workspace, 7 +bind = $mod, 8, workspace, 8 +bind = $mod, 9, workspace, 9 +bind = $mod, 0, workspace, 10 + +# Move window to workspace (from DWM tag) +bind = $mod SHIFT, 1, movetoworkspace, 1 +bind = $mod SHIFT, 2, movetoworkspace, 2 +bind = $mod SHIFT, 3, movetoworkspace, 3 +bind = $mod SHIFT, 4, movetoworkspace, 4 +bind = $mod SHIFT, 5, movetoworkspace, 5 +bind = $mod SHIFT, 6, movetoworkspace, 6 +bind = $mod SHIFT, 7, movetoworkspace, 7 +bind = $mod SHIFT, 8, movetoworkspace, 8 +bind = $mod SHIFT, 9, movetoworkspace, 9 +bind = $mod SHIFT, 0, movetoworkspace, 10 + +# Monitor focus (from DWM focusmon) +bind = $mod, COMMA, focusmonitor, -1 +bind = $mod, PERIOD, focusmonitor, +1 +bind = $mod SHIFT, COMMA, movewindow, mon:-1 +bind = $mod SHIFT, PERIOD, movewindow, mon:+1 + +# Scratchpads (from DWM togglescratch) +# Audio mixer (was MODKEY+a -> spaudio/pulsemixer) +bind = $mod, A, togglespecialworkspace, audio +bind = $mod, A, exec, [workspace special:audio] pgrep -x pulsemixer || st -n spaudio -e pulsemixer +windowrulev2 = float, class:^(st)$, title:^(spaudio)$ +windowrulev2 = size 60% 60%, class:^(st)$, title:^(spaudio)$ +windowrulev2 = center, class:^(st)$, title:^(spaudio)$ +windowrulev2 = workspace special:audio, class:^(st)$, title:^(spaudio)$ + +# System monitor (was MODKEY+m -> spmon/gotop) +bind = $mod, M, togglespecialworkspace, monitor +bind = $mod, M, exec, [workspace special:monitor] pgrep -x gotop || st -n spmon -e gotop +windowrulev2 = float, class:^(st)$, title:^(spmon)$ +windowrulev2 = size 60% 60%, class:^(st)$, title:^(spmon)$ +windowrulev2 = workspace special:monitor, class:^(st)$, title:^(spmon)$ + +# Music player (was MODKEY+slash -> spmp/ncmpcpp) +bind = $mod, SLASH, togglespecialworkspace, music +bind = $mod, SLASH, exec, [workspace special:music] pgrep -x ncmpcpp || st -n spmp -e ncmpcpp +windowrulev2 = float, class:^(st)$, title:^(spmp)$ +windowrulev2 = size 60% 60%, class:^(st)$, title:^(spmp)$ +windowrulev2 = workspace special:music, class:^(st)$, title:^(spmp)$ + +# Terminal scratchpad (was MODKEY+Shift+Return -> spterm/tmux) +bind = $mod SHIFT, RETURN, togglespecialworkspace, term +bind = $mod SHIFT, RETURN, exec, [workspace special:term] pgrep -f "st.*spterm" || st -n spterm -e tmux +windowrulev2 = float, class:^(st)$, title:^(spterm)$ +windowrulev2 = size 60% 60%, class:^(st)$, title:^(spterm)$ +windowrulev2 = workspace special:term, class:^(st)$, title:^(spterm)$ + +# File manager (was MODKEY+f -> spfm/ranger) +bind = $mod, F, togglespecialworkspace, files +bind = $mod, F, exec, [workspace special:files] pgrep -x ranger || st -n spfm -e ranger +windowrulev2 = float, class:^(st)$, title:^(spfm)$ +windowrulev2 = size 60% 60%, class:^(st)$, title:^(spfm)$ +windowrulev2 = workspace special:files, class:^(st)$, title:^(spfm)$ + +# Calculator (was MODKEY+x or MODKEY+c -> qalculate) +bind = $mod, X, exec, qalculate-gtk +bind = $mod, C, exec, qalculate-gtk + +# Htop (was MODKEY+Shift+h -> sptop/htop) +bind = $mod SHIFT, H, togglespecialworkspace, htop +bind = $mod SHIFT, H, exec, [workspace special:htop] pgrep -x htop || st -n sptop -e htop +windowrulev2 = float, class:^(st)$, title:^(sptop)$ +windowrulev2 = size 60% 60%, class:^(st)$, title:^(sptop)$ +windowrulev2 = workspace special:htop, class:^(st)$, title:^(sptop)$ + +# Media/hardware keys +bindel = , XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% +bindel = , XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% +bindl = , XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle +bindel = , XF86MonBrightnessUp, exec, brightnessctl s +10% +bindel = , XF86MonBrightnessDown, exec, brightnessctl s 10%- + +# Microphone toggle (from sxhkdrc) +bind = CTRL ALT, SPACE, exec, amixer set Capture toggle && amixer get Capture | grep '\[off\]' && notify-send "Microphone" "Muted" || notify-send "Microphone" "On" + +# Bluetooth (from DWM and sxhkdrc) +bind = $mod SHIFT, B, exec, blueman-manager + +# Screenshots (Wayland: grim + slurp instead of maim) +bind = $mod, S, exec, grim -g "$(slurp)" ~/pictures/screenshots/$(date +%Y.%m.%d-%H%M%S).png && notify-send "Screenshot" "Saved to ~/pictures/screenshots/" +bind = , Print, exec, grim ~/pictures/screenshots/$(date +%Y.%m.%d-%H%M%S).png && notify-send "Screenshot" "Full screen saved" + +# Color picker (Wayland: hyprpicker instead of xcolor) +# bind = $mod, C, exec, hyprpicker -a # conflicts with calculator, uncomment if needed + +# Lock screen (from sxhkdrc: super+Escape) +bind = $mod, ESCAPE, exec, hyprlock + +# Touchpad toggle +bind = $mod, F9, exec, toggle-touchpad + +# Exit/session (from DWM) +bind = $mod SHIFT, Q, exec, wofi --show dmenu --prompt "Exit?" -D dmenu/exit="0" < /dev/null && hyprctl dispatch exit +bind = $mod SHIFT, BACKSPACE, exit +bind = $mod SHIFT, ESCAPE, exec, hyprctl reload + +# Mouse bindings (from DWM buttons) +bindm = $mod, mouse:272, movewindow +bindm = $mod, mouse:273, resizewindow +bindm = $mod SHIFT, mouse:272, resizewindow diff --git a/dotfiles/hyprland/.config/hypr/hyprlock.conf b/dotfiles/hyprland/.config/hypr/hyprlock.conf new file mode 100644 index 0000000..b4dcfb8 --- /dev/null +++ b/dotfiles/hyprland/.config/hypr/hyprlock.conf @@ -0,0 +1,75 @@ +# Hyprlock configuration +# Matching DWM colors: gray1=#222222, accent=#daa520 + +general { + disable_loading_bar = false + hide_cursor = true + grace = 0 + no_fade_in = false +} + +background { + monitor = + path = screenshot + blur_passes = 3 + blur_size = 8 + noise = 0.0117 + contrast = 0.8916 + brightness = 0.8172 + vibrancy = 0.1696 + vibrancy_darkness = 0.0 +} + +input-field { + monitor = + size = 300, 50 + outline_thickness = 3 + dots_size = 0.33 + dots_spacing = 0.15 + dots_center = true + dots_rounding = -1 + outer_color = rgb(444444) + inner_color = rgb(222222) + font_color = rgb(bbbbbb) + fade_on_empty = true + fade_timeout = 1000 + placeholder_text = Password... + hide_input = false + rounding = 0 + check_color = rgb(daa520) + fail_color = rgb(d9534f) + fail_text = $FAIL ($ATTEMPTS) + fail_transition = 300 + capslock_color = rgb(f0ad4e) + numlock_color = -1 + bothlock_color = -1 + invert_numlock = false + swap_font_color = false + position = 0, -20 + halign = center + valign = center +} + +label { + monitor = + text = $TIME + text_align = center + color = rgb(bbbbbb) + font_size = 64 + font_family = FiraCode Nerd Font Mono + position = 0, 80 + halign = center + valign = center +} + +label { + monitor = + text = $USER + text_align = center + color = rgb(daa520) + font_size = 20 + font_family = FiraCode Nerd Font Mono + position = 0, -80 + halign = center + valign = center +} diff --git a/dotfiles/hyprland/.config/waybar/config b/dotfiles/hyprland/.config/waybar/config new file mode 100644 index 0000000..3b3a90f --- /dev/null +++ b/dotfiles/hyprland/.config/waybar/config @@ -0,0 +1,50 @@ +{ + "layer": "top", + "position": "top", + "height": 30, + "spacing": 4, + + "modules-left": ["hyprland/workspaces"], + "modules-center": ["hyprland/window"], + "modules-right": ["tray", "battery", "disk", "clock"], + + "hyprland/workspaces": { + "format": "{name}", + "on-click": "activate", + "sort-by-number": true + }, + + "hyprland/window": { + "format": "{}", + "max-length": 50 + }, + + "tray": { + "spacing": 10 + }, + + "battery": { + "bat": "BAT0", + "interval": 30, + "states": { + "warning": 30, + "critical": 15 + }, + "format": "󱊣 {capacity}% {icon}", + "format-charging": "󱊣 {capacity}% ", + "format-plugged": "󱊣 {capacity}% ", + "format-icons": ["", "", "", "", ""] + }, + + "disk": { + "interval": 30, + "format": " {used}/{total}", + "path": "/" + }, + + "clock": { + "interval": 30, + "format": " {:%a %B %d} 󰥔 {:%I:%M %p %Z}", + "tooltip-format": "{calendar}" + } +} diff --git a/dotfiles/hyprland/.config/waybar/style.css b/dotfiles/hyprland/.config/waybar/style.css new file mode 100644 index 0000000..9411b46 --- /dev/null +++ b/dotfiles/hyprland/.config/waybar/style.css @@ -0,0 +1,68 @@ +/* Waybar style - matching DWM colors */ +/* gray1=#222222, gray2=#444444, gray3=#bbbbbb, gray4=#eeeeee, accent=#daa520 */ + +* { + font-family: "FiraCode Nerd Font Mono", monospace; + font-size: 12px; + border: none; + border-radius: 0; + min-height: 0; +} + +window#waybar { + background-color: #222222; + color: #bbbbbb; +} + +#workspaces button { + padding: 0 8px; + color: #bbbbbb; + background-color: transparent; +} + +#workspaces button:hover { + background-color: #444444; +} + +#workspaces button.active { + color: #eeeeee; + background-color: #daa520; +} + +#workspaces button.urgent { + background-color: #900000; +} + +#window { + color: #bbbbbb; + padding: 0 10px; +} + +#clock, +#battery, +#disk, +#tray { + padding: 0 10px; + color: #bbbbbb; +} + +#battery.charging { + color: #daa520; +} + +#battery.warning:not(.charging) { + color: #f0ad4e; +} + +#battery.critical:not(.charging) { + color: #d9534f; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; + background-color: #daa520; +} diff --git a/dotfiles/hyprland/.config/wofi/config b/dotfiles/hyprland/.config/wofi/config new file mode 100644 index 0000000..c023353 --- /dev/null +++ b/dotfiles/hyprland/.config/wofi/config @@ -0,0 +1,12 @@ +show=drun +width=480 +height=400 +always_parse_args=true +show_all=false +print_command=true +layer=overlay +insensitive=true +prompt=Search +image_size=24 +columns=1 +allow_images=true diff --git a/dotfiles/hyprland/.config/wofi/style.css b/dotfiles/hyprland/.config/wofi/style.css new file mode 100644 index 0000000..84072bf --- /dev/null +++ b/dotfiles/hyprland/.config/wofi/style.css @@ -0,0 +1,59 @@ +/* Wofi style - matching rofi rounded-gray-dark theme */ +/* Colors: bg0=#383c4a, bg1=#2d303c, fg0=#cdd1dc, fg2=#969696 */ + +window { + margin: 0px; + border: 1px solid #2d303c; + border-radius: 10px; + background-color: rgba(56, 60, 74, 0.94); + font-family: "FiraCode Nerd Font Mono"; + font-size: 10pt; +} + +#input { + margin: 12px; + padding: 12px 20px; + border: 1px solid #2d303c; + border-radius: 6px; + background-color: #2d303c; + color: #cdd1dc; +} + +#input:focus { + border-color: #4a4e5c; +} + +#inner-box { + margin: 0px 12px 12px 12px; +} + +#outer-box { + margin: 0px; + padding: 0px; +} + +#scroll { + margin: 0px; +} + +#text { + margin: 0px; + padding: 8px 16px; + color: #cdd1dc; +} + +#entry { + border-radius: 6px; +} + +#entry:selected { + background-color: #2d303c; +} + +#entry:selected #text { + color: #ffffff; +} + +#img { + margin-right: 8px; +} -- cgit v1.2.3