aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rwxr-xr-xconfig/hypr/UserScripts/Tak0-Autodispatch.sh62
-rwxr-xr-xconfig/hypr/scripts/Tak0-Autodispatch.sh226
-rwxr-xr-xconfig/hypr/scripts/Tak0-Per-Window-Switch.sh6
3 files changed, 85 insertions, 209 deletions
diff --git a/config/hypr/UserScripts/Tak0-Autodispatch.sh b/config/hypr/UserScripts/Tak0-Autodispatch.sh
index 114a3e8e..48c22515 100755
--- a/config/hypr/UserScripts/Tak0-Autodispatch.sh
+++ b/config/hypr/UserScripts/Tak0-Autodispatch.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# USAGE / ІНСТРУКЦІЯ:
+# USAGE:
# 1) Run from terminal:
# ./dispatch.sh <application_command> <target_workspace_number>
# Example:
@@ -14,77 +14,49 @@
# Notes:
# - Script waits about ~9 seconds (30 iterations of 0.3 sec) for window to appear.
# - Uses hyprctl and jq, so these tools must be installed.
-#
-# USAGE / ІНСТРУКЦІЯ:
-# 1) Запуск з терміналу:
-# ./dispatch.sh <application_command> <target_workspace_number>
-# Наприклад:
-# ./dispatch.sh discord 2
-#
-# 2) Виклик з конфігурації Hyprland (у файлі hyprland.conf):
-# exec-once = /path/to/dispatch.sh <application_command> <target_workspace_number>
-#
-# Логи зберігаються у файлі dispatch.log поруч зі скриптом.
-# Якщо вікно не з'явилось або неправильно диспатчилось — інформація там.
-#
-# Примітки:
-# - Скрипт чекає до ~9 секунд (30 ітерацій по 0.3 сек) поки вікно з'явиться.
-# - Використовує hyprctl і jq, тому ці інструменти мають бути встановлені.
LOGFILE="$(dirname "$0")/dispatch.log"
# Log file path located next to the script.
-# Файл логів розташований поруч зі скриптом.
APP=$1
# The application command or window class to launch or match.
-# Команда для запуску аплікації або клас вікна для пошуку.
TARGET_WORKSPACE=$2
# The target workspace number where the window should be moved.
-# Цільовий номер воркспейсу, куди потрібно перемістити вікно.
# Check if required arguments are provided.
-# Перевірка наявності необхідних параметрів.
if [[ -z "$APP" || -z "$TARGET_WORKSPACE" ]]; then
- echo "Usage: $0 <application_command> <target_workspace_number>" >> "$LOGFILE" 2>&1
- exit 1
+ echo "Usage: $0 <application_command> <target_workspace_number>" >>"$LOGFILE" 2>&1
+ exit 1
fi
-echo "Starting dispatch of '$APP' to workspace $TARGET_WORKSPACE at $(date)" >> "$LOGFILE"
+echo "Starting dispatch of '$APP' to workspace $TARGET_WORKSPACE at $(date)" >>"$LOGFILE"
# Starting the dispatch process and logging the event.
-# Початок процесу диспатчу, запис у лог.
-
# Avoid early workspace focus issues by switching workspace first.
-# Уникаємо проблем з раннім фокусом, спочатку переключаємо воркспейс.
-hyprctl dispatch workspace "$TARGET_WORKSPACE" >> "$LOGFILE" 2>&1
+hyprctl dispatch workspace "$TARGET_WORKSPACE" >>"$LOGFILE" 2>&1
sleep 0.4
# Launch the application in the background and disown it.
-# Запускаємо аплікацію у фоновому режимі та відв’язуємо від терміналу.
-$APP & disown
+$APP &
+disown
pid=$!
-echo "Launched '$APP' with PID $pid" >> "$LOGFILE"
+echo "Launched '$APP' with PID $pid" >>"$LOGFILE"
# Log the launched process ID.
-# Лог процесу запуску з PID.
-
# Wait for the application window to appear (matching window class).
-# Чекаємо появи вікна аплікації (за класом вікна).
for i in {1..30}; do
- win=$(hyprctl clients -j | jq -r --arg APP "$APP" '
+ win=$(hyprctl clients -j | jq -r --arg APP "$APP" '
.[] | select(.class | test($APP;"i")) | .address' 2>>"$LOGFILE")
- if [[ -n "$win" ]]; then
- echo "Found window $win for app '$APP', moving to workspace $TARGET_WORKSPACE" >> "$LOGFILE"
- # Move the window to the target workspace.
- # Переміщаємо вікно на цільовий воркспейс.
- hyprctl dispatch movetoworkspace "$TARGET_WORKSPACE,address:$win" >> "$LOGFILE" 2>&1
- exit 0
- fi
- sleep 0.3
+ if [[ -n "$win" ]]; then
+ echo "Found window $win for app '$APP', moving to workspace $TARGET_WORKSPACE" >>"$LOGFILE"
+ # Move the window to the target workspace.
+ hyprctl dispatch movetoworkspace "$TARGET_WORKSPACE,address:$win" >>"$LOGFILE" 2>&1
+ exit 0
+ fi
+ sleep 0.3
done
-echo "ERROR: Window for '$APP' was NOT found or dispatched properly to workspace $TARGET_WORKSPACE at $(date)" >> "$LOGFILE"
+echo "ERROR: Window for '$APP' was NOT found or dispatched properly to workspace $TARGET_WORKSPACE at $(date)" >>"$LOGFILE"
# Log error if window was not found or dispatched correctly.
-# Запис помилки, якщо вікно не знайдено або неправильно диспатчено.
exit 1
diff --git a/config/hypr/scripts/Tak0-Autodispatch.sh b/config/hypr/scripts/Tak0-Autodispatch.sh
index 0f81a6a3..6ed7ec13 100755
--- a/config/hypr/scripts/Tak0-Autodispatch.sh
+++ b/config/hypr/scripts/Tak0-Autodispatch.sh
@@ -1,11 +1,8 @@
#!/usr/bin/env bash
-#
+
# ─────────────────────────────────────────────────────────────────────────────
# Tak0-Autodispatch.sh
# ─────────────────────────────────────────────────────────────────────────────
-#
-# 🇬🇧 ENGLISH
-# -----------------------------------------------------------------------------
# This script is an "authoritative spawn dispatcher" for Hyprland.
#
# Its purpose is to FORCE all windows belonging to a single application launch
@@ -29,41 +26,11 @@
# Important notes:
# • All window rules are TEMPORARY
# • No permanent pollution of Hyprland configuration
-#
-# -----------------------------------------------------------------------------
-# 🇺🇦 УКРАЇНСЬКА
-# -----------------------------------------------------------------------------
-# Цей скрипт — це "авторитарний диспетчер запуску" для Hyprland.
-#
-# Його задача — ГАРАНТОВАНО відправити ВСІ вікна одного запуску програми
-# (основне вікно + helper-и + Electron / Steam дочірні процеси)
-# на вказаний workspace.
-#
-# Скрипту байдуже на:
-# • race conditions
-# • затримки створення вікон
-# • відʼєднані helper-процеси
-# • Electron / Chromium / Steam безумство
-#
-# Типові сценарії використання:
-# • Запуск Steam / Discord / браузерів без витоку вікон
-# • Заборона спавну на поточному workspace
-# • Контроль програм, які ігнорують static windowrules
-#
-# Запуск:
-# ./Tak0-Autodispatch.sh <workspace> [rule ...] -- <command>
-#
-# Важливо:
-# • Всі rules — тимчасові
-# • Глобальна конфігурація Hyprland НЕ псується
-#
# ─────────────────────────────────────────────────────────────────────────────
-#
-# REQUIREMENTS / ВИМОГИ:
+# REQUIREMENTS:
# - hyprctl → runtime control of Hyprland
# - jq → JSON client parsing
# - pgrep/ps → process tree inspection
-#
set -u
@@ -72,38 +39,29 @@ LOGFILE="$(dirname "$0")/dispatch.log"
# ─────────────────────────────────────────────────────────────────────────────
# 0️⃣ ARGUMENT PARSING
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# $1 → target workspace
# Next args → optional capture rules (windowrulev2 syntax)
# "--" → argument separator
# After "--" → command to execute (verbatim)
-#
-# UA:
-# $1 → цільовий workspace
-# Далі → capture rules (сумісні з windowrulev2)
-# "--" → роздільник аргументів
-# Після "--" → команда запуску (як є)
-#
TARGET_WS="$1"
shift || true
CAPTURE_RULES=()
while [[ "${1-}" != "--" && -n "${1-}" ]]; do
- CAPTURE_RULES+=("$1")
- shift || break
+ CAPTURE_RULES+=("$1")
+ shift || break
done
if [[ "${1-}" == "--" ]]; then
- shift
+ shift
fi
CMD="$*"
if [[ -z "$TARGET_WS" || -z "$CMD" ]]; then
- echo "Usage: $0 <workspace> [rule rule ...] -- <command>" >>"$LOGFILE"
- exit 1
+ echo "Usage: $0 <workspace> [rule rule ...] -- <command>" >>"$LOGFILE"
+ exit 1
fi
echo "=== Deploy '$CMD' → WS $TARGET_WS @ $(date) ===" >>"$LOGFILE"
@@ -111,43 +69,28 @@ echo "=== Deploy '$CMD' → WS $TARGET_WS @ $(date) ===" >>"$LOGFILE"
# ─────────────────────────────────────────────────────────────────────────────
# 1️⃣ HYPRLAND READINESS GATE
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# Hyprland may not be fully initialized during early autostart.
# hyprctl silently fails if called too early.
-#
-# UA:
-# Під час раннього автозапуску Hyprland може бути ще не готовий.
-# hyprctl у такому випадку тихо фейлиться.
-#
for _ in {1..50}; do
- hyprctl -j monitors >/dev/null 2>&1 && break
- sleep 0.1
+ hyprctl -j monitors >/dev/null 2>&1 && break
+ sleep 0.1
done
# ─────────────────────────────────────────────────────────────────────────────
# 2️⃣ CLEANUP GUARANTEE
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# Ensures that ALL temporary rules are removed
# even on crash, SIGTERM, or user interruption.
-#
-# UA:
-# Гарантує прибирання ВСІХ тимчасових правил
-# навіть у разі крешу, SIGTERM або Ctrl+C.
-#
cleanup() {
- echo "Cleanup: removing temporary capture rules and initialWorkspace at $(date)" >>"$LOGFILE"
-
- hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+ echo "Cleanup: removing temporary capture rules and initialWorkspace at $(date)" >>"$LOGFILE"
- for RULE in "${CAPTURE_RULES[@]}"; do
- echo "Cleanup: removing temporary capture rule: $RULE" >>"$LOGFILE"
- hyprctl keyword windowrulev2 "unset, $RULE" >>"$LOGFILE" 2>&1 || true
- done
+ hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
+ for RULE in "${CAPTURE_RULES[@]}"; do
+ echo "Cleanup: removing temporary capture rule: $RULE" >>"$LOGFILE"
+ hyprctl keyword windowrulev2 "unset, $RULE" >>"$LOGFILE" 2>&1 || true
+ done
}
trap cleanup EXIT INT TERM ERR
@@ -155,8 +98,6 @@ trap cleanup EXIT INT TERM ERR
# ─────────────────────────────────────────────────────────────────────────────
# 3️⃣ ULTRA-EARLY GLOBAL CAPTURE (NUCLEAR OPTION)
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# Temporarily forces ALL windows (initialClass:.*)
# onto the target workspace.
#
@@ -164,51 +105,30 @@ trap cleanup EXIT INT TERM ERR
# • gpu-process
# • renderer
# • steamwebhelper
-#
-# UA:
-# Тимчасово заганяє АБСОЛЮТНО всі вікна
-# на цільовий workspace.
-#
-# Рятує від ультрашвидких helper-ів.
-#
echo "Applying temporary initialWorkspace capture (initialClass:.*)" >>"$LOGFILE"
hyprctl keyword windowrulev2 \
- "initialWorkspace $TARGET_WS silent, initialClass:.*" \
- >>"$LOGFILE" 2>&1 || true
+ "initialWorkspace $TARGET_WS silent, initialClass:.*" \
+ >>"$LOGFILE" 2>&1 || true
# ─────────────────────────────────────────────────────────────────────────────
# 3️⃣.1 OPTIONAL CLASS-BASED PRE-CAPTURE
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# Additional precision rules.
# Useful for Electron / Steam multi-process hell.
-#
-# UA:
-# Додаткові class-based правила.
-# Підвищують точність для Electron / Steam.
-#
for RULE in "${CAPTURE_RULES[@]}"; do
- echo "Applying temporary capture rule: $RULE" >>"$LOGFILE"
- hyprctl keyword windowrulev2 \
- "initialWorkspace $TARGET_WS silent, $RULE" \
- >>"$LOGFILE" 2>&1 || true
+ echo "Applying temporary capture rule: $RULE" >>"$LOGFILE"
+ hyprctl keyword windowrulev2 \
+ "initialWorkspace $TARGET_WS silent, $RULE" \
+ >>"$LOGFILE" 2>&1 || true
done
# ─────────────────────────────────────────────────────────────────────────────
# 4️⃣ APPLICATION LAUNCH
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# bash -c allows aliases, env vars, wrappers.
# ROOT_PID is the root of process lineage.
-#
-# UA:
-# bash -c дозволяє aliases, env vars та wrappers.
-# ROOT_PID — корінь дерева процесів.
-#
bash -c "$CMD" &
ROOT_PID=$!
@@ -217,102 +137,92 @@ echo "Root PID: $ROOT_PID" >>"$LOGFILE"
# Resolve canonical process name
APP_NAME=""
for _ in {1..20}; do
- if [[ -r "/proc/$ROOT_PID/comm" ]]; then
- APP_NAME="$(tr -d '\0' < /proc/$ROOT_PID/comm 2>/dev/null || true)"
- break
- fi
- sleep 0.05
+ if [[ -r "/proc/$ROOT_PID/comm" ]]; then
+ APP_NAME="$(tr -d '\0' </proc/$ROOT_PID/comm 2>/dev/null || true)"
+ break
+ fi
+ sleep 0.05
done
if [[ -z "$APP_NAME" ]]; then
- read -r -a __toks <<< "$CMD"
- APP_NAME="$(basename "${__toks[0]}")"
+ read -r -a __toks <<<"$CMD"
+ APP_NAME="$(basename "${__toks[0]}")"
fi
echo "App gate name: $APP_NAME" >>"$LOGFILE"
sleep 1.5
-# Release the nuclear option ASAP
+#!TO-DO: Release the nuclear option ASAP
echo "Releasing ultra-early wide capture" >>"$LOGFILE"
hyprctl keyword windowrulev2 "unset, initialClass:.*" >>"$LOGFILE" 2>&1 || true
# ─────────────────────────────────────────────────────────────────────────────
# 5️⃣ SUPERVISION LOOP (AUTHORITATIVE PHASE)
# ─────────────────────────────────────────────────────────────────────────────
-#
-# EN:
# This loop:
# • scans ALL Hyprland clients
# • matches PID lineage
# • matches detached helpers
# • matches class rules
-#
-# UA:
-# Цей цикл:
-# • читає ВСІ клієнти Hyprland
-# • звіряє PID дерево
-# • ловить відʼєднані helper-и
-# • застосовує class fallback
-#
get_descendants() {
- local root="$1"
- local all=("$root")
- local changed=1
+ local root="$1"
+ local all=("$root")
+ local changed=1
- while (( changed )); do
- changed=0
- for p in "${all[@]}"; do
- for c in $(pgrep -P "$p" 2>/dev/null || true); do
- if [[ ! " ${all[*]} " =~ " $c " ]]; then
- all+=("$c")
- changed=1
- fi
- done
- done
+ while ((changed)); do
+ changed=0
+ for p in "${all[@]}"; do
+ for c in $(pgrep -P "$p" 2>/dev/null || true); do
+ if [[ ! " ${all[*]} " =~ " $c " ]]; then
+ all+=("$c")
+ changed=1
+ fi
+ done
done
+ done
- echo "${all[@]}"
+ echo "${all[@]}"
}
pid_matches_app() {
- local pid="$1"
- local comm
- comm="$(ps -p "$pid" -o comm= 2>/dev/null)" || return 1
- [[ "$comm" == "$APP_NAME" || "$comm" == "$APP_NAME"* ]]
+ local pid="$1"
+ local comm
+ comm="$(ps -p "$pid" -o comm= 2>/dev/null)" || return 1
+ [[ "$comm" == "$APP_NAME" || "$comm" == "$APP_NAME"* ]]
}
END_TIME=$((SECONDS + 20))
declare -A SEEN
-while (( SECONDS < END_TIME )); do
- PIDS="$(get_descendants "$ROOT_PID")"
+while ((SECONDS < END_TIME)); do
+ PIDS="$(get_descendants "$ROOT_PID")"
- while IFS=$'\t' read -r PID ADDR CLASS; do
- MATCH=0
+ while IFS=$'\t' read -r PID ADDR CLASS; do
+ MATCH=0
- for TPID in $PIDS; do
- [[ "$PID" == "$TPID" ]] && MATCH=1 && break
- done
+ for TPID in $PIDS; do
+ [[ "$PID" == "$TPID" ]] && MATCH=1 && break
+ done
- pid_matches_app "$PID" && MATCH=1
+ pid_matches_app "$PID" && MATCH=1
- for RULE in "${CAPTURE_RULES[@]}"; do
- if [[ "$RULE" =~ class:\^\((.*)\)\$ ]]; then
- [[ "$CLASS" =~ ${BASH_REMATCH[1]} ]] && MATCH=1
- fi
- done
+ for RULE in "${CAPTURE_RULES[@]}"; do
+ if [[ "$RULE" =~ class:\^\((.*)\)\$ ]]; then
+ [[ "$CLASS" =~ ${BASH_REMATCH[1]} ]] && MATCH=1
+ fi
+ done
- if (( MATCH )) && [[ -z "${SEEN[$ADDR]-}" ]]; then
- echo "Placing window $ADDR (pid $PID, class $CLASS) → WS $TARGET_WS" >>"$LOGFILE"
- hyprctl dispatch movetoworkspacesilent \
- "$TARGET_WS,address:$ADDR" >>"$LOGFILE" 2>&1 || true
- SEEN[$ADDR]=1
- fi
- done < <(hyprctl clients -j | jq -r '.[] | [.pid, .address, .class] | @tsv')
+ if ((MATCH)) && [[ -z "${SEEN[$ADDR]-}" ]]; then
+ echo "Placing window $ADDR (pid $PID, class $CLASS) → WS $TARGET_WS" >>"$LOGFILE"
+ hyprctl dispatch movetoworkspacesilent \
+ "$TARGET_WS,address:$ADDR" >>"$LOGFILE" 2>&1 || true
+ SEEN[$ADDR]=1
+ fi
+ done < <(hyprctl clients -j | jq -r '.[] | [.pid, .address, .class] | @tsv')
- sleep 0.01
+ sleep 0.01
done
echo "=== Deploy finished: '$CMD' ===" >>"$LOGFILE"
diff --git a/config/hypr/scripts/Tak0-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
index 7cec89a6..d652f0f7 100755
--- a/config/hypr/scripts/Tak0-Per-Window-Switch.sh
+++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
@@ -1,16 +1,10 @@
##################################################################
-# #
-# #
# TAK_0'S Per-Window-Switch #
# #
-# #
-# #
# Just a little script that I made to switch keyboard layouts #
# per-window instead of global switching for the more #
# smooth and comfortable workflow. #
-# #
##################################################################
-
# This is for changing kb_layouts. Set kb_layouts in
MAP_FILE="$HOME/.cache/kb_layout_per_window"
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage