hypr-dotfiles/hypr/scripts/dynamic-borders.sh
Jeena 496fd6fc67 hypr: migrate runtime IPC calls to the Hyprland 0.56 Lua syntax
Hyprland 0.56 removed the string form of `hyprctl dispatch` and
`hyprctl keyword` entirely: the argument is now evaluated as Lua
(hl.dispatch expects a dispatcher object from hl.dsp.*), and `setprop`
lost the `noborder` property in favour of border_size 0. Everything
that shelled out to these silently broke — wlogout's logout button
did nothing, idle screen-off and lid-close DPMS died, borders stopped
tracking single-window workspaces, and display mirroring was gone.

All callers now use the documented forms: `hyprctl dispatch
"hl.dsp.*"` for dispatchers and `hyprctl eval "hl.monitor(...)"` for
monitor rules. dynamic-borders.sh gets a set_border() helper around
the new window.set_prop dispatcher.

wlogout layouts additionally cannot contain escaped quotes at all:
it parses them with jsmn, which never unescapes strings, so \" used
to reach the shell verbatim and break the command with a syntax
error. Actions now use single quotes only.
2026-09-20 14:03:30 +09:00

133 lines
5.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Hyprland 0.56 removed the "noborder" window prop (use border_size 0) and
# "hyprctl dispatch <string>" — runtime props now go through the Lua API.
# Keep in sync with decoration.border_size in hyprland.lua.
BORDER_SIZE=3
# set_border <address> <1 = hide border, 0 = show border>
set_border() {
local hex=${1#address:}; hex=${hex#0x}
local size=0
[[ $2 == 0 ]] && size=$BORDER_SIZE
hyprctl dispatch "hl.dsp.window.set_prop({prop='border_size', value='$size', window='address:0x$hex'})" >/dev/null
}
function handle {
if [[ ${1:0:10} == "openwindow" ]]
then
window_id=$(echo $1 | cut --delimiter ">" --fields=3 | cut --delimiter "," --fields=1)
workspace_id=$(echo $1 | cut --delimiter ">" --fields=3 | cut --delimiter "," --fields=2)
if [[ $workspace_id == "special" ]]
then
workspace_id=-99
fi
windows=$(hyprctl workspaces -j | jq ".[] | select(.id == $workspace_id) | .windows")
if [[ $windows -eq 1 ]]
then
floating_status=$(hyprctl clients -j | jq ".[] | select(.address == \"0x$window_id\" ) | .floating" )
if [[ $floating_status == "false" ]]
then
set_border "0x$window_id" 1
else
set_border "0x$window_id" 0
return
fi
elif [[ $windows -eq 2 ]]
then
addresses=$(hyprctl clients -j | jq -r --arg foo "$foo" ".[] | select(.workspace.id == $workspace_id) | .address")
for address in $addresses
do
if [[ "$address" != "$window_id" ]]; then
set_border "$(echo $address | xargs)" 0
fi
done
fi
elif [[ ${1:0:10} == "movewindow" ]]
then
window_id=$(echo $1 | cut --delimiter ">" --fields=3 | cut --delimiter "," --fields=1)
workspace_id=$(echo $1 | cut --delimiter ">" --fields=3 | cut --delimiter "," --fields=2)
# Sepcial workspaces have an id of -99, they need to be handled separately
if [[ $workspace_id == "special" ]]
then
workspace_id=-99
fi
windows=$(hyprctl workspaces -j | jq ".[] | select(.id == $workspace_id) | .windows")
if [[ $windows -eq 1 ]]
then
# Check if the current window is floating and then set the border accordingly
floating_status=$(hyprctl clients -j | jq ".[] | select(.address == \"0x$window_id\" ) | .floating" )
if [[ $floating_status == "false" ]]
then
set_border "0x$window_id" 1
else
set_border "0x$window_id" 0
return
fi
elif [[ $windows -eq 2 ]]
then
addresses=$(hyprctl clients -j | jq -r --arg foo "$foo" ".[] | select(.workspace.id == $workspace_id) | .address")
for address in $addresses
do
if [[ "$address" != "$window_id" ]]; then
set_border "$(echo $address | xargs)" 0
fi
done
fi
# Handle all the other workspaces with only one window
single_window_workspaces=$(hyprctl workspaces -j | jq '.[] | select(.windows == 1)' | jq ".id")
for workspace in $single_window_workspaces
do
window=$(hyprctl clients -j | jq ".[] | select(.workspace.id == $workspace) | .address")
set_border "$(echo $window | xargs)" 1
done
elif [[ ${1:0:11} == "closewindow" ]]
then
workspace_id=$(hyprctl activewindow -j | jq ".workspace.id")
windows=$(hyprctl workspaces -j | jq ".[] | select(.id == $workspace_id) | .windows")
if [[ $windows -eq 1 ]]
then
window_id=$(hyprctl activewindow -j | jq -r ".address")
floating_status=$(hyprctl activewindow -j | jq ".floating")
if [[ $floating_status == "false" ]]
then
set_border "$window_id" 1
else
set_border "$window_id" 0
return
fi
fi
elif [[ ${1:0:18} == "changefloatingmode" ]]
then
floating_status=$(echo $1 | cut --delimiter ">" --fields 3 | cut --delimiter "," --fields 2)
address="0x$(echo $1 | cut --delimiter ">" --fields 3 | cut --delimiter "," --fields 1)"
workspace_id=$(hyprctl clients -j | jq --arg address "$address" '.[] | select(.address == $address) | .workspace.id')
if [[ $floating_status -eq 1 ]]
then
set_border "$address" 0
else
no_windows=$(hyprctl workspaces -j | jq ".[] | select(.id == $workspace_id) | .windows")
if [[ $no_windows -eq 1 ]]
then
set_border "$address" 1
else
set_border "$address" 0
fi
fi
fi
}
# Socket directory has changed in Hyprland v0.40.0
# socat - UNIX-CONNECT:/tmp/hypr/$(echo $HYPRLAND_INSTANCE_SIGNATURE)/.socket2.sock | while read line; do handle $line; done
socat -U - UNIX-CONNECT:$(echo $XDG_RUNTIME_DIR)/hypr/$(echo $HYPRLAND_INSTANCE_SIGNATURE)/.socket2.sock | while read line; do handle $line; done