diff options
| author | tak0dan <tmtroshko@gmail.com> | 2025-07-26 17:20:35 +0200 |
|---|---|---|
| committer | tak0dan <tmtroshko@gmail.com> | 2025-07-26 17:31:14 +0200 |
| commit | a2651ce31761301b5ac9c1c5915ef16c3f13ce6f (patch) | |
| tree | b29dc5737f550b119a853eadd29f207615f2c8ef | |
| parent | 7e958b7fdfb233d7c0ebd56aaf1935b7e4c4cba2 (diff) | |
Small technical additions for keyboard layout and app dispatch fixesSmall technical additions for keyboard layout and app dispatch fixes
This commit introduces two minor but useful scripts aimed at solving specific edge cases
in Hyprland usage:
1. Tak0-Per-Window-Switch.sh:
Enables per-window keyboard layout switching. This is useful for multilingual workflows
where the global layout model becomes inconvenient. The script listens to window focus
events and restores the last-used layout for that specific window.
2. Tak0-Autodispatch.sh:
Fixes a recurring issue where startup applications are dispatched to incorrect monitors
or workspaces, especially in dynamic multi-monitor environments (e.g., a laptop that
gets docked/undocked). The original dispatch rules sometimes fail due to race conditions
or child process spawning out of focus. This script re-applies correct dispatching logic
after startup, reducing manual corrections.
Also:
- Updated UserKeybinds.conf to run the per-window layout script at startup.
- All changes are additive. No existing configs or behavior were overridden or broken.
These changes don't introduce any core structural modifications — just small utilities
to improve the overall experience when using Hyprland in daily workflows.
| -rw-r--r-- | config/hypr/UserConfigs/UserKeybinds.conf | 3 | ||||
| -rwxr-xr-x | config/hypr/scripts/Tak0-Autodispatch.sh | 90 | ||||
| -rwxr-xr-x | config/hypr/scripts/Tak0-Per-Window-Switch.sh | 123 |
3 files changed, 215 insertions, 1 deletions
diff --git a/config/hypr/UserConfigs/UserKeybinds.conf b/config/hypr/UserConfigs/UserKeybinds.conf index 70202ba4..dd18b971 100644 --- a/config/hypr/UserConfigs/UserKeybinds.conf +++ b/config/hypr/UserConfigs/UserKeybinds.conf @@ -64,7 +64,8 @@ bind = $mainMod CTRL, O, exec, hyprctl setprop active opaque toggle # disable op bind = $mainMod SHIFT, K, exec, $scriptsDir/KeyBinds.sh # search keybinds via rofi bind = $mainMod SHIFT, A, exec, $scriptsDir/Animations.sh #hyprland animations menu bind = $mainMod SHIFT, O, exec, $UserScripts/ZshChangeTheme.sh # Change oh-my-zsh theme -bindln = ALT_L, SHIFT_L, exec, $scriptsDir/SwitchKeyboardLayout.sh # Change keyboard layout +bindln = ALT_L, SHIFT_L, exec, $scriptsDir/SwitchKeyboardLayout.sh # Change keyboard layout globally +bindln = SHIFT_L, ALT_L, exec, $scriptsDir/Tak0-Per-Window-Switch.sh # Change keyboard layout locally for each window bind = $mainMod ALT, C, exec, $UserScripts/RofiCalc.sh # calculator (qalculate) diff --git a/config/hypr/scripts/Tak0-Autodispatch.sh b/config/hypr/scripts/Tak0-Autodispatch.sh new file mode 100755 index 00000000..a1f72129 --- /dev/null +++ b/config/hypr/scripts/Tak0-Autodispatch.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# USAGE / ІНСТРУКЦІЯ: +# 1) Run from terminal: +# ./dispatch.sh <application_command> <target_workspace_number> +# Example: +# ./dispatch.sh discord 2 +# +# 2) Call from Hyprland config (in hyprland.conf file): +# exec-once = /path/to/dispatch.sh <application_command> <target_workspace_number> +# +# Logs are saved in dispatch.log file next to the script. +# If the window doesn't appear or is dispatched incorrectly — info will be there. +# +# 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 +fi + +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 +sleep 0.4 + +# Launch the application in the background and disown it. +# Запускаємо аплікацію у фоновому режимі та відв’язуємо від терміналу. +$APP & disown +pid=$! + +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" ' + .[] | 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 +done + +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-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh new file mode 100755 index 00000000..76b6ad2d --- /dev/null +++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh @@ -0,0 +1,123 @@ +################################################################## +# # +# # +# 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" +CFG_FILE="$HOME/.config/hypr/UserConfigs/UserSettings.conf" +ICON="$HOME/.config/swaync/images/ja.png" +SCRIPT_NAME="$(basename "$0")" + +# Ensure map file exists +touch "$MAP_FILE" + +# Read layouts from config +if ! grep -q 'kb_layout' "$CFG_FILE"; then + echo "Error: cannot find kb_layout in $CFG_FILE" >&2 + exit 1 +fi +kb_layouts=($(grep 'kb_layout' "$CFG_FILE" | cut -d '=' -f2 | tr -d '[:space:]' | tr ',' ' ')) +count=${#kb_layouts[@]} + +# Get current active window ID +get_win() { + hyprctl activewindow -j | jq -r '.address // .id' +} + +# Get available keyboards +get_keyboards() { + hyprctl devices -j | jq -r '.keyboards[].name' +} + +# Save window-specific layout +save_map() { + local W=$1 L=$2 + grep -v "^${W}:" "$MAP_FILE" > "$MAP_FILE.tmp" + echo "${W}:${L}" >> "$MAP_FILE.tmp" + mv "$MAP_FILE.tmp" "$MAP_FILE" +} + +# Load layout for window (fallback to default) +load_map() { + local W=$1 + local E + E=$(grep "^${W}:" "$MAP_FILE") + [[ -n "$E" ]] && echo "${E#*:}" || echo "${kb_layouts[0]}" +} + +# Switch layout for all keyboards to layout index +do_switch() { + local IDX=$1 + for kb in $(get_keyboards); do + hyprctl switchxkblayout "$kb" "$IDX" 2>/dev/null + done +} + +# Toggle layout for current window only +cmd_toggle() { + local W=$(get_win) + [[ -z "$W" ]] && return + local CUR=$(load_map "$W") + local i NEXT + for idx in "${!kb_layouts[@]}"; do + if [[ "${kb_layouts[idx]}" == "$CUR" ]]; then + i=$idx + break + fi + done + NEXT=$(( (i+1) % count )) + do_switch "$NEXT" + save_map "$W" "${kb_layouts[NEXT]}" + notify-send -u low -i "$ICON" "kb_layout: ${kb_layouts[NEXT]}" +} + +# Restore layout on focus +cmd_restore() { + local W=$(get_win) + [[ -z "$W" ]] && return + local LAY=$(load_map "$W") + for idx in "${!kb_layouts[@]}"; do + if [[ "${kb_layouts[idx]}" == "$LAY" ]]; then + do_switch "$idx" + break + fi + done +} + +# Listen to focus events and restore window-specific layouts +subscribe() { + local SOCKET2="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" + [[ -S "$SOCKET2" ]] || { echo "Error: Hyprland socket not found." >&2; exit 1; } + + socat -u UNIX-CONNECT:"$SOCKET2" - | while read -r line; do + [[ "$line" =~ ^activewindow ]] && cmd_restore + done +} + +# Ensure only one listener +if ! pgrep -f "$SCRIPT_NAME.*--listener" >/dev/null; then + subscribe --listener & +fi + +# CLI +case "$1" in + toggle|"") cmd_toggle ;; + *) echo "Usage: $SCRIPT_NAME [toggle]" >&2; exit 1 ;; +esac |
