mirror of
https://github.com/elenapan/dotfiles.git
synced 2026-01-08 01:37:38 +08:00
284 lines
8.5 KiB
Bash
Executable file
284 lines
8.5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# This script:
|
|
# - Changes the visibility of an eww widget, by also setting its state variable
|
|
# and accounting for a delay to allow the hiding animation to complete.
|
|
# Related: https://github.com/elkowar/eww/issues/196
|
|
# - Manages pre-show, post-show, pre-hide and post-hide commands.
|
|
# - Automatically enables or disables the respective sway binding mode when
|
|
# needed.
|
|
# - Automatically opens the dismiss-overlay widget when needed which can be used
|
|
# to achieve "close when clicking outside the widget" functionality.
|
|
# - Before showing the selected widget, it automatically hides all other widgets
|
|
# if needed.
|
|
#
|
|
# The script assumes that:
|
|
# - The widget state variable is in the format ${widget_name}-visible
|
|
# (e.g. variable `sidebar-visible` refers to the visibility state of the
|
|
# `sidebar` widget)
|
|
# Value: true/false
|
|
# - Windows that need overlays in secondary monitors declare an `is-secondary`
|
|
# argument.
|
|
#
|
|
# Usage:
|
|
# manage (show|hide|toggle|hide_all_except) widget_name
|
|
|
|
eww="$HOME/.config/eww/scripts"
|
|
|
|
# Fullscreen widgets will be shown in the primary monitor, and if needed,
|
|
# overlays will be shown in the following secondary monitors.
|
|
# You can find OUTPUT_NAME with `swaymsg -t get_outputs`
|
|
secondary_monitors=(
|
|
"HEADLESS-3"
|
|
"HDMI-A-1"
|
|
)
|
|
|
|
# Overlay widgets are spawned in all monitors (using the `is-secondary` argument
|
|
# to customize their appearance or functionality depending on monitor type)
|
|
declare -A overlay_widgets
|
|
overlay_widgets[powermenu]=true
|
|
|
|
# How long to wait for the revealer animation to complete. This should be
|
|
# match the revealer delay in the respective *.yuck files.
|
|
declare -A revealer_delay
|
|
revealer_delay[sidebar]=0.3
|
|
revealer_delay[powermenu]=0.3
|
|
revealer_delay[split-indicator]=0.3
|
|
revealer_delay[mode-indicator]=0.3
|
|
revealer_delay[microphone-indicator]=0.2
|
|
revealer_delay[networks]=0.3
|
|
revealer_delay[alarms]=0.3
|
|
|
|
# Only one of these should be visible at a time
|
|
mutually_exclusive_widgets=(
|
|
"sidebar"
|
|
"networks"
|
|
"alarms"
|
|
"powermenu"
|
|
)
|
|
|
|
# These widgets capture keys while they are visible (through sway binding
|
|
# modes). The convention currently is that for every such widget there exists a
|
|
# sway binding mode with the same name that starts with an underscore.
|
|
declare -A mode_widget
|
|
mode_widget[sidebar]="_sidebar"
|
|
mode_widget[networks]="_networks"
|
|
mode_widget[alarms]="_alarms"
|
|
mode_widget[powermenu]="_powermenu"
|
|
|
|
# Clicking out of these widgets should close them
|
|
dismiss_when_clicking_outside_widgets=(
|
|
"sidebar"
|
|
"networks"
|
|
"alarms"
|
|
)
|
|
|
|
declare -A pre_show_cmds
|
|
# shellcheck disable=2016
|
|
pre_show_cmds[networks]='[ "$(eww get networks-ping-loading)" = "true" ] || eww update networks-ping-result=ping'
|
|
|
|
declare -A post_show_cmds
|
|
post_show_cmds[networks]="($eww/networks.sh update_networks &)"
|
|
|
|
declare -A pre_hide_cmds
|
|
|
|
declare -A post_hide_cmds
|
|
post_hide_cmds[powermenu]='eww update powermenu-button-selected= screen-lock-input='
|
|
post_hide_cmds[alarms]='eww update alarms-state=select-type'
|
|
|
|
# ------------------------------------------------------------
|
|
|
|
cmd="$1"
|
|
widget_name="$2"
|
|
active_windows="$(eww active-windows 2>/dev/null)"
|
|
active_monitors="$(swaymsg -t get_outputs | jq -r '.[] | .name')"
|
|
|
|
# Helpers
|
|
_is_secondary_monitor() {
|
|
mon="$1"
|
|
grep -q "^${mon}$" <<< "$(printf '%s\n' "${secondary_monitors[@]}")"
|
|
}
|
|
|
|
_open() {
|
|
widget_name="$1"
|
|
|
|
if [[ -v overlay_widgets["$widget_name"] ]]; then
|
|
extra_args="--arg ${widget_name}:is-secondary=false"
|
|
for mon in ${active_monitors}; do
|
|
if _is_secondary_monitor "$mon"; then
|
|
extra_args+=" ${widget_name}:${widget_name}-${mon} --arg ${widget_name}-${mon}:screen=${mon} --arg ${widget_name}-${mon}:is-secondary=true"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# shellcheck disable=2086
|
|
eww open-many "$widget_name" $extra_args >/dev/null
|
|
}
|
|
|
|
_close() {
|
|
widget_name="$1"
|
|
|
|
if [[ -v overlay_widgets["$widget_name"] ]]; then
|
|
for mon in ${active_monitors}; do
|
|
if _is_secondary_monitor "$mon"; then
|
|
extra_args+=" ${widget_name}-${mon}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# shellcheck disable=2086
|
|
eww close "$widget_name" $extra_args >/dev/null
|
|
}
|
|
|
|
_mode_enable() {
|
|
widget_name="$1"
|
|
if [[ -v mode_widget["$widget_name"] ]]; then
|
|
swaymsg -q mode "${mode_widget[$widget_name]}"
|
|
fi
|
|
}
|
|
_mode_disable() {
|
|
widget_name="$1"
|
|
if [[ -v mode_widget["$widget_name"] ]]; then
|
|
swaymsg -q mode default
|
|
fi
|
|
}
|
|
|
|
_pre_show() {
|
|
widget_name="$1"
|
|
if [[ -v pre_show_cmds["$widget_name"] ]]; then
|
|
sh <<< "${pre_show_cmds[$widget_name]}"
|
|
fi
|
|
if [[ ${mutually_exclusive_widgets[*]} =~ $widget_name ]]; then
|
|
hide_all_except "$widget_name"
|
|
fi
|
|
}
|
|
|
|
_post_show() {
|
|
widget_name="$1"
|
|
if [[ -v post_show_cmds["$widget_name"] ]]; then
|
|
sh <<< "${post_show_cmds[$widget_name]}"
|
|
fi
|
|
if [[ ${dismiss_when_clicking_outside_widgets[*]} =~ $widget_name ]]; then
|
|
secondary_overlays=''
|
|
# Show an overlay for all active secondary monitors
|
|
for mon in ${active_monitors}; do
|
|
if _is_secondary_monitor "$mon"; then
|
|
secondary_overlays+=" dismiss-overlay:dismiss-overlay-${mon} --arg dismiss-overlay-${mon}:screen=${mon}"
|
|
fi
|
|
done
|
|
|
|
# shellcheck disable=2086
|
|
eww open-many \
|
|
dismiss-overlay:dismiss-overlay \
|
|
$secondary_overlays \
|
|
--arg widget-to-dismiss="${widget_name}" \
|
|
>/dev/null;
|
|
fi
|
|
}
|
|
|
|
_pre_hide() {
|
|
widget_name="$1"
|
|
if [[ -v pre_hide_cmds["$widget_name"] ]]; then
|
|
sh <<< "${pre_hide_cmds[$widget_name]}"
|
|
fi
|
|
if [[ ${dismiss_when_clicking_outside_widgets[*]} =~ $widget_name ]]; then
|
|
secondary_overlays=''
|
|
# Hide the overlay for all active secondary monitors
|
|
for mon in ${active_monitors}; do
|
|
if _is_secondary_monitor "$mon"; then
|
|
secondary_overlays+=" dismiss-overlay-${mon}"
|
|
fi
|
|
done
|
|
|
|
# shellcheck disable=2086
|
|
eww close \
|
|
dismiss-overlay \
|
|
$secondary_overlays \
|
|
>/dev/null;
|
|
fi
|
|
}
|
|
|
|
_post_hide() {
|
|
widget_name="$1"
|
|
if [[ -v post_hide_cmds["$widget_name"] ]]; then
|
|
sh <<< "${post_hide_cmds[$widget_name]}"
|
|
fi
|
|
}
|
|
|
|
_show() {
|
|
widget_name="$1"
|
|
_pre_show "$widget_name"
|
|
_mode_enable "$widget_name"
|
|
_open "$widget_name"
|
|
eww update "${widget_name}"-visible=true
|
|
_post_show "$widget_name"
|
|
}
|
|
|
|
_hide() {
|
|
widget_name="$1"
|
|
delay="${revealer_delay[$widget_name]:-0}" # default delay is 0
|
|
_pre_hide "$widget_name"
|
|
_mode_disable "$widget_name"
|
|
eww update "${widget_name}"-visible=false
|
|
sleep "$delay"
|
|
_close "$widget_name"
|
|
_post_hide "$widget_name"
|
|
}
|
|
|
|
# Available commands
|
|
toggle() {
|
|
widget_name="$1"
|
|
if [ "$(eww get "${widget_name}-visible")" = "false" ]; then
|
|
_show "$widget_name"
|
|
else
|
|
_hide "$widget_name"
|
|
fi
|
|
}
|
|
|
|
show() {
|
|
if [ "$(eww get "${widget_name}-visible")" = "false" ]; then
|
|
_show "$widget_name"
|
|
fi
|
|
}
|
|
|
|
hide() {
|
|
if [ "$(eww get "${widget_name}-visible")" = "true" ]; then
|
|
_hide "$widget_name"
|
|
fi
|
|
}
|
|
|
|
hide_all_except() {
|
|
widget_except="$1"
|
|
|
|
for widget in "${mutually_exclusive_widgets[@]}"; do
|
|
if [[ ! "$widget" == "$widget_except" ]] && grep -e "^${widget}:" >/dev/null <<< "$active_windows"; then
|
|
delay="${revealer_delay[$widget]:-0}" # default delay is 0
|
|
# We do not call the `hide` helper because we do not necessarily
|
|
# want to mess with the sway modes.
|
|
# The widget to be activated will set its own mode through the
|
|
# `show` function if needed.
|
|
# If:
|
|
# - Widget to be hidden uses a mode AND
|
|
# - Widget to stay active does not use any mode
|
|
# -> We need to disable the mode.
|
|
# We need to do this outside the subshell running in the background
|
|
# to avoid a race condition causing the mode that was enabled in
|
|
# `show` to be disabled right after.
|
|
if [[ -v mode_widget["$widget"] && ! -v mode_widget["$widget_except"] ]]; then
|
|
swaymsg -q mode default
|
|
fi
|
|
|
|
# Run in the background to avoid delaying the next command while
|
|
# waiting for the animation
|
|
(
|
|
_pre_hide "$widget"
|
|
eww update "${widget}-visible"=false
|
|
sleep "$delay"
|
|
_close "$widget"
|
|
_post_hide "$widget"
|
|
)&
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Run selected cmd
|
|
$cmd "$widget_name"
|