From 46f16c406ccf363dd416436367f2f172be82002d Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Wed, 4 Feb 2026 01:41:00 -0800 Subject: [PATCH] Improve Hyprland scratchpads --- dotfiles/config/hypr/hyprland.conf | 34 ++++++++----- .../config/hypr/scripts/toggle-scratchpad.sh | 51 +++++++++++++++++++ 2 files changed, 71 insertions(+), 14 deletions(-) create mode 100755 dotfiles/config/hypr/scripts/toggle-scratchpad.sh diff --git a/dotfiles/config/hypr/hyprland.conf b/dotfiles/config/hypr/hyprland.conf index 33a94ffa..7a850c4e 100644 --- a/dotfiles/config/hypr/hyprland.conf +++ b/dotfiles/config/hypr/hyprland.conf @@ -196,10 +196,12 @@ windowrulev2 = float, title:^(Save File)$ windowrulev2 = float, title:^(Confirm)$ # Scratchpad windows - float and size +windowrulev2 = workspace special:htop silent, class:^(htop-scratch)$ windowrulev2 = float, class:^(htop-scratch)$ windowrulev2 = size 90% 90%, class:^(htop-scratch)$ windowrulev2 = center, class:^(htop-scratch)$ +windowrulev2 = workspace special:volume silent, class:^(pavucontrol)$ windowrulev2 = float, class:^(pavucontrol)$ windowrulev2 = size 90% 90%, class:^(pavucontrol)$ windowrulev2 = center, class:^(pavucontrol)$ @@ -209,23 +211,28 @@ windowrulev2 = float, class:^(spotify)$ windowrulev2 = size 90% 90%, class:^(spotify)$ windowrulev2 = center, class:^(spotify)$ +windowrulev2 = workspace special:element silent, class:^(Element)$ windowrulev2 = float, class:^(Element)$ windowrulev2 = size 90% 90%, class:^(Element)$ windowrulev2 = center, class:^(Element)$ +windowrulev2 = workspace special:slack silent, class:^(Slack)$ windowrulev2 = float, class:^(Slack)$ windowrulev2 = size 90% 90%, class:^(Slack)$ windowrulev2 = center, class:^(Slack)$ +windowrulev2 = workspace special:transmission silent, class:^(transmission-gtk)$ windowrulev2 = float, class:^(transmission-gtk)$ windowrulev2 = size 90% 90%, class:^(transmission-gtk)$ windowrulev2 = center, class:^(transmission-gtk)$ # Gmail and Messages (Chrome windows) +windowrulev2 = workspace special:gmail silent, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ windowrulev2 = float, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ windowrulev2 = center, class:^(google-chrome)$,title:^(.*@gmail.com.*Gmail.*)$ +windowrulev2 = workspace special:messages silent, class:^(google-chrome)$,title:^(Messages.*)$ windowrulev2 = float, class:^(google-chrome)$,title:^(Messages.*)$ windowrulev2 = size 90% 90%, class:^(google-chrome)$,title:^(Messages.*)$ windowrulev2 = center, class:^(google-chrome)$,title:^(Messages.*)$ @@ -264,14 +271,14 @@ bind = $modAlt, C, exec, ~/.config/hypr/scripts/raise-or-run.sh google-chrome go # SCRATCHPADS (Special Workspaces) # ----------------------------------------------------------------------------- # Toggle scratchpads -bind = $modAlt, E, togglespecialworkspace, element -bind = $modAlt, G, togglespecialworkspace, gmail -bind = $modAlt, H, togglespecialworkspace, htop -bind = $modAlt, M, togglespecialworkspace, messages -bind = $modAlt, K, togglespecialworkspace, slack -bind = $modAlt, S, togglespecialworkspace, spotify -bind = $modAlt, T, togglespecialworkspace, transmission -bind = $modAlt, V, togglespecialworkspace, volume +bind = $modAlt, E, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh element '^Element$' - element-desktop +bind = $modAlt, G, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh gmail '^google-chrome$' '.*@gmail.com.*Gmail.*' google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox +bind = $modAlt, H, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh htop '^htop-scratch$' - alacritty --class htop-scratch --title htop -e htop +bind = $modAlt, M, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh messages '^google-chrome$' '^Messages.*' google-chrome-stable --new-window https://messages.google.com/web/conversations +bind = $modAlt, K, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh slack '^Slack$' - slack +bind = $modAlt, S, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh spotify '^spotify$' - spotify +bind = $modAlt, T, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh transmission '^transmission-gtk$' - transmission-gtk +bind = $modAlt, V, exec, ~/.config/hypr/scripts/toggle-scratchpad.sh volume '^pavucontrol$' - pavucontrol # Move windows to scratchpads bind = $modAlt SHIFT, E, movetoworkspace, special:element @@ -534,16 +541,15 @@ bind = $mainMod, mouse_up, workspace, e-1 exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE exec-once = systemctl --user start hyprland-session.target -# Scratchpad applications (start in special workspaces) -exec-once = [workspace special:element silent] element-desktop -# Disabled autostarts +# Scratchpad applications (spawn on demand via keybinds) +# exec-once = [workspace special:element silent] element-desktop # exec-once = [workspace special:gmail silent] google-chrome-stable --new-window https://mail.google.com/mail/u/0/#inbox -exec-once = [workspace special:htop silent] alacritty --class htop-scratch --title htop -e htop +# exec-once = [workspace special:htop silent] alacritty --class htop-scratch --title htop -e htop # exec-once = [workspace special:messages silent] google-chrome-stable --new-window https://messages.google.com/web/conversations -exec-once = [workspace special:slack silent] slack +# exec-once = [workspace special:slack silent] slack # exec-once = [workspace special:spotify silent] spotify # exec-once = [workspace special:transmission silent] transmission-gtk -exec-once = [workspace special:volume silent] pavucontrol +# exec-once = [workspace special:volume silent] pavucontrol # Clipboard history daemon exec-once = wl-paste --type text --watch cliphist store diff --git a/dotfiles/config/hypr/scripts/toggle-scratchpad.sh b/dotfiles/config/hypr/scripts/toggle-scratchpad.sh new file mode 100755 index 00000000..118c696c --- /dev/null +++ b/dotfiles/config/hypr/scripts/toggle-scratchpad.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Toggle a named Hyprland scratchpad, spawning it if needed. +# Usage: toggle-scratchpad.sh + +set -euo pipefail + +if [ "$#" -lt 4 ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +NAME="$1" +shift +CLASS_REGEX="$1" +shift +TITLE_REGEX="$1" +shift +COMMAND=("$@") + +if [ "$CLASS_REGEX" = "-" ]; then + CLASS_REGEX="" +fi +if [ "$TITLE_REGEX" = "-" ]; then + TITLE_REGEX="" +fi + +if [ -z "$CLASS_REGEX" ] && [ -z "$TITLE_REGEX" ]; then + echo "toggle-scratchpad: provide a class or title regex" >&2 + exit 1 +fi + +MATCHING=$(hyprctl clients -j | jq -r --arg cre "$CLASS_REGEX" --arg tre "$TITLE_REGEX" ' + .[] + | select( + (($cre == "") or (.class | test($cre; "i"))) + and + (($tre == "") or (.title | test($tre; "i"))) + ) + | .address +') + +if [ -z "$MATCHING" ]; then + "${COMMAND[@]}" & +else + while IFS= read -r ADDR; do + [ -n "$ADDR" ] || continue + hyprctl dispatch movetoworkspacesilent "special:$NAME,address:$ADDR" + done <<< "$MATCHING" +fi + +hyprctl dispatch togglespecialworkspace "$NAME"