Files
bananarchy/overlay/rootfs/usr/bin/sxmo_wmmenu.sh
T
2026-10-19 09:23:54 +03:00

430 lines
9.6 KiB
Bash
Executable File

#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2022 Sxmo Contributors
# this script is a menu which lets the user perform some WM actions.
# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. sxmo_common.sh
# shellcheck source=configs/default_hooks/sxmo_hook_icons.sh
. sxmo_hook_icons.sh
set -e
_movetowssubmenu() {
for ws in $(seq "${SXMO_WORKSPACE_WRAPPING:-4}"); do
printf "%s Move to WS %s\n" "$ws" "$ws"
done
}
# A menu which allows to move windows or toggle floating.
swaymovemenu() {
CHOICES="$(cat <<EOF
$icon_cls Close Menu
$icon_aru Move Up
$icon_ard Move Down
$icon_arl Move Left
$icon_arr Move Right
$icon_wn2 Toggle Floating
$icon_ac1 Move Scratchpad
$(_movetowssubmenu)
EOF
)"
MOVEINDEX=0
while : ; do
# Remove current workspace from the list
CHOICES="$(
printf "%s" "$CHOICES" |
grep -v "$(
swaymsg -t get_workspaces |
jq -r '
.[] | select(.focused).name
')"
)"
PICKED="$(printf "%s" "$CHOICES" | dmenu -I "$MOVEINDEX" -p "Move menu")"
MOVEINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
?" Move to WS "?)
sxmo_wm.sh moveworkspace "${PICKED%" Move to WS "?}"
return
;;
"$icon_wn2 Toggle Floating")
swaymsg floating toggle
;;
*)
printf "%s" "$PICKED" | tr -cd '\000-\177' | xargs swaymsg
;;
esac
done
}
# The generic sway menu
swaywmmenu() {
WMINDEX=0
while : ; do
# generate layout line with format "current → next → 2nd next"
CURRENT_LAYOUT="$(
swaymsg -t get_tree |
jq -r 'recurse(.nodes[]) |
if select(.nodes[].focused).layout=="output" then
select(.nodes[].focused).nodes[].layout
else select(.nodes[].focused).layout end'
)"
if [ -n "$CURRENT_LAYOUT" ]; then
if [ "$CURRENT_LAYOUT" = "splitv" ]; then
LAYOUT_LINE="splitv $icon_arr splith $icon_arr tabbed"
elif [ "$CURRENT_LAYOUT" = "splith" ]; then
LAYOUT_LINE="splith $icon_arr tabbed $icon_arr splitv"
else
LAYOUT_LINE="tabbed $icon_arr splitv $icon_arr splith"
fi
fi
CHOICES="$(grep . <<EOF
$icon_cls Close Menu
$icon_win Next window
$icon_mov Move menu
$icon_rld Switch menu
$([ -n "$CURRENT_LAYOUT" ] && printf "%s" "$icon_rld $LAYOUT_LINE")
$icon_mnu Split vertical
$icon_grd Split horizontal
$icon_tab Tabbed layout
$icon_exp Focus parent
$icon_trh Kill window
EOF
)"
PICKED="$(printf "%s" "$CHOICES" | grep . | dmenu -I "$WMINDEX" -p "WM Menu")"
WMINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
"$icon_win Next window")
swaymsg focus next
return
;;
"$icon_mov Move menu")
swaymovemenu
;;
"$icon_rld Switch menu")
swaywindowswitcher
;;
"$icon_rld $LAYOUT_LINE")
sxmo_wm.sh togglelayout
;;
"$icon_mnu Split vertical")
swaymsg layout splitv
swaymsg splitv
return
;;
"$icon_grd Split horizontal")
swaymsg layout splith
swaymsg splith
return
;;
"$icon_tab Tabbed layout")
swaymsg layout tabbed
return
;;
"$icon_exp Focus parent")
swaymsg focus parent
;;
"$icon_trh Kill window")
sxmo_killwindow.sh
;;
*)
printf "%s" "$PICKED" | tr -cd '\000-\177' | xargs swaymsg
esac
done
}
# The generic river menu
riverwmmenu() {
WMINDEX=0
while : ; do
# For now justs swap between fullscreen and tiled.
LAYOUT_LINE="tiled $icon_arr fullscreen"
CHOICES="$(grep . <<EOF
$icon_cls Close Menu
$icon_mov Move menu
$icon_rld Switch menu
$(printf "%s" "$icon_rld $LAYOUT_LINE")
$icon_trh Kill window
EOF
)"
PICKED="$(printf "%s" "$CHOICES" | grep . | dmenu -I "$WMINDEX" -p "WM Menu")"
WMINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
"$icon_mov Move menu")
rivermovemenu
;;
"$icon_rld Switch menu")
riverwindowswitcher
;;
"$icon_rld $LAYOUT_LINE")
sxmo_wm.sh togglelayout
;;
"$icon_trh Kill window")
sxmo_killwindow.sh
;;
*)
printf "%s" "$PICKED" | tr -cd '\000-\177' | xargs swaymsg
esac
done
}
_rivermovetowssubmenu() {
for ws in $(seq "${SXMO_WORKSPACE_WRAPPING:-9}"); do
printf "%s Move to WS %s\n" "$ws" "$ws"
done
}
# A menu which allows to move windows or toggle floating.
rivermovemenu() {
CHOICES="$(cat <<EOF
$icon_cls Close Menu
$icon_wn2 Toggle Floating
$(_rivermovetowssubmenu)
EOF
)"
MOVEINDEX=0
while : ; do
# Remove current workspace from the list
CHOICES="$(
printf "%s" "$CHOICES" |
grep -v "$(
river-bedload -print focused |
jq -r ' .[] | .focused_id')"
)"
PICKED="$(printf "%s" "$CHOICES" | dmenu -I "$MOVEINDEX" -p "Move menu")"
MOVEINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
?" Move to WS "?)
sxmo_wm.sh moveworkspace "${PICKED%" Move to WS "?}"
return
;;
"$icon_wn2 Toggle Floating")
riverctl toggle-float
;;
esac
done
}
riverwindowswitcher() {
SWITCHINDEX=0
while : ; do
# There is currently no easy in river to get the tag of a given window,
# skip the window part of this menu for now.
# Get the container ID from the node tree
CHOICES="$(
cat <<EOF
$icon_cls Close Menu
$icon_arl Previous Workspace
$icon_arr Next Workspace
$(_rivermovetowssubmenu | grep -v "$(
river-bedload -print focused |
jq -r ' .[] | .focused_id')")
EOF
)"
PICKED="$(printf "%s" "$CHOICES" | dmenu -p "Switch menu" -I "$SWITCHINDEX")"
SWITCHINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
"$icon_arr Next Workspace")
sxmo_wm.sh nextworkspace
;;
"$icon_arl Previous Workspace")
sxmo_wm.sh previousworkspace
;;
?" Move to WS "?)
sxmo_wm.sh workspace "${PICKED%" Move to WS "?}"
return
;;
## When we'll have proper window switching:
# *)
# # Requires the actual `id` to be at the end and between parentheses
# CON_ID=${PICKED##*(}
# CON_ID=${CON_ID%)}
# swaymsg "[con_id=$CON_ID]" focus
# ;;
esac
done
}
dwmwmmenu() {
WMINDEX=0
while : ; do
CHOICES="$(
cat <<EOF
$icon_cls Close Menu
$(_movetowssubmenu)
$icon_rld Shift stack
$icon_grd Toggle Layout
$icon_trh Kill window
EOF
)"
PICKED="$(printf "%s" "$CHOICES" | dmenu -I "$WMINDEX" -p "WM Menu")"
WMINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
?" Move to WS "?)
sxmo_wm.sh moveworkspace "${PICKED%" Move to WS "?}"
;;
"$icon_rld Shift stack")
sxmo_wm.sh switchfocus
;;
"$icon_grd Toggle Layout")
sxmo_wm.sh togglelayout
;;
"$icon_trh Kill window")
sxmo_killwindow.sh
;;
esac
done
}
i3windowswitcher() {
SWITCHINDEX=0
while : ; do
FORMAT='"W:" + .workspace + " | " + .app_id + " - " + .name + " (" + .id + ")"'
WINDOWSLIST="$(
i3-msg -t get_tree |
jq -r ".nodes[]
| {output: .name, content: .nodes[]}
| {output: .output, workspace: .content.name, apps: .content
| ..
| {id: .id?|tostring, name: .name?, app_id: .app_id?, shell: .shell?}
| select(.app_id != null or .shell != null)}
| {output: .output, workspace: .workspace,
id: .apps.id, app_id: .apps.app_id, name: .apps.name }
| $FORMAT
| tostring
"
)"
# Get the container ID from the node tree
CHOICES="$(
cat <<EOF
$icon_cls Close Menu
$icon_arl Previous Workspace
$icon_arr Next Workspace
$WINDOWSLIST
EOF
)"
PICKED="$(printf "%s" "$CHOICES" | dmenu -p "Switch menu" -I "$SWITCHINDEX")"
SWITCHINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
"$icon_arr Next Workspace")
sxmo_wm.sh nextworkspace
;;
"$icon_arl Previous Workspace")
sxmo_wm.sh previousworkspace
;;
*)
# Requires the actual `id` to be at the end and between parentheses
CON_ID=${PICKED##*(}
CON_ID=${CON_ID%)}
i3-msg "[con_id=$CON_ID]" focus
;;
esac
done
}
swaywindowswitcher() {
SWITCHINDEX=0
while : ; do
FORMAT='"W:" + .workspace + " | " + .app_id + " - " + .name + " (" + .id + ")"'
WINDOWSLIST="$(
swaymsg -t get_tree |
jq -r ".nodes[]
| {output: .name, content: .nodes[]}
| {output: .output, workspace: .content.name, apps: .content
| ..
| {id: .id?|tostring, name: .name?, app_id: .app_id?, shell: .shell?}
| select(.app_id != null or .shell != null)}
| {output: .output, workspace: .workspace,
id: .apps.id, app_id: .apps.app_id, name: .apps.name }
| $FORMAT
| tostring
"
)"
# Get the container ID from the node tree
CHOICES="$(
cat <<EOF
$icon_cls Close Menu
$icon_arl Previous Workspace
$icon_arr Next Workspace
$WINDOWSLIST
EOF
)"
PICKED="$(printf "%s" "$CHOICES" | dmenu -p "Switch menu" -I "$SWITCHINDEX")"
SWITCHINDEX="$(($(printf "%s" "$CHOICES" | grep -nm1 "^$PICKED$" | cut -d: -f1) -1))"
case "$PICKED" in
""|"$icon_cls Close Menu")
return
;;
"$icon_arr Next Workspace")
sxmo_wm.sh nextworkspace
;;
"$icon_arl Previous Workspace")
sxmo_wm.sh previousworkspace
;;
*)
# Requires the actual `id` to be at the end and between parentheses
CON_ID=${PICKED##*(}
CON_ID=${CON_ID%)}
swaymsg "[con_id=$CON_ID]" focus
;;
esac
done
}
if [ -n "$1" ]; then
"$SXMO_WM$1"
exit
fi
case "$SXMO_WM" in
dwm|i3) dwmwmmenu ;;
sway) swaywmmenu ;;
river) riverwmmenu ;;
esac