aboutsummaryrefslogtreecommitdiffstats
path: root/config/hypr/scripts/Dropterminal.sh
diff options
context:
space:
mode:
Diffstat (limited to 'config/hypr/scripts/Dropterminal.sh')
-rwxr-xr-xconfig/hypr/scripts/Dropterminal.sh630
1 files changed, 466 insertions, 164 deletions
diff --git a/config/hypr/scripts/Dropterminal.sh b/config/hypr/scripts/Dropterminal.sh
index 81c0f157..21349d4a 100755
--- a/config/hypr/scripts/Dropterminal.sh
+++ b/config/hypr/scripts/Dropterminal.sh
@@ -24,6 +24,106 @@ LOCK_FILE="/tmp/dropdown_terminal_lock"
LAST_TOGGLE_FILE="/tmp/dropdown_terminal_last_toggle"
MIN_TOGGLE_INTERVAL_MS=250
DROPDOWN_KITTY_CLASS="kitty-dropterm"
+CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
+HYPR_DIR="$CONFIG_HOME/hypr"
+LUA_ENTRY="$HYPR_DIR/hyprland.lua"
+LEGACY_LUA_ENTRY="$CONFIG_HOME/hyprland.lua"
+
+if [[ -f "$LUA_ENTRY" || -f "$LEGACY_LUA_ENTRY" ]]; then
+ HYPR_CONFIG_MODE="lua"
+else
+ HYPR_CONFIG_MODE="conf"
+fi
+lua_escape() {
+ local value="$1"
+ value=${value//\\/\\\\}
+ value=${value//\"/\\\"}
+ value=${value//$'\n'/\\n}
+ printf '%s' "$value"
+}
+
+
+hypr_dispatch() {
+ local dispatcher="$1"
+ shift
+ local payload="$*"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local command="$dispatcher"
+ if [ -n "$payload" ]; then
+ command="$dispatcher $payload"
+ fi
+ local escaped
+ escaped="$(lua_escape "$command")"
+ hyprctl dispatch "hl.dsp.exec_raw(\"$escaped\")"
+ else
+ hyprctl dispatch "$dispatcher" "$payload"
+ fi
+}
+
+hypr_exec_cmd() {
+ local command="$*"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local escaped
+ escaped="$(lua_escape "$command")"
+ hyprctl dispatch "hl.dsp.exec_cmd(\"$escaped\")"
+ else
+ hyprctl dispatch exec "$command"
+ fi
+}
+
+lua_workspace_expr() {
+ local workspace="$1"
+ if [[ "$workspace" =~ ^-?[0-9]+$ ]]; then
+ printf '%s' "$workspace"
+ else
+ local escaped
+ escaped="$(lua_escape "$workspace")"
+ printf '"%s"' "$escaped"
+ fi
+}
+
+focus_window() {
+ local addr="$1"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local selector escaped
+ selector="address:$addr"
+ escaped="$(lua_escape "$selector")"
+ hyprctl dispatch "hl.dsp.focus({ window = \"$escaped\" })"
+ else
+ hypr_dispatch focuswindow "address:$addr"
+ fi
+}
+
+set_window_floating() {
+ local addr="$1"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ hyprctl dispatch "hl.dsp.window.float({ window = 'address:$addr', action = 'on' })"
+ else
+ hypr_dispatch setfloating "address:$addr"
+ fi
+}
+
+resize_window_exact() {
+ local addr="$1"
+ local width="$2"
+ local height="$3"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ hyprctl dispatch "hl.dsp.window.resize({ window = 'address:$addr', x = $width, y = $height, exact = true })"
+ else
+ hypr_dispatch resizewindowpixel "exact $width $height,address:$addr"
+ fi
+}
+
+move_window_exact() {
+ local addr="$1"
+ local x="$2"
+ local y="$3"
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ hyprctl dispatch "hl.dsp.window.move({ window = 'address:$addr', x = $x, y = $y, exact = true })"
+ else
+ hypr_dispatch movewindowpixel "exact $x $y,address:$addr"
+ fi
+}
# Dropdown size and position configuration (percentages)
WIDTH_PERCENT=65 # Width as percentage of screen width
@@ -31,19 +131,42 @@ HEIGHT_PERCENT=65 # Height as percentage of screen height
Y_PERCENT=10 # Y position as percentage from top (X is auto-centered)
# Animation settings
-ANIMATION_DURATION=100 # milliseconds
-SLIDE_STEPS=5
-SLIDE_DELAY=5 # milliseconds between steps
+ANIMATION_DURATION=220 # total animation time in milliseconds
+SLIDE_STEPS=12
+SLIDE_DELAY=$((ANIMATION_DURATION / SLIDE_STEPS))
+if [ "$SLIDE_DELAY" -lt 8 ]; then
+ SLIDE_DELAY=8
+fi
# Parse arguments
-if [ "$1" = "-d" ]; then
- DEBUG=true
- shift
-fi
+STARTUP_MODE=false
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -d | --debug)
+ DEBUG=true
+ shift
+ ;;
+ --startup | --init)
+ STARTUP_MODE=true
+ shift
+ ;;
+ -h | --help)
+ echo "Usage: $0 [-d|--debug] [--startup|--init] <terminal_command>"
+ echo "Examples:"
+ echo " $0 kitty"
+ echo " $0 --startup kitty"
+ echo " $0 -d \"kitty -e zsh\""
+ exit 0
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
-TERMINAL_CMD="$1"
+TERMINAL_CMD="$*"
if [[ "$TERMINAL_CMD" == kitty* ]] && [[ "$TERMINAL_CMD" != *"--class"* ]] && [[ "$TERMINAL_CMD" != *"--name"* ]] && [[ "$TERMINAL_CMD" != *"--app-id"* ]]; then
- TERMINAL_CMD="$TERMINAL_CMD --class $DROPDOWN_KITTY_CLASS"
+ TERMINAL_CMD="$TERMINAL_CMD --class $DROPDOWN_KITTY_CLASS --app-id $DROPDOWN_KITTY_CLASS"
fi
# Ensure only one instance runs at a time (prevents overlapping animations)
@@ -51,25 +174,27 @@ exec 9>"$LOCK_FILE"
flock -n 9 || exit 0
# Debounce rapid toggles
-now_ms=""
-if date +%s%3N >/dev/null 2>&1; then
- now_ms=$(date +%s%3N)
-else
- now_ms=$(( $(date +%s) * 1000 ))
-fi
-if [ -f "$LAST_TOGGLE_FILE" ]; then
- last_ms=$(cat "$LAST_TOGGLE_FILE" 2>/dev/null || echo 0)
- if [ -n "$last_ms" ] && [ "$last_ms" -ge 0 ] 2>/dev/null; then
- delta_ms=$((now_ms - last_ms))
- if [ "$delta_ms" -lt "$MIN_TOGGLE_INTERVAL_MS" ] 2>/dev/null; then
- if [ "$DEBUG" = true ]; then
- echo "Toggle debounced (${delta_ms}ms < ${MIN_TOGGLE_INTERVAL_MS}ms)" >&2
+if [ "$STARTUP_MODE" != true ]; then
+ now_ms=""
+ if date +%s%3N >/dev/null 2>&1; then
+ now_ms=$(date +%s%3N)
+ else
+ now_ms=$(( $(date +%s) * 1000 ))
+ fi
+ if [ -f "$LAST_TOGGLE_FILE" ]; then
+ last_ms=$(cat "$LAST_TOGGLE_FILE" 2>/dev/null || echo 0)
+ if [ -n "$last_ms" ] && [ "$last_ms" -ge 0 ] 2>/dev/null; then
+ delta_ms=$((now_ms - last_ms))
+ if [ "$delta_ms" -lt "$MIN_TOGGLE_INTERVAL_MS" ] 2>/dev/null; then
+ if [ "$DEBUG" = true ]; then
+ echo "Toggle debounced (${delta_ms}ms < ${MIN_TOGGLE_INTERVAL_MS}ms)" >&2
+ fi
+ exit 0
fi
- exit 0
fi
fi
+ echo "$now_ms" >"$LAST_TOGGLE_FILE"
fi
-echo "$now_ms" >"$LAST_TOGGLE_FILE"
# Debug echo function
debug_echo() {
@@ -103,10 +228,11 @@ resolve_terminal_address() {
# Validate input
if [ -z "$TERMINAL_CMD" ]; then
- echo "Missing terminal command. Usage: $0 [-d] <terminal_command>"
+ echo "Missing terminal command. Usage: $0 [-d|--debug] [--startup|--init] <terminal_command>"
echo "Examples:"
- echo " $0 foot"
- echo " $0 -d foot (with debug output)"
+ echo " $0 kitty"
+ echo " $0 --startup kitty"
+ echo " $0 -d kitty (with debug output)"
echo " $0 'kitty -e zsh'"
echo " $0 'alacritty --working-directory /home/user'"
echo ""
@@ -127,14 +253,57 @@ get_window_geometry() {
# Function to check if window is currently hidden off-screen
window_is_hidden() {
local addr="$1"
- local y
- y=$(hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .at[1]' 2>/dev/null)
- if [[ "$y" =~ ^-?[0-9]+$ ]] && [ "$y" -lt 0 ]; then
+ local geometry y height monitor_id monitor_y
+ geometry=$(hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | "\(.at[1]) \(.size[1]) \(.monitor)"' 2>/dev/null)
+ y=$(echo "$geometry" | awk '{print $1}')
+ height=$(echo "$geometry" | awk '{print $2}')
+ monitor_id=$(echo "$geometry" | awk '{print $3}')
+
+ if ! [[ "$y" =~ ^-?[0-9]+$ && "$height" =~ ^[0-9]+$ ]]; then
+ return 1
+ fi
+
+ if [[ "$monitor_id" =~ ^-?[0-9]+$ ]]; then
+ monitor_y=$(hyprctl monitors -j 2>/dev/null | jq -r --argjson MID "$monitor_id" '.[] | select(.id == $MID) | .y' 2>/dev/null | head -1)
+ fi
+ if ! [[ "$monitor_y" =~ ^-?[0-9]+$ ]]; then
+ monitor_y=0
+ fi
+
+ if [ $((y + height)) -le "$monitor_y" ]; then
return 0
fi
return 1
}
+get_window_monitor_top() {
+ local addr="$1"
+ local monitor_id monitor_y
+ monitor_id=$(hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .monitor' 2>/dev/null | head -1)
+ if [[ "$monitor_id" =~ ^-?[0-9]+$ ]]; then
+ monitor_y=$(hyprctl monitors -j 2>/dev/null | jq -r --argjson MID "$monitor_id" '.[] | select(.id == $MID) | .y' 2>/dev/null | head -1)
+ if [[ "$monitor_y" =~ ^-?[0-9]+$ ]]; then
+ echo "$monitor_y"
+ return 0
+ fi
+ fi
+ echo 0
+}
+
+get_hidden_y_for_window() {
+ local addr="$1"
+ local height="$2"
+ local monitor_top
+ if ! [[ "$height" =~ ^[0-9]+$ ]]; then
+ height=702
+ fi
+ monitor_top=$(get_window_monitor_top "$addr")
+ if ! [[ "$monitor_top" =~ ^-?[0-9]+$ ]]; then
+ monitor_top=0
+ fi
+ echo $((monitor_top - height - 80))
+}
+
# State helpers
get_hidden_state() {
if [ -f "$STATE_FILE" ]; then
@@ -146,6 +315,15 @@ set_hidden_state() {
echo "$1" >"$STATE_FILE"
}
+sleep_ms() {
+ local ms="$1"
+ if command -v awk >/dev/null 2>&1; then
+ sleep "$(awk -v value="$ms" 'BEGIN { printf "%.3f", value / 1000 }')"
+ else
+ sleep 0.01
+ fi
+}
+
# Function to animate window slide down (show)
animate_slide_down() {
local addr="$1"
@@ -153,28 +331,28 @@ animate_slide_down() {
local target_y="$3"
local width="$4"
local height="$5"
+ local start_y="$6"
debug_echo "Animating slide down for window $addr to position $target_x,$target_y"
- # Start position (above screen)
- local start_y=$((target_y - height - 50))
-
- # Calculate step size
- local step_y=$(((target_y - start_y) / SLIDE_STEPS))
+ if ! [[ "$start_y" =~ ^-?[0-9]+$ ]]; then
+ start_y=$((target_y - height - 50))
+ fi
+ local total_delta=$((target_y - start_y))
# Move window to start position instantly (off-screen)
- hyprctl dispatch movewindowpixel "exact $target_x $start_y,address:$addr" >/dev/null 2>&1
- sleep 0.05
+ move_window_exact "$addr" "$target_x" "$start_y" >/dev/null 2>&1 || return 1
+ sleep_ms "$SLIDE_DELAY"
# Animate slide down
for i in $(seq 1 $SLIDE_STEPS); do
- local current_y=$((start_y + (step_y * i)))
- hyprctl dispatch movewindowpixel "exact $target_x $current_y,address:$addr" >/dev/null 2>&1
- sleep 0.03
+ local current_y=$((start_y + (total_delta * i / SLIDE_STEPS)))
+ move_window_exact "$addr" "$target_x" "$current_y" >/dev/null 2>&1 || return 1
+ sleep_ms "$SLIDE_DELAY"
done
# Ensure final position is exact
- hyprctl dispatch movewindowpixel "exact $target_x $target_y,address:$addr" >/dev/null 2>&1
+ move_window_exact "$addr" "$target_x" "$target_y" >/dev/null 2>&1
}
# Function to animate window slide up (hide)
@@ -184,21 +362,22 @@ animate_slide_up() {
local start_y="$3"
local width="$4"
local height="$5"
+ local end_y="$6"
debug_echo "Animating slide up for window $addr from position $start_x,$start_y"
- # End position (above screen)
- local end_y=$((start_y - height - 50))
-
- # Calculate step size
- local step_y=$(((start_y - end_y) / SLIDE_STEPS))
+ if ! [[ "$end_y" =~ ^-?[0-9]+$ ]]; then
+ end_y=$((start_y - height - 50))
+ fi
+ local total_delta=$((start_y - end_y))
# Animate slide up
for i in $(seq 1 $SLIDE_STEPS); do
- local current_y=$((start_y - (step_y * i)))
- hyprctl dispatch movewindowpixel "exact $start_x $current_y,address:$addr" >/dev/null 2>&1
- sleep 0.03
+ local current_y=$((start_y - (total_delta * i / SLIDE_STEPS)))
+ move_window_exact "$addr" "$start_x" "$current_y" >/dev/null 2>&1 || return 1
+ sleep_ms "$SLIDE_DELAY"
done
+ move_window_exact "$addr" "$start_x" "$end_y" >/dev/null 2>&1
debug_echo "Slide up animation completed"
}
@@ -312,8 +491,9 @@ calculate_dropdown_position() {
echo "$final_x $final_y $width $height $mon_name"
}
-# Get the current workspace
-CURRENT_WS=$(hyprctl activeworkspace -j | jq -r '.id')
+get_current_workspace() {
+ hyprctl activeworkspace -j 2>/dev/null | jq -r '.id // empty'
+}
# Function to get stored terminal address
get_terminal_address() {
@@ -325,7 +505,7 @@ get_terminal_address() {
# Try to find an existing dropdown terminal by class (kitty only)
find_terminal_by_class() {
hyprctl clients -j 2>/dev/null | jq -r --arg CLASS "$DROPDOWN_KITTY_CLASS" \
- '.[] | select(.class == $CLASS) | .address' | head -1
+ '.[] | select((.class == $CLASS) or (.initialClass == $CLASS)) | .address' | head -1
}
# Function to get stored monitor name
@@ -356,29 +536,197 @@ window_exists() {
}
-# Function to check if window is pinned
-window_is_pinned() {
+window_workspace_name() {
local addr="$1"
- if [ -n "$addr" ]; then
- hyprctl clients -j 2>/dev/null | jq -e --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .pinned == true' >/dev/null 2>&1
+ hyprctl clients -j 2>/dev/null | jq -r --arg ADDR "$addr" '.[] | select(.address == $ADDR) | .workspace.name // empty'
+}
+
+window_is_on_special_workspace() {
+ local addr="$1"
+ local workspace_name
+ workspace_name=$(window_workspace_name "$addr")
+ [ "$workspace_name" = "$SPECIAL_WS" ] || [ "$workspace_name" = "$SPECIAL_NAME" ]
+}
+
+workspace_matches_target() {
+ local target_ws="$1"
+ local current_ws="$2"
+ if [ "$target_ws" = "$SPECIAL_WS" ] || [ "$target_ws" = "$SPECIAL_NAME" ]; then
+ [ "$current_ws" = "$SPECIAL_WS" ] || [ "$current_ws" = "$SPECIAL_NAME" ]
else
+ [ "$current_ws" = "$target_ws" ]
+ fi
+}
+
+move_window_to_workspace_silent() {
+ local target_ws="$1"
+ local addr="$2"
+ local post_ws=""
+
+ if [[ "$HYPR_CONFIG_MODE" == "lua" ]]; then
+ local ws_expr
+ ws_expr=$(lua_workspace_expr "$target_ws")
+ hyprctl dispatch "hl.dsp.window.move({ window = 'address:$addr', workspace = $ws_expr, follow = false })" >/dev/null 2>&1 || return 1
+ sleep 0.03
+ post_ws=$(window_workspace_name "$addr")
+ workspace_matches_target "$target_ws" "$post_ws"
+ return $?
+ fi
+
+ # Preferred syntax on newer Hyprland builds (target a specific window by selector).
+ if hypr_dispatch movetoworkspacesilent "$target_ws,address:$addr" >/dev/null 2>&1; then
+ sleep 0.03
+ post_ws=$(window_workspace_name "$addr")
+ if workspace_matches_target "$target_ws" "$post_ws"; then
+ return 0
+ fi
+ fi
+
+ # Compatibility fallback for builds where selector syntax is ignored.
+ hypr_dispatch focuswindow "address:$addr" >/dev/null 2>&1 || return 1
+ hypr_dispatch movetoworkspacesilent "$target_ws" >/dev/null 2>&1 || return 1
+ sleep 0.03
+ post_ws=$(window_workspace_name "$addr")
+ workspace_matches_target "$target_ws" "$post_ws"
+}
+
+infer_hidden_state() {
+ local addr="$1"
+ if window_is_hidden "$addr"; then
+ echo "hidden"
+ elif window_is_on_special_workspace "$addr"; then
+ echo "hidden"
+ else
+ echo "shown"
+ fi
+}
+
+apply_dropdown_layout() {
+ local addr="$1"
+ local pos_info
+ pos_info=$(calculate_dropdown_position)
+ if [ $? -ne 0 ]; then
+ debug_echo "Warning: Failed to calculate dropdown position, layout update skipped"
return 1
fi
+
+ local target_x=$(echo "$pos_info" | cut -d' ' -f1)
+ local target_y=$(echo "$pos_info" | cut -d' ' -f2)
+ local width=$(echo "$pos_info" | cut -d' ' -f3)
+ local height=$(echo "$pos_info" | cut -d' ' -f4)
+ set_window_floating "$addr" >/dev/null 2>&1
+ resize_window_exact "$addr" "$width" "$height" >/dev/null 2>&1
+ move_window_exact "$addr" "$target_x" "$target_y" >/dev/null 2>&1
+ return 0
}
-# Ensure pin state without toggling unexpectedly
-ensure_pinned() {
+show_terminal() {
local addr="$1"
- if ! window_is_pinned "$addr"; then
- hyprctl dispatch pin "address:$addr" >/dev/null 2>&1
+ local current_ws
+ local pos_info target_x target_y width height hidden_y
+ current_ws=$(get_current_workspace)
+ if ! [[ "$current_ws" =~ ^-?[0-9]+$ ]]; then
+ current_ws=1
+ fi
+ pos_info=$(calculate_dropdown_position)
+ if [ $? -ne 0 ] || [ -z "$pos_info" ]; then
+ debug_echo "Failed to calculate dropdown position for show; falling back to direct layout"
+ move_window_to_workspace_silent "$current_ws" "$addr" >/dev/null 2>&1 || debug_echo "Failed to move dropdown terminal to workspace $current_ws"
+ apply_dropdown_layout "$addr" || debug_echo "Dropdown layout update returned non-zero"
+ focus_window "$addr" >/dev/null 2>&1 || true
+ set_hidden_state "shown"
+ debug_echo "Dropdown terminal shown"
+ return 0
+ fi
+
+ target_x=$(echo "$pos_info" | cut -d' ' -f1)
+ target_y=$(echo "$pos_info" | cut -d' ' -f2)
+ width=$(echo "$pos_info" | cut -d' ' -f3)
+ height=$(echo "$pos_info" | cut -d' ' -f4)
+ hidden_y=$(get_hidden_y_for_window "$addr" "$height")
+ if window_is_on_special_workspace "$addr"; then
+ move_window_to_workspace_silent "$current_ws" "$addr" >/dev/null 2>&1 || debug_echo "Failed to move dropdown terminal to workspace $current_ws"
+ fi
+ set_window_floating "$addr" >/dev/null 2>&1 || true
+ resize_window_exact "$addr" "$width" "$height" >/dev/null 2>&1 || true
+ animate_slide_down "$addr" "$target_x" "$target_y" "$width" "$height" "$hidden_y" || move_window_exact "$addr" "$target_x" "$target_y" >/dev/null 2>&1
+ focus_window "$addr" >/dev/null 2>&1 || true
+ set_hidden_state "shown"
+ debug_echo "Dropdown terminal shown"
+ return 0
+}
+
+hide_terminal() {
+ local addr="$1"
+ local geometry start_x start_y width height hidden_y
+ if window_is_hidden "$addr" || window_is_on_special_workspace "$addr"; then
+ set_hidden_state "hidden"
+ debug_echo "Dropdown terminal already hidden"
+ return 0
+ fi
+
+ geometry=$(get_window_geometry "$addr")
+ if [ -n "$geometry" ]; then
+ start_x=$(echo "$geometry" | awk '{print $1}')
+ start_y=$(echo "$geometry" | awk '{print $2}')
+ width=$(echo "$geometry" | awk '{print $3}')
+ height=$(echo "$geometry" | awk '{print $4}')
+ else
+ local pos_info
+ pos_info=$(calculate_dropdown_position)
+ start_x=$(echo "$pos_info" | cut -d' ' -f1)
+ start_y=$(echo "$pos_info" | cut -d' ' -f2)
+ width=$(echo "$pos_info" | cut -d' ' -f3)
+ height=$(echo "$pos_info" | cut -d' ' -f4)
+ fi
+
+ if ! [[ "$height" =~ ^[0-9]+$ ]]; then
+ height=702
+ fi
+ hidden_y=$(get_hidden_y_for_window "$addr" "$height")
+ if ! [[ "$start_x" =~ ^-?[0-9]+$ && "$start_y" =~ ^-?[0-9]+$ ]]; then
+ debug_echo "Missing geometry for slide-up animation; moving off-screen directly"
+ move_window_exact "$addr" "$start_x" "$hidden_y" >/dev/null 2>&1 || true
+ else
+ animate_slide_up "$addr" "$start_x" "$start_y" "$width" "$height" "$hidden_y" || true
+ fi
+
+ if ! window_is_hidden "$addr"; then
+ debug_echo "Dropdown not off-screen after slide; trying direct off-screen move"
+ move_window_exact "$addr" "$start_x" "$hidden_y" >/dev/null 2>&1 || true
+ fi
+ if ! window_is_hidden "$addr"; then
+ debug_echo "Off-screen hide failed, falling back to $SPECIAL_WS"
+ if ! move_window_to_workspace_silent "$SPECIAL_WS" "$addr"; then
+ debug_echo "Failed to move dropdown terminal to $SPECIAL_WS"
+ return 1
+ fi
fi
+ set_hidden_state "hidden"
+ debug_echo "Dropdown terminal hidden"
+ return 0
}
-ensure_unpinned() {
+hide_terminal_silent() {
local addr="$1"
- if window_is_pinned "$addr"; then
- hyprctl dispatch pin "address:$addr" >/dev/null 2>&1
+ local geometry start_x height hidden_y
+ geometry=$(get_window_geometry "$addr")
+ if [ -n "$geometry" ]; then
+ start_x=$(echo "$geometry" | awk '{print $1}')
+ height=$(echo "$geometry" | awk '{print $4}')
fi
+ if ! [[ "$height" =~ ^[0-9]+$ ]]; then
+ height=702
+ fi
+ hidden_y=$(get_hidden_y_for_window "$addr" "$height")
+ if ! [[ "$start_x" =~ ^-?[0-9]+$ ]]; then
+ start_x=0
+ fi
+ move_window_exact "$addr" "$start_x" "$hidden_y" >/dev/null 2>&1 || true
+ move_window_to_workspace_silent "$SPECIAL_WS" "$addr" >/dev/null 2>&1 || true
+ set_hidden_state "hidden"
+ debug_echo "Dropdown terminal hidden (silent)"
+ return 0
}
# Function to spawn terminal and capture its address
@@ -403,45 +751,48 @@ spawn_terminal() {
local windows_before=$(hyprctl clients -j)
local count_before=$(echo "$windows_before" | jq 'length')
- # Launch terminal directly in special workspace to avoid visible spawn
- hyprctl dispatch exec "[float; size $width $height; workspace special:scratchpad silent] $TERMINAL_CMD"
-
- # Wait for window to appear
- sleep 0.1
-
- # Get windows after spawning
- local windows_after=$(hyprctl clients -j)
- local count_after=$(echo "$windows_after" | jq 'length')
+ # Launch terminal with pre-applied workspace/geometry hints to avoid visible zigzag.
+ local launch_cmd="[workspace $SPECIAL_WS silent;float;size $width $height;move $target_x $target_y] $TERMINAL_CMD"
+ hypr_exec_cmd "$launch_cmd"
local new_addr=""
+ for _ in $(seq 1 20); do
+ local windows_after=$(hyprctl clients -j)
+ local recovered
+ recovered=$(echo "$windows_after" | jq -r --arg CLASS "$DROPDOWN_KITTY_CLASS" \
+ '.[] | select((.class == $CLASS) or (.initialClass == $CLASS)) | .address' | head -1)
+ if [ -n "$recovered" ] && [ "$recovered" != "null" ]; then
+ new_addr="$recovered"
+ break
+ fi
- if [ "$count_after" -gt "$count_before" ]; then
- # Find the new window by comparing before/after lists
- new_addr=$(comm -13 \
- <(echo "$windows_before" | jq -r '.[].address' | sort) \
- <(echo "$windows_after" | jq -r '.[].address' | sort) |
- head -1)
- fi
-
- # Fallback: try to find by the most recently mapped window
- if [ -z "$new_addr" ] || [ "$new_addr" = "null" ]; then
- new_addr=$(hyprctl clients -j | jq -r 'sort_by(.focusHistoryID) | .[-1] | .address')
- fi
+ local count_after=$(echo "$windows_after" | jq 'length')
+ if [ "$count_after" -gt "$count_before" ]; then
+ new_addr=$(comm -13 \
+ <(echo "$windows_before" | jq -r '.[].address' | sort) \
+ <(echo "$windows_after" | jq -r '.[].address' | sort) |
+ head -1)
+ if [ -n "$new_addr" ] && [ "$new_addr" != "null" ]; then
+ break
+ fi
+ fi
+ sleep 0.1
+ done
if [ -n "$new_addr" ] && [ "$new_addr" != "null" ]; then
# Store the address and monitor name
echo "$new_addr $monitor_name" >"$ADDR_FILE"
debug_echo "Terminal created with address: $new_addr in special workspace on monitor $monitor_name"
- # Small delay to ensure it's properly in special workspace
- sleep 0.2
- # Move to current workspace but start hidden off-screen
- hyprctl dispatch movetoworkspacesilent "$CURRENT_WS,address:$new_addr"
- ensure_pinned "$new_addr"
- hyprctl dispatch resizewindowpixel "exact $width $height,address:$new_addr" >/dev/null 2>&1
- local off_y=$((target_y - height - 200))
- hyprctl dispatch movewindowpixel "exact $target_x $off_y,address:$new_addr" >/dev/null 2>&1
- set_hidden_state "hidden"
+ # Configure in special workspace and keep hidden until explicitly toggled.
+ set_window_floating "$new_addr" >/dev/null 2>&1
+ resize_window_exact "$new_addr" "$width" "$height" >/dev/null 2>&1
+ move_window_exact "$new_addr" "$target_x" "$target_y" >/dev/null 2>&1
+ if [ "$STARTUP_MODE" = true ]; then
+ hide_terminal_silent "$new_addr" || debug_echo "Failed to hide new dropdown terminal after spawn (silent)"
+ else
+ hide_terminal "$new_addr" || debug_echo "Failed to hide new dropdown terminal after spawn"
+ fi
return 0
fi
@@ -452,80 +803,31 @@ spawn_terminal() {
# Main logic
TERMINAL_ADDR=$(resolve_terminal_address)
-
-if [ -n "$TERMINAL_ADDR" ]; then
- debug_echo "Found existing terminal: $TERMINAL_ADDR"
- focused_monitor=$(get_monitor_info | awk '{print $6}')
- dropdown_monitor=$(get_terminal_monitor)
- if [ "$focused_monitor" != "$dropdown_monitor" ]; then
- debug_echo "Monitor focus changed: moving dropdown to $focused_monitor"
- # Calculate new position for focused monitor
- pos_info=$(calculate_dropdown_position)
- target_x=$(echo $pos_info | cut -d' ' -f1)
- target_y=$(echo $pos_info | cut -d' ' -f2)
- width=$(echo $pos_info | cut -d' ' -f3)
- height=$(echo $pos_info | cut -d' ' -f4)
- monitor_name=$(echo $pos_info | cut -d' ' -f5)
- # Move and resize window
- hyprctl dispatch movewindowpixel "exact $target_x $target_y,address:$TERMINAL_ADDR"
- hyprctl dispatch resizewindowpixel "exact $width $height,address:$TERMINAL_ADDR"
- # Update ADDR_FILE
- echo "$TERMINAL_ADDR $monitor_name" >"$ADDR_FILE"
+if [ -z "$TERMINAL_ADDR" ]; then
+ debug_echo "No existing terminal found, creating new one"
+ if spawn_terminal; then
+ TERMINAL_ADDR=$(get_terminal_address)
fi
+fi
- hidden_state=$(get_hidden_state)
- if [ "$hidden_state" = "hidden" ] || [ -z "$hidden_state" ] || window_is_hidden "$TERMINAL_ADDR"; then
- debug_echo "Bringing terminal from hidden position with slide down animation"
-
- # Calculate target position
- pos_info=$(calculate_dropdown_position)
- target_x=$(echo $pos_info | cut -d' ' -f1)
- target_y=$(echo $pos_info | cut -d' ' -f2)
- width=$(echo $pos_info | cut -d' ' -f3)
- height=$(echo $pos_info | cut -d' ' -f4)
-
- ensure_pinned "$TERMINAL_ADDR"
-
- # Set size and animate slide down
- hyprctl dispatch resizewindowpixel "exact $width $height,address:$TERMINAL_ADDR"
- animate_slide_down "$TERMINAL_ADDR" "$target_x" "$target_y" "$width" "$height"
-
- hyprctl dispatch focuswindow "address:$TERMINAL_ADDR"
- set_hidden_state "shown"
- else
- debug_echo "Hiding terminal off-screen with slide up animation"
-
- # Get current geometry for animation
- geometry=$(get_window_geometry "$TERMINAL_ADDR")
- if [ -n "$geometry" ]; then
- curr_x=$(echo $geometry | cut -d' ' -f1)
- curr_y=$(echo $geometry | cut -d' ' -f2)
- curr_width=$(echo $geometry | cut -d' ' -f3)
- curr_height=$(echo $geometry | cut -d' ' -f4)
-
- debug_echo "Current geometry: ${curr_x},${curr_y} ${curr_width}x${curr_height}"
+if [ -z "$TERMINAL_ADDR" ]; then
+ debug_echo "No dropdown terminal instance is available"
+ exit 1
+fi
- # Animate slide up first
- animate_slide_up "$TERMINAL_ADDR" "$curr_x" "$curr_y" "$curr_width" "$curr_height"
+if [ "$STARTUP_MODE" = true ]; then
+ debug_echo "Startup mode requested: ensuring dropdown terminal exists and stays hidden"
+ hide_terminal_silent "$TERMINAL_ADDR"
+ exit 0
+fi
+HIDDEN_STATE=$(get_hidden_state)
+if [ "$HIDDEN_STATE" != "hidden" ] && [ "$HIDDEN_STATE" != "shown" ]; then
+ HIDDEN_STATE=$(infer_hidden_state "$TERMINAL_ADDR")
+ set_hidden_state "$HIDDEN_STATE"
+fi
- # Move off-screen after animation
- off_y=$((curr_y - curr_height - 200))
- hyprctl dispatch movewindowpixel "exact $curr_x $off_y,address:$TERMINAL_ADDR" >/dev/null 2>&1
- ensure_unpinned "$TERMINAL_ADDR"
- set_hidden_state "hidden"
- else
- debug_echo "Could not get window geometry, moving off-screen without animation"
- hyprctl dispatch movewindowpixel "exact 0 -1000,address:$TERMINAL_ADDR" >/dev/null 2>&1
- ensure_unpinned "$TERMINAL_ADDR"
- set_hidden_state "hidden"
- fi
- fi
+if [ "$HIDDEN_STATE" = "hidden" ]; then
+ show_terminal "$TERMINAL_ADDR"
else
- debug_echo "No existing terminal found, creating new one"
- if spawn_terminal; then
- TERMINAL_ADDR=$(get_terminal_address)
- if [ -n "$TERMINAL_ADDR" ]; then
- hyprctl dispatch focuswindow "address:$TERMINAL_ADDR"
- fi
- fi
+ hide_terminal "$TERMINAL_ADDR"
fi
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage