update:new mmsg syntax for window management

This commit is contained in:
2026-06-15 20:21:13 +09:00
parent 2965a3a3cd
commit 69ed82a0e8
2 changed files with 97 additions and 54 deletions

View File

@@ -6,35 +6,108 @@ if ! command -v mmsg >/dev/null 2>&1; then
exit 1 exit 1
fi fi
if ! command -v jq >/dev/null 2>&1; then
echo "error: jq not found; install with: sudo pacman -S jq" >&2
exit 1
fi
mode="${1:-all}" mode="${1:-all}"
case "$mode" in case "$mode" in
all|single) ;; all|single) ;;
*) *)
echo "usage: $(basename "$0") [single]" >&2 echo "usage: $(basename "$0") [all|single]" >&2
exit 2 exit 2
;; ;;
esac esac
mapfile -t outputs < <(mmsg -O | awk 'NF { print $1 }') get_monitors_json() {
out_count=${#outputs[@]} local json
json="$(mmsg get all-monitors 2>&1)"
if ! jq -e '.monitors | type == "array"' >/dev/null 2>&1 <<<"$json"; then
echo "error: failed to read monitors from mmsg:" >&2
echo "$json" >&2
exit 1
fi
printf '%s\n' "$json"
}
get_outputs() {
get_monitors_json | jq -r '.monitors[].name'
}
get_active_monitor() {
local json="$1"
local active
active="$(jq -r '.monitors[] | select(.active == true) | .name' <<<"$json" | head -n1)"
if [[ -n "$active" && "$active" != "null" ]]; then
echo "$active"
else
jq -r '.monitors[0].name' <<<"$json"
fi
}
get_active_tag() {
local mon="$1"
get_monitors_json | jq -r --arg mon "$mon" '
.monitors[]
| select(.name == $mon)
| (.active_tags[0] // 1)
'
}
get_tag_clients() {
local mon="$1"
local tag="$2"
get_monitors_json | jq -r --arg mon "$mon" --argjson tag "$tag" '
.monitors[]
| select(.name == $mon)
| (.tags[] | select(.index == $tag) | .client_count) // 0
'
}
get_total_clients() {
local mon="$1"
get_monitors_json | jq -r --arg mon "$mon" '
.monitors[]
| select(.name == $mon)
| [.tags[].client_count]
| add // 0
'
}
dispatch() {
mmsg dispatch "$1" >/dev/null
}
json="$(get_monitors_json)"
mapfile -t outputs < <(jq -r '.monitors[].name' <<<"$json")
out_count="${#outputs[@]}"
if (( out_count == 0 )); then if (( out_count == 0 )); then
echo "error: no monitors detected" >&2 echo "error: no monitors detected" >&2
exit 1 exit 1
fi fi
if (( out_count == 1 )); then if (( out_count == 1 )); then
echo "info: only one monitor connected, nothing to move" echo "info: only one monitor detected by MangoWM, nothing to move"
exit 0 exit 0
fi fi
if (( out_count > 2 )); then if (( out_count > 2 )); then
echo "error: script supports max 2 monitors, found ${out_count}" >&2 echo "error: script supports max 2 monitors, found ${out_count}" >&2
printf 'monitors:\n' >&2
printf ' %s\n' "${outputs[@]}" >&2
exit 2 exit 2
fi fi
active="$(mmsg -g -o | awk '$2=="selmon" && $3=="1" { print $1; exit }')" active="$(get_active_monitor "$json")"
if [[ -z "$active" ]]; then
active="${outputs[0]}"
fi
target="" target=""
for out in "${outputs[@]}"; do for out in "${outputs[@]}"; do
@@ -49,49 +122,12 @@ if [[ -z "$target" ]]; then
exit 1 exit 1
fi fi
get_active_tag() {
local mon="$1"
local active_mask
active_mask="$(mmsg -g -t | awk -v m="$mon" '$1==m && $2=="tags" && $3 ~ /^[0-9]+$/ && $4 ~ /^[0-9]+$/ { print $4; exit }')"
if [[ ! "$active_mask" =~ ^[0-9]+$ ]]; then
echo 1
return
fi
for tag in {1..9}; do
if (( active_mask & (1 << (tag - 1)) )); then
echo "$tag"
return
fi
done
echo 1
}
get_tag_clients() {
local mon="$1" tag="$2"
local n
n="$(mmsg -g -t | awk -v m="$mon" -v t="$tag" '$1==m && $2=="tag" && $3==t { print $5; exit }')"
if [[ "$n" =~ ^[0-9]+$ ]]; then
echo "$n"
else
echo 0
fi
}
get_total_clients() {
local mon="$1"
local n
n="$(mmsg -g -t | awk -v m="$mon" '$1==m && $2=="clients" { print $3; exit }')"
if [[ "$n" =~ ^[0-9]+$ ]]; then
echo "$n"
else
echo 0
fi
}
if [[ "$mode" == "single" ]]; then if [[ "$mode" == "single" ]]; then
echo "move-single: active=${active} target=${target}" echo "move-single: active=${active} target=${target}"
mmsg -o "$active" -s -d "tagmon,${target},1" >/dev/null
dispatch "focusmon,${active}"
dispatch "tagmon,${target},1"
echo "move-single: done" echo "move-single: done"
exit 0 exit 0
fi fi
@@ -107,16 +143,25 @@ fi
echo "move-all: active=${active} target=${target} target_tag=${target_tag} total=${source_total}" echo "move-all: active=${active} target=${target} target_tag=${target_tag} total=${source_total}"
moved=0 moved=0
for tag in {1..9}; do for tag in {1..9}; do
while :; do while :; do
before="$(get_tag_clients "$active" "$tag")" before="$(get_tag_clients "$active" "$tag")"
(( before > 0 )) || break (( before > 0 )) || break
mmsg -o "$active" -s -t "$tag" >/dev/null dispatch "focusmon,${active}"
mmsg -o "$active" -s -d "tagcrossmon,${target_tag},${target}" >/dev/null
mmsg -s -d "focusmon,${active}" >/dev/null || true # Select source tag.
# If your Mango build uses tag masks instead of tag indexes for view,
# this line may need changing.
dispatch "view,${tag}"
dispatch "tagcrossmon,${target_tag},${target}"
dispatch "focusmon,${active}" || true
after="$(get_tag_clients "$active" "$tag")" after="$(get_tag_clients "$active" "$tag")"
if (( after < before )); then if (( after < before )); then
(( moved += (before - after) )) (( moved += (before - after) ))
else else

View File

@@ -73,8 +73,6 @@ yay -S ttf-nerd-fonts-symbols
fc-cache -fv fc-cache -fv
# monitor management # monitor management
# use wlr-randr to set kanshi settings when getting monitor name
yay -S wdisplays wlr-randr
sudo pacman -S kanshi sudo pacman -S kanshi
# bluetooth # bluetooth