~mil/sxmo-utils

8a27933c4788ffca88408fbeeb1b8fa618bd5d69 — Stacy Harper 2 months ago b1403f9
SWMO - SXMO over Wayland

This is a huge patch for Swmo, Sxmo over Sway.

It is Dwm backward compatible so dwm users should not expect regressions.

If you install all dependencies, you then can toggle between Sway and Dwm using a new config entry. It will reboot the phone.

This commit also contains:
    * Make the modemmonitor bullet proof
    * various other smaller fixes

Signed-off-by: Stacy Harper <contact@stacyharper.net>
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
54 files changed, 1497 insertions(+), 542 deletions(-)

M Makefile
A configs/appcfg/foot.ini
A configs/appcfg/mako.conf
A configs/appcfg/sway_template
M configs/appcfg/xinit_template
A configs/applications/swmo.desktop
M configs/default_hooks/inputhandler
M configs/default_hooks/lisgdstart
M configs/default_hooks/unlocksim
M scripts/appscripts/sxmo_files.sh
M scripts/appscripts/sxmo_record.sh
M scripts/appscripts/sxmo_reddit.sh
M scripts/appscripts/sxmo_rss.sh
M scripts/appscripts/sxmo_timer.sh
M scripts/appscripts/sxmo_websearch.sh
M scripts/appscripts/sxmo_youtube.sh
M scripts/core/sxmo_appmenu.sh
M scripts/core/sxmo_bluetoothmenu.sh
M scripts/core/sxmo_brightness.sh
M scripts/core/sxmo_common.sh
M scripts/core/sxmo_contactmenu.sh
M scripts/core/sxmo_dmenu.sh
M scripts/core/sxmo_dmenu_with_kb.sh
M scripts/core/sxmo_gpsutil.sh
M scripts/core/sxmo_hotspot.sh
A scripts/core/sxmo_idle.sh
M scripts/core/sxmo_inputhandler.sh
M scripts/core/sxmo_killwindow.sh
M scripts/core/sxmo_migrate.sh
A scripts/core/sxmo_multikey.sh
M scripts/core/sxmo_networks.sh
M scripts/core/sxmo_pipecomplete.sh
M scripts/core/sxmo_postwake.sh
M scripts/core/sxmo_rotate.sh
M scripts/core/sxmo_rtcwake.sh
M scripts/core/sxmo_screenlock.sh
M scripts/core/sxmo_statusbar.sh
M scripts/core/sxmo_surf_linkselect.sh
M scripts/core/sxmo_terminal.sh
M scripts/core/sxmo_timezonechange.sh
A scripts/core/sxmo_type.sh
M scripts/core/sxmo_urlhandler.sh
A scripts/core/sxmo_winit.sh
A scripts/core/sxmo_wm.sh
A scripts/core/sxmo_wmtoggle.sh
A scripts/core/sxmo_workspace.sh
M scripts/core/sxmo_xinit.sh
M scripts/modem/sxmo_modemcall.sh
M scripts/modem/sxmo_modemdial.sh
M scripts/modem/sxmo_modeminfo.sh
M scripts/modem/sxmo_modemmonitor.sh
M scripts/modem/sxmo_modemmonitortoggle.sh
M scripts/modem/sxmo_modemtext.sh
M scripts/notifications/sxmo_notificationsmenu.sh
M Makefile => Makefile +1 -0
@@ 39,6 39,7 @@ install: $(PROGRAMS)

	install -D -m 0644 -t $(DESTDIR)$(PREFIX)/share/applications/ configs/xdg/mimeapps.list
	install -D -m 0644 -t $(DESTDIR)$(PREFIX)/share/xsessions/ configs/applications/sxmo.desktop
	install -D -m 0644 -t $(DESTDIR)$(PREFIX)/share/wayland-sessions/ configs/applications/swmo.desktop

	install -D -m 0644 -t $(DESTDIR)/etc/sudoers.d/ configs/sudo/poweroff


A configs/appcfg/foot.ini => configs/appcfg/foot.ini +23 -0
@@ 0,0 1,23 @@
font=monospace:size=11

[colors]
# alpha=1.0
foreground=eaeaea
background=303030
regular0=1e1e1e  # black
regular1=d54e53  # red
regular2=b9ca4a  # green
regular3=e6c547  # yellow
regular4=7aa6da  # blue
regular5=c397d8  # magenta
regular6=70c0ba  # cyan
regular7=eaeaea  # white
bright0=666666   # bright black
bright1=ff3334   # bright red
bright2=9ec400   # bright green
bright3=e7c547   # bright yellow
bright4=7aa6da   # bright blue
bright5=b77ee0   # bright magenta
bright6=54ced6   # bright cyan
bright7=ffffff   # bright white


A configs/appcfg/mako.conf => configs/appcfg/mako.conf +16 -0
@@ 0,0 1,16 @@
default-timeout=5000
background-color=#ffffff
text-color=#000000
border-color=#000000
layer=overlay

[urgency=low]
default-timeout=3000
background-color=#222222
text-color=#888888

[urgency=high]
default-timeout=0
background-color=#900000
text-color=#ffffff
background-color=#ff0000

A configs/appcfg/sway_template => configs/appcfg/sway_template +237 -0
@@ 0,0 1,237 @@
# Default config for sway
#
# Copy this to ~/.config/sway/config and edit it to your liking.
#
# Read `man 5 sway` for a complete reference.

### Variables
#
# Logo key. Use Mod1 for Alt.
set $mod Mod4
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term foot
# Your preferred application launcher
# Note: pass the final command to swaymsg so that the resulting window can be opened
# on the original workspace that the command was run on.
set $menu bemenu-run

### Output configuration

output "DSI-1" {
         scale 2
         #transform 90
         bg /usr/share/sxmo/background.jpg fill
}

### Idle

exec sxmo_idle.sh start

#
# This will lock your screen after 300 seconds of inactivity, then turn off
# your displays after another 300 seconds, and turn your screens back on when
# resumed. It will also lock your screen before your computer goes to sleep.

### Input configuration
#
# Example configuration:
#
#   input "2:14:SynPS/2_Synaptics_TouchPad" {
#       dwt enabled
#       tap enabled
#       natural_scroll enabled
#       middle_emulation enabled
#   }
#
# You can get the names of your inputs by running: swaymsg -t get_inputs
# Read `man 5 sway-input` for more information about this section.

# repeat_delay how much time in milisec to consider it is hold pressed
#    should be long enough to trigger simple click easily but
#    should be short enough to trigger a repeat before the next threshold
# repeat_rate then how much key per second should be triggered
#    adapt it accordingly with the delay.
#    prefer a lower but enough value
# This is enough for 4 multikeys long presses
# Power button
input 0:0:axp20x-pek {
	repeat_delay 200
	repeat_rate 15
}
# Volume buttons
input 1:1:1c21800.lradc {
	repeat_delay 200
	repeat_rate 15
}
exec sxmo_multikey.sh clear

### Key bindings
#
# Basics:
#
    # Start a terminal
    bindsym $mod+Return exec $term
    bindsym --input-device=0:0:axp20x-pek XF86PowerOff exec sxmo_multikey.sh powerbutton "sxmo_inputhandler.sh powerbutton_one" "sxmo_inputhandler.sh powerbutton_two" "sxmo_inputhandler.sh powerbutton_three"
    bindsym $mod+p exec sxmo_appmenu.sh

    # Lock sxmo
    bindsym --input-device=1:1:1c21800.lradc XF86AudioRaiseVolume exec sxmo_multikey.sh volup "sxmo_inputhandler.sh volup_one" "sxmo_inputhandler.sh volup_two" "sxmo_inputhandler.sh volup_three"

    # Next workspace
    bindsym --input-device=1:1:1c21800.lradc XF86AudioLowerVolume exec sxmo_multikey.sh voldown "sxmo_inputhandler.sh voldown_one" "sxmo_inputhandler.sh voldown_two" "sxmo_inputhandler.sh voldown_three"

    # Kill focused window
    bindsym $mod+Shift+q kill

    # Start your launcher
    bindsym $mod+d exec $menu

    # Drag floating windows by holding down $mod and left mouse button.
    # Resize them with right mouse button + $mod.
    # Despite the name, also works for non-floating windows.
    # Change normal to inverse to use left mouse button for resizing and right
    # mouse button for dragging.
    floating_modifier $mod normal

    # Reload the configuration file
    bindsym $mod+Shift+c reload

    # Exit sway (logs you out of your Wayland session)
    bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
#
# Moving around:
#
    # Move your focus around
    bindsym $mod+$left focus left
    bindsym $mod+$down focus down
    bindsym $mod+$up focus up
    bindsym $mod+$right focus right
    # Or use $mod+[up|down|left|right]
    bindsym $mod+Left focus left
    bindsym $mod+Down focus down
    bindsym $mod+Up focus up
    bindsym $mod+Right focus right

    # Move the focused window with the same, but add Shift
    bindsym $mod+Shift+$left move left
    bindsym $mod+Shift+$down move down
    bindsym $mod+Shift+$up move up
    bindsym $mod+Shift+$right move right
    # Ditto, with arrow keys
    bindsym $mod+Shift+Left move left
    bindsym $mod+Shift+Down move down
    bindsym $mod+Shift+Up move up
    bindsym $mod+Shift+Right move right
#
# Workspaces:
#
    # Switch to workspace
    bindsym $mod+1 workspace number 1
    bindsym $mod+2 workspace number 2
    bindsym $mod+3 workspace number 3
    bindsym $mod+4 workspace number 4
    # Move focused container to workspace
    bindsym $mod+Shift+1 move container to workspace number 1
    bindsym $mod+Shift+2 move container to workspace number 2
    bindsym $mod+Shift+3 move container to workspace number 3
    bindsym $mod+Shift+4 move container to workspace number 4
    # Note: workspaces can have any name you want, not just numbers.
    # We just use 1-10 as the default.
#
# Layout stuff:
#
    # You can "split" the current object of your focus with
    # $mod+b or $mod+v, for horizontal and vertical splits
    # respectively.
    bindsym $mod+b splith
    bindsym $mod+v splitv

    # Switch the current container between different layout styles
    bindsym $mod+s layout stacking
    bindsym $mod+w layout tabbed
    bindsym $mod+e layout toggle split

    # Make the current focus fullscreen
    # bindsym $mod+f fullscreen

    # Toggle the current focus between tiling and floating mode
    bindsym $mod+Shift+space floating toggle

    # Swap focus between the tiling area and the floating area
    bindsym $mod+space focus mode_toggle

    # Move focus to the parent container
    bindsym $mod+a focus parent
#
# Scratchpad:
#
    # Sway has a "scratchpad", which is a bag of holding for windows.
    # You can send windows there and get them back later.

    # Move the currently focused window to the scratchpad
    bindsym $mod+Shift+minus move scratchpad

    # Show the next scratchpad window or hide the focused scratchpad window.
    # If there are multiple scratchpad windows, this command cycles through them.
    bindsym $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
    # left will shrink the containers width
    # right will grow the containers width
    # up will shrink the containers height
    # down will grow the containers height
    bindsym $left resize shrink width 10px
    bindsym $down resize grow height 10px
    bindsym $up resize shrink height 10px
    bindsym $right resize grow width 10px

    # Ditto, with arrow keys
    bindsym Left resize shrink width 10px
    bindsym Down resize grow height 10px
    bindsym Up resize shrink height 10px
    bindsym Right resize grow width 10px

    # Return to default mode
    bindsym Return mode "default"
    bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"

#
# Status Bar:
#
# Read `man 5 sway-bar` for more information about this section.
bar {
    position top

    # When the status_command prints a new line to stdout, swaybar updates.
    # The default just shows the current date and time.
    status_command sxmo_statusbar.sh

    colors {
        statusline #ffffff
        background #323232
        inactive_workspace #32323200 #32323200 #5c5c5c
        font "Mono"
    }
}

default_border pixel 3
titlebar_border_thickness 3

include /etc/sway/config.d/*

exec 'printf %s "$SWAYSOCK" > "$CACHEDIR"/sxmo.swaysock'

exec sxmo_networkmonitor.sh
exec sxmo_modemmonitortoggle.sh restart
exec sxmo_notificationmonitor.sh
exec mako
exec sxmo_hooks.sh lisgdstart

M configs/appcfg/xinit_template => configs/appcfg/xinit_template +1 -1
@@ 34,7 34,7 @@ amixer set "Line Out" 50%
# not receive texts/calls!
# (there is a bit of a delay to
# give the modem some time to set up)
sleep 15 && sxmo_modemmonitortoggle.sh on &
sxmo_modemmonitortoggle.sh restart &


### Configuration Parameters ###

A configs/applications/swmo.desktop => configs/applications/swmo.desktop +5 -0
@@ 0,0 1,5 @@
[Desktop Entry]
Name=Sxmo
Exec=sxmo_winit.sh
Terminal=false
Type=Application

M configs/default_hooks/inputhandler => configs/default_hooks/inputhandler +10 -25
@@ 4,21 4,6 @@ WMCLASS="$1"
WMNAME="$2"
ACTION="$3"

key() {
	xdotool windowactivate "$WIN"
	xdotool key --delay 50 --clearmodifiers "$@"
}

type() {
	xdotool windowactivate "$WIN"
	xdotool type --delay 50 --clearmodifiers "$@"
}

typeenter() {
	type "$@"
	xdotool key Return
}

# You must exit 0 if you handled the input to not trigger default behaviors

if [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; then


@@ 35,24 20,24 @@ exit 1 # Remove this in your user hook
# Please share your recipes to the community :D

case "$WMCLASS" in
	*"st-256color"*)
	*"foot"*)
		case "$WMNAME" in
			*"weechat"*)
				case "$ACTION" in
					*"oneleft")
						key Alt+a
						sxmo_type.sh -M Alt -k a
						exit 0
						;;
					*"oneright")
						key Alt+Shift+comma
						sxmo_type.sh -M Alt -k less
						exit 0
						;;
					*"oneup")
						key Page_Down
						sxmo_type.sh -k Page_Down
						exit 0
						;;
					*"onedown")
						key Page_Up
						sxmo_type.sh -k Page_Up
						exit 0
						;;
			esac


@@ 62,19 47,19 @@ case "$WMCLASS" in
	*"mpv"*)
		case "$ACTION" in
			"oneright")
				key Left
				sxmo_type.sh -k Left
				exit 0
				;;
			"oneleft")
				key Right
				sxmo_type.sh -k Right
				exit 0
				;;
			"upone")
				key m
			"oneup")
				sxmo_type.sh m
				exit 0
				;;
			"onedown")
				key p
				sxmo_type.sh p
				exit 0
				;;
		esac

M configs/default_hooks/lisgdstart => configs/default_hooks/lisgdstart +31 -1
@@ 13,10 13,40 @@ if [ -z "$LISGD_THRESHOLD_PRESSED" ]; then
	LISGD_THRESHOLD_PRESSED=60
fi

case "$(sxmo_wm.sh)" in
	sway)
		output="$(
			swaymsg -t get_outputs \
				| jq -r '.[] | select(.name == "DSI-1") | {transform: .transform, width: .current_mode.width, height: .current_mode.height}' \
				| sed "s|normal|0|"
		)"
		transform="$(printf %s "$output" | jq -r .transform)"
		width="$(printf %s "$output" | jq -r .width)"
		height="$(printf %s "$output" | jq -r .height)"
		orientation="$((transform / 90))"
		;;
	dwm)
		output="$(xrandr | grep DSI-1 | sed "s|.* \(\d\+\)x\(\d\+\)+.*|\1 \2|")"
		height="$(printf %s "$output" | cut -d" " -f2)"
		width="$(printf %s "$output" | cut -d" " -f1)"
		case "$(xrandr | grep DSI-1 | cut -d' ' -f 5)" in
			right) orientation=1;;
			left) orientation=3;;
			inverted) orientation=2;;
			*) orientation=0;;
		esac
		if [ "$((orientation%2))" -ne 0 ]; then
			tmp="$height"
			height="$width"
			width="$tmp"
		fi
esac

#-g format:
#   fingers,swipe,edge,distance,command
#order matters, only the first match gets executed
lisgd "$@" -t "$LISGD_THRESHOLD" -T "$LISGD_THRESHOLD_PRESSED" \
lisgd "$@" -o "$orientation" -h "$height" -w "$width" \
	-t "$LISGD_THRESHOLD" -T "$LISGD_THRESHOLD_PRESSED" \
	-g '1,DRUL,BR,*,sxmo_inputhandler.sh bottomrightcorner' \
	-g '1,DLUR,BL,*,sxmo_inputhandler.sh bottomleftcorner' \
	-g '1,ULDR,TL,*,sxmo_inputhandler.sh topleftcorner' \

M configs/default_hooks/unlocksim => configs/default_hooks/unlocksim +1 -1
@@ 17,7 17,7 @@ sim_n() {
}

retry=1
pkill dmenu #kill existing dmenu
sxmo_dmenu.sh close
while [ $retry -eq 1 ]; do
	PICKED="$(
		# shellcheck disable=SC2039,SC3037

M scripts/appscripts/sxmo_files.sh => scripts/appscripts/sxmo_files.sh +2 -2
@@ 16,7 16,7 @@ sort_loop() {

	PICKED="$(
		printf %b "$CHOICES" |
		dmenu -c -p "Sort" -l 10 -i
		sxmo_dmenu.sh -p "Sort" -i
	)"

	echo "$PICKED" | grep -q "date" && SORT="--sort=t"


@@ 39,7 39,7 @@ while true; do

	PICKED="$(
		echo "$CHOICES" |
		dmenu -c -p "$DIR" -l 20 -i
		sxmo_dmenu.sh -p "$DIR" -i
	)" || exit

	echo "$PICKED" | grep "Sort By" && sort_loop

M scripts/appscripts/sxmo_record.sh => scripts/appscripts/sxmo_record.sh +3 -3
@@ 43,13 43,13 @@ recordconfirm() {
				Delete Recording
			" |
			xargs -0 echo | sed '/^[[:space:]]*$/d' | awk '{$1=$1};1' |
			dmenu -p "$DUR" -c -l 10
			sxmo_dmenu.sh -p "$DUR"
		)"
		if echo "$PICK" | grep "Playback"; then
			sxmo_terminal.sh mpv -ao=alsa -v "$FILE"
		elif echo "$PICK" | grep "Delete Recording"; then
			rm "$FILE"
			echo "File deleted." | dmenu -c -l 10
			echo "File deleted." | sxmo_dmenu.sh
			return
		else
			return


@@ 72,7 72,7 @@ recordmenu() {
			xargs -0 echo |
			sed '/^[[:space:]]*$/d' |
			awk '{$1=$1};1' |
			dmenu -c -p "Record" -l 20
			sxmo_dmenu.sh -p "Record"
		)"

		if [ "$OPTION" = "Line Jack" ]; then

M scripts/appscripts/sxmo_reddit.sh => scripts/appscripts/sxmo_reddit.sh +2 -2
@@ 10,7 10,7 @@ menu() {
	sxmo_keyboard.sh open
	SUBREDDIT="$(
		printf %b "Close Menu\n$(echo "$SXMO_SUBREDDITS" | tr " " '\n')" |
		dmenu -p "Subreddit:" -c -l 10
		sxmo_dmenu.sh -p "Subreddit:"
	)"
	sxmo_keyboard.sh close
	[ "Close Menu" = "$SUBREDDIT" ] && exit 0


@@ 29,7 29,7 @@ menu() {
	while true; do
		RESULT="$(
			printf %b "Close Menu\n$REDDITRESULTS" |
			dmenu -c -l 10 -fn Terminus-20
			sxmo_dmenu.sh -fn Terminus-20
		)"

		[ "Close Menu" = "$RESULT" ] && exit 0

M scripts/appscripts/sxmo_rss.sh => scripts/appscripts/sxmo_rss.sh +2 -2
@@ 66,7 66,7 @@ rsstimespanmenu() {
			echo "$CHOICES" |
			sed '/^[[:space:]]*$/d' |
			awk '{$1=$1};1' |
			dmenu -p "RSS Timespan" -c -l 10
			sxmo_dmenu.sh -p "RSS Timespan"
		)"

		if echo "$CHOICE" | grep "Fetch"; then


@@ 101,7 101,7 @@ rssreadmenu() {
	DMENUIDX=1
	while true; do
		# Show list of items
		PICKED="$(printf %b "$CHOICES" | dmenu -idx $DMENUIDX -p "RSS ($TIMESPANABBR)" -c -l 20 -fn Terminus-15)"
		PICKED="$(printf %b "$CHOICES" | sxmo_dmenu.sh -ix $DMENUIDX -p "RSS ($TIMESPANABBR)" -fn Terminus-15)"
		DMENUIDX="$(echo "$CHOICES" | grep -m1 -F -n "$PICKED" | cut -d ':' -f1)"
		if [ "$PICKED" = "Close Menu" ]; then
			die Closed Menu

M scripts/appscripts/sxmo_timer.sh => scripts/appscripts/sxmo_timer.sh +2 -2
@@ 45,11 45,11 @@ menu() {
		1m
		30s
		Close Menu
	" | awk 'NF' | awk '{$1=$1};1' | dmenu -p Timer -c -l 20
	" | awk 'NF' | awk '{$1=$1};1' | sxmo_dmenu.sh -p Timer
	)"
	sxmo_keyboard.sh close
	[ "Close Menu" = "$TIMEINPUT" ] && exit 0
	st -f Monospace-50 -e "$0" timerrun "$TIMEINPUT"
	sxmo_terminal.sh -f Monospace-50 "$0" timerrun "$TIMEINPUT"
}

if [ $# -gt 0 ]; then "$@"; else menu; fi

M scripts/appscripts/sxmo_websearch.sh => scripts/appscripts/sxmo_websearch.sh +1 -1
@@ 6,7 6,7 @@

sxmo_keyboard.sh open
SEARCHQUERY="$(
	echo "Close Menu" | dmenu -t -p "Search:" -c -l 20
	echo "Close Menu" | sxmo_dmenu.sh -p "Search:"
)"
sxmo_keyboard.sh close
[ "Close Menu" = "$SEARCHQUERY" ] && exit 0

M scripts/appscripts/sxmo_youtube.sh => scripts/appscripts/sxmo_youtube.sh +2 -2
@@ 32,7 32,7 @@ searchmenu() {
				xargs -0 echo |
				sed '/^[[:space:]]*$/d' |
				awk '{$1=$1};1' |
				sxmo_dmenu_with_kb.sh -p "Yt Search" -c -l 10
				sxmo_dmenu_with_kb.sh -p "Yt Search"
		)"

		if [ "Close Menu" = "$ENTRY" ]; then


@@ 58,7 58,7 @@ resultsmenu() {
				xargs -0 echo |
				sed '/^[[:space:]]*$/d' |
				awk '{$1=$1};1' |
				dmenu -c -l 10 -p "Results"
				sxmo_dmenu.sh -p "Results"
		)"

		if [ "Change Search" = "$PICKED" ]; then

M scripts/core/sxmo_appmenu.sh => scripts/core/sxmo_appmenu.sh +219 -210
@@ 5,15 5,13 @@ trap gracefulexit INT TERM
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

WIN=$(xdotool getwindowfocus)

gracefulexit() {
	echo "Gracefully exiting $0">&2
	kill -9 0
}

confirm() {
	PICKED="$(printf "Yes\nNo\n" | dmenu -l 16 -c -p "Confirm $1")"
	PICKED="$(printf "Yes\nNo\n" | dmenu -p "Confirm $1")"

	if [ "$PICKED" = "Yes" ]; then
		return 0


@@ 22,9 20,13 @@ confirm() {
	fi
}

sxmo_type() {
	sxmo_type.sh -s 200 "$@" # dunno why this is necessary but it sucks without
}

programchoicesinit() {
	XPROPOUT="$(xprop -id "$(xdotool getactivewindow)")"
	WMCLASS="${1:-$(echo "$XPROPOUT" | grep WM_CLASS | cut -d ' ' -f3- | tr '[:upper:]' '[:lower:]')}"
	XPROPOUT="$(sxmo_wm.sh focusedwindow)"
	WMCLASS="${1:-$(printf %s "$XPROPOUT" | grep app: | cut -d" " -f2- | tr '[:upper:]' '[:lower:]')}"
	if [ -z "$XPROPOUT" ]; then
		echo "sxmo_appmenu: detected no active window, no problem, opening system menu" >&2
	else


@@ 116,7 118,8 @@ programchoicesinit() {
				$(command -v ranger     >/dev/null && echo "$icon_dir Ranger      ^ 0 ^ sxmo_terminal.sh ranger")
				$(command -v sacc       >/dev/null && echo "$icon_itm Sacc        ^ 0 ^ sxmo_terminal.sh sacc i-logout.cz/1/bongusta")
				$(command -v sic        >/dev/null && echo "$icon_itm Sic         ^ 0 ^ sxmo_terminal.sh sic")
				$(command -v st         >/dev/null && echo "$icon_trm St          ^ 0 ^ sxmo_terminal.sh $SHELL")
				$(command -v st         >/dev/null && echo "$icon_trm St          ^ 0 ^ st -e $SHELL")
				$(command -v foot       >/dev/null && echo "$icon_trm Foot        ^ 0 ^ foot $SHELL")
				$(command -v surf       >/dev/null && echo "$icon_glb Surf        ^ 0 ^ surf")
				$(command -v syncthing  >/dev/null && echo "$icon_rld Syncthing          ^ 0 ^ syncthing")
				$(command -v telegram-desktop >/dev/null && echo "$icon_tgm Telegram     ^ 0 ^ telegram-desktop")


@@ 153,7 156,7 @@ programchoicesinit() {
				printf %b "Off → On" ||  printf %b "On → Off";
				printf %b "^ 1 ^ sxmo_flashtoggle.sh"
			)
			$icon_cfg Bar Toggle                 ^ 1 ^ key Super+b
			$icon_cfg Idle Config                ^ 1 ^ sxmo_idle.sh config
			$icon_cfg Invert Colors              ^ 1 ^ xcalib -a -invert
			$icon_clk Change Timezone            ^ 1 ^ sxmo_timezonechange.sh
			$icon_ror Autorotate $(


@@ 165,6 168,7 @@ programchoicesinit() {
				printf %b "On → Off ^ 0 ^ sxmo_proximitylocktoggle.sh &" ||  printf %b "Off → On ^ 0 ^ sxmo_proximitylocktoggle.sh &"
			)
			$icon_ror Rotate                     ^ 1 ^ sxmo_rotate.sh rotate
			$icon_rol Toggle WM                  ^ 1 ^ sxmo_terminal.sh sxmo_wmtoggle.sh
			$icon_upc Upgrade Pkgs               ^ 0 ^ sxmo_terminal.sh sxmo_upgrade.sh
			$icon_cfg Edit configuration         ^ 0 ^ sxmo_terminal.sh $EDITOR $XDG_CONFIG_HOME/sxmo/xinit
			$(command -v pmos-tweaks >/dev/null && echo "$icon_cfg PostmarketOS Tweaks	     ^ 0 ^ GDK_SCALE=1 pmos-tweaks")


@@ 199,172 203,171 @@ programchoicesinit() {
	*mpv* )
		# MPV
		CHOICES="
			$icon_pau Pause        ^ 0 ^ key space
			$icon_fbw Seek       ^ 1 ^ key Left
			$icon_ffw Seek       ^ 1 ^ key Right
			$icon_aru App Volume ↑ ^ 1 ^ key 0
			$icon_ard App Volume ↓ ^ 1 ^ key 9
			$icon_aru Speed up      ^ 1 ^ key bracketright
			$icon_ard Speed down    ^ 1 ^ key bracketleft
			$icon_cam Screenshot   ^ 1 ^ key s
			$icon_itm Loopmark     ^ 1 ^ key l
			$icon_inf Info         ^ 1 ^ key i
			$icon_inf Seek Info    ^ 1 ^ key o
			$icon_pau Pause        ^ 0 ^ sxmo_type -k Space
			$icon_fbw Seek       ^ 1 ^ sxmo_type -k Left
			$icon_ffw Seek       ^ 1 ^ sxmo_type -k Right
			$icon_aru App Volume ↑ ^ 1 ^ sxmo_type 0
			$icon_ard App Volume ↓ ^ 1 ^ sxmo_type 9
			$icon_aru Speed up      ^ 1 ^ sxmo_type -k bracketRight
			$icon_ard Speed down    ^ 1 ^ sxmo_type -k bracketLeft
			$icon_cam Screenshot   ^ 1 ^ sxmo_type s
			$icon_itm Loopmark     ^ 1 ^ sxmo_type l
			$icon_inf Info         ^ 1 ^ sxmo_type i
			$icon_inf Seek Info    ^ 1 ^ sxmo_type o
		"
		WINNAME=Mpv && return
		;;
	*feh* )
		# Feh
		CHOICES="
			$icon_arr Next          ^ 1 ^ key space
			$icon_arl Previous      ^ 1 ^ key BackSpace
			$icon_zmi Zoom in       ^ 1 ^ key up
			$icon_zmo Zoom out      ^ 1 ^ key down
			$icon_exp Zoom to fit   ^ 1 ^ key slash
			$icon_shr Zoom to fill  ^ 1 ^ key exlam
			$icon_rol Rotate        ^ 1 ^ key less
			$icon_ror Rotate        ^ 1 ^ key greater
			$icon_a2y Flip          ^ 1 ^ key underscore
			$icon_a2x Mirror        ^ 1 ^ key bar
			$icon_inf Toggle filename ^ 1 ^ key d
			$icon_arr Next          ^ 1 ^ sxmo_type -k Space
			$icon_arl Previous      ^ 1 ^ sxmo_type -k BackSpace
			$icon_zmi Zoom in       ^ 1 ^ sxmo_type -k up
			$icon_zmo Zoom out      ^ 1 ^ sxmo_type -k down
			$icon_exp Zoom to fit   ^ 1 ^ sxmo_type -k slash
			$icon_shr Zoom to fill  ^ 1 ^ sxmo_type '!'
			$icon_rol Rotate        ^ 1 ^ sxmo_type -k less
			$icon_ror Rotate        ^ 1 ^ sxmo_type -k greater
			$icon_a2y Flip          ^ 1 ^ sxmo_type -k underscore
			$icon_a2x Mirror        ^ 1 ^ sxmo_type -k bar
			$icon_inf Toggle filename ^ 1 ^ sxmo_type d
		"
		WINNAME=Feh && return
		;;
	*sxiv* )
		# Sxiv
		CHOICES="
			$icon_arr Next          ^ 1 ^ key space
			$icon_arl Previous      ^ 1 ^ key BackSpace
			$icon_zmi Zoom in       ^ 1 ^ key equal
			$icon_zmo Zoom out      ^ 1 ^ key minus
			$icon_rol Rotate        ^ 1 ^ key less
			$icon_ror Rotate        ^ 1 ^ key greater
			$icon_a2y Flip          ^ 1 ^ key question
			$icon_a2x Mirror        ^ 1 ^ key bar
			$icon_grd Thumbnail     ^ 0 ^ key Return
			$icon_arr Next          ^ 1 ^ sxmo_type -k Space
			$icon_arl Previous      ^ 1 ^ sxmo_type -k BackSpace
			$icon_zmi Zoom in       ^ 1 ^ sxmo_type -k equal
			$icon_zmo Zoom out      ^ 1 ^ sxmo_type -k minus
			$icon_rol Rotate        ^ 1 ^ sxmo_type -k less
			$icon_ror Rotate        ^ 1 ^ sxmo_type -k greater
			$icon_a2y Flip          ^ 1 ^ sxmo_type -k question
			$icon_a2x Mirror        ^ 1 ^ sxmo_type -k bar
			$icon_grd Thumbnail     ^ 0 ^ sxmo_type -k Return
		"
		WINNAME=Sxiv && return
		;;
	*st-256color* )
		# St
		# First we try to handle the app running inside st:
		WMNAME="${1:-$(echo "$XPROPOUT" | grep -E "^WM_NAME" | cut -d ' ' -f3-)}"
	*foot*|*st* )
		# First we try to handle the app running inside the terminal:
		WMNAME="${1:-$(printf %s "$XPROPOUT" | grep title: | cut -d" " -f2- | tr '[:upper:]' '[:lower:]')}"
		if echo "$WMNAME" | grep -i -E "(vi|vim|vis|nvim|neovim|kakoune)"; then
			#Vim in st
			#Vim in foot
			CHOICES="
				$icon_aru Scroll up        ^ 1 ^ key Ctrl+Shift+u
				$icon_ard Scroll down      ^ 1 ^ key Ctrl+Shift+d
				$icon_trm Command prompt   ^ 0 ^ key Escape Shift+semicolon
				$icon_cls Save             ^ 0 ^ key Escape Shift+semicolon w Return
				$icon_cls Save and Quit    ^ 0 ^ key Escape Shift+semicolon w q Return
				$icon_cls Quit without saving  ^ 0 ^ key Escape Shift+semicolon q exclam Return
				$icon_pst Paste Selection  ^ 0 ^ key Escape quotedbl asterisk p
				$icon_pst Paste Clipboard  ^ 0 ^ key Escape quotedbl plus p
				$icon_fnd Search           ^ 0 ^ key Escape /
				$icon_zmi Zoom in          ^ 1 ^ key Ctrl+Shift+Prior
				$icon_zmo Zoom out         ^ 1 ^ key Ctrl+Shift+Next
				$icon_mnu St menu          ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_aru Scroll up        ^ 1 ^ sxmo_type -M Ctrl u
				$icon_ard Scroll down      ^ 1 ^ sxmo_type -M Ctrl d
				$icon_trm Command prompt   ^ 0 ^ sxmo_type -k Escape ':'
				$icon_cls Save             ^ 0 ^ sxmo_type -k Escape ':w' -k Return
				$icon_cls Save and Quit    ^ 0 ^ sxmo_type -k Escape ':wq' -k Return
				$icon_cls Quit without saving  ^ 0 ^ sxmo_type -k Escape ':q!' -k Return
				$icon_pst Paste Selection  ^ 0 ^ sxmo_type -k Escape -k quotedbl -k asterisk -k p
				$icon_pst Paste Clipboard  ^ 0 ^ wl-paste
				$icon_fnd Search           ^ 0 ^ sxmo_type -k Escape /
				$icon_zmi Zoom in          ^ 1 ^ sxmo_type -k Prior
				$icon_zmo Zoom out         ^ 1 ^ sxmo_type -k Next
				$icon_mnu Terminal menu    ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=Vim
		elif echo "$WMNAME" | grep -i -w "nano"; then
			#Nano in st
			#Nano in foot
			CHOICES="
				$icon_aru Scroll up       ^ 1 ^ key Prior
				$icon_ard Scroll down     ^ 1 ^ key Next
				$icon_sav Save            ^ 0 ^ key Ctrl+O
				$icon_cls Quit            ^ 0 ^ key Ctrl+X
				$icon_pst Paste           ^ 0 ^ key Ctrl+U
				$icon_itm Type complete   ^ 0 ^ key Ctrl+Shift+u
				$icon_cpy Copy complete   ^ 0 ^ key Ctrl+Shift+i
				$icon_zmi Zoom in         ^ 1 ^ key Ctrl+Shift+Prior
				$icon_zmo Zoom out        ^ 1 ^ key Ctrl+Shift+Next
				$icon_mnu St menu         ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_aru Scroll up       ^ 1 ^ sxmo_type -k Prior
				$icon_ard Scroll down     ^ 1 ^ sxmo_type -k Next
				$icon_sav Save            ^ 0 ^ sxmo_type -M Ctrl o
				$icon_cls Quit            ^ 0 ^ sxmo_type -M Ctrl x
				$icon_pst Paste           ^ 0 ^ sxmo_type -M Ctrl u
				$icon_itm Type complete   ^ 0 ^ sxmo_type -M Shift -M Ctrl u
				$icon_cpy Copy complete   ^ 0 ^ sxmo_type -M Shift -M Ctrl i
				$icon_zmi Zoom in         ^ 1 ^ sxmo_type -k Prior
				$icon_zmo Zoom out        ^ 1 ^ sxmo_type -k Next
				$icon_mnu Terminal menu   ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=Nano
		elif echo "$WMNAME" | grep -i -w "tuir"; then
			#tuir (reddit client) in st
			#tuir (reddit client) in foot
			CHOICES="
				$icon_aru Previous      ^ 1 ^ key k
				$icon_ard Next          ^ 1 ^ key j
				$icon_aru Scroll up     ^ 1 ^ key Prior
				$icon_ard Scroll down   ^ 1 ^ key Next
				$icon_ret Open          ^ 0 ^ key o
				$icon_arl Back          ^ 0 ^ key h
				$icon_arr Comments      ^ 0 ^ key l
				$icon_edt Post          ^ 0 ^ key c
				$icon_rld Refresh       ^ 0 ^ key r
				$icon_cls Quit          ^ 0 ^ key q
				$icon_zmi Zoom in       ^ 1 ^ key Ctrl+Shift+Prior
				$icon_zmo Zoom out      ^ 1 ^ key Ctrl+Shift+Next
				$icon_mnu St menu       ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_aru Previous      ^ 1 ^ sxmo_type k
				$icon_ard Next          ^ 1 ^ sxmo_type j
				$icon_aru Scroll up     ^ 1 ^ sxmo_type -k Prior
				$icon_ard Scroll down   ^ 1 ^ sxmo_type -k Next
				$icon_ret Open          ^ 0 ^ sxmo_type o
				$icon_arl Back          ^ 0 ^ sxmo_type h
				$icon_arr Comments      ^ 0 ^ sxmo_type l
				$icon_edt Post          ^ 0 ^ sxmo_type c
				$icon_rld Refresh       ^ 0 ^ sxmo_type r
				$icon_cls Quit          ^ 0 ^ sxmo_type q
				$icon_zmi Zoom in       ^ 1 ^ sxmo_type -k Prior
				$icon_zmo Zoom out      ^ 1 ^ sxmo_type -k Next
				$icon_mnu Terminal menu ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=tuir
		elif echo "$WMNAME" | grep -i -w "w3m"; then
			#w3m
			CHOICES="
				$icon_arl Back          ^ 1 ^ key B
				$icon_glb Goto URL        ^ 1 ^ key U
				$icon_arr Next Link       ^ 1 ^ key Tab
				$icon_arl Previous Link   ^ 1 ^ key Shift+Tab
				$icon_tab Open tab        ^ 0 ^ key T
				$icon_cls Close tab       ^ 0 ^ Ctrl+q
				$icon_itm Next tab        ^ 1 ^ key braceright
				$icon_itm Previous tab    ^ 1 ^ key braceleft
				$icon_zmi Zoom in          ^ 1 ^ key Ctrl+Shift+Prior
				$icon_zmo Zoom out          ^ 1 ^ key Ctrl+Shift+Next
				$icon_mnu St menu         ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_arl Back          ^ 1 ^ sxmo_type b
				$icon_glb Goto URL        ^ 1 ^ sxmo_type u
				$icon_arr Next Link       ^ 1 ^ sxmo_type -k Tab
				$icon_arl Previous Link   ^ 1 ^ sxmo_type -M Shift -k Tab
				$icon_tab Open tab        ^ 0 ^ sxmo_type t
				$icon_cls Close tab       ^ 0 ^ sxmo_type -M Ctrl q
				$icon_itm Next tab        ^ 1 ^ sxmo_type -k braceRight
				$icon_itm Previous tab    ^ 1 ^ sxmo_type -k braceLeft
				$icon_zmi Zoom in          ^ 1 ^ sxmo_type -k Prior
				$icon_zmo Zoom out          ^ 1 ^ sxmo_type -k Next
				$icon_mnu Terminal menu   ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=w3m
		elif echo "$WMNAME" | grep -i -w "ncmpcpp"; then
			#ncmpcpp
			CHOICES="
				$icon_lst Playlist        ^ 0 ^ key 1
				$icon_fnd Browser         ^ 0 ^ key 2
				$icon_fnd Search          ^ 0 ^ key 3
				$icon_nxt Next track      ^ 0 ^ key greater
				$icon_prv Previous track  ^ 0 ^ key less
				$icon_pau Pause           ^ 0 ^ key p
				$icon_stp Stop            ^ 0 ^ key s
				$icon_rld Toggle repeat   ^ 0 ^ key r
				$icon_sfl Toggle random   ^ 0 ^ key z
				$icon_itm Toggle consume  ^ 0 ^ key R
				$icon_mnu St menu         ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_lst Playlist        ^ 0 ^ sxmo_type 1
				$icon_fnd Browser         ^ 0 ^ sxmo_type 2
				$icon_fnd Search          ^ 0 ^ sxmo_type 3
				$icon_nxt Next track      ^ 0 ^ sxmo_type -k greater
				$icon_prv Previous track  ^ 0 ^ sxmo_type -k less
				$icon_pau Pause           ^ 0 ^ sxmo_type p
				$icon_stp Stop            ^ 0 ^ sxmo_type s
				$icon_rld Toggle repeat   ^ 0 ^ sxmo_type r
				$icon_sfl Toggle random   ^ 0 ^ sxmo_type z
				$icon_itm Toggle consume  ^ 0 ^ sxmo_type R
				$icon_mnu Terminal menu   ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=ncmpcpp
		elif echo "$WMNAME" | grep -i -w "aerc"; then
			#aerc
			CHOICES="
				$icon_pau Archive	  ^ 1 ^ typeenter ':archive flat'
				$icon_nxt Next Tab	  ^ 0 ^ typeenter ':next-tab'
				$icon_prv Previous Tab	  ^ 0 ^ typeenter ':prev-tab'
				$icon_cls Close Tab	  ^ 0 ^ typeenter ':close'
				$icon_itm Next Part	  ^ 1 ^ typeenter ':next-part'
				$icon_trm xdg-open Part	  ^ 0 ^ typeenter ':open'
				$icon_pau Archive	  ^ 1 ^ sxmo_type ':archive flat' -k Return
				$icon_nxt Next Tab	  ^ 0 ^ sxmo_type ':next-tab' -k Return
				$icon_prv Previous Tab	  ^ 0 ^ sxmo_type ':prev-tab' -k Return
				$icon_cls Close Tab	  ^ 0 ^ sxmo_type ':close' -k Return
				$icon_itm Next Part	  ^ 1 ^ sxmo_type ':next-part' -k Return
				$icon_trm xdg-open Part	  ^ 0 ^ sxmo_type ':open' -k Return
			"
			WINNAME=aerc
		elif echo "$WMNAME" | grep -i -E -w "(less|mless)"; then
			#less
			CHOICES="
				$icon_arr Page next       ^ 1 ^ typeenter ':n'
				$icon_arl Page previous   ^ 1 ^ typeenter ':p'
				$icon_cls Quit            ^ 0 ^ key q
				$icon_zmi Zoom in         ^ 1 ^ key Ctrl+Shift+Prior
				$icon_zmo Zoom out        ^ 1 ^ key Ctrl+Shift+Next
				$icon_aru Scroll up       ^ 1 ^ key Ctrl+Shift+b
				$icon_ard Scroll down     ^ 1 ^ key Ctrl+Shift+f
				$icon_mnu St menu       ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_arr Page next       ^ 1 ^ sxmo_type ':n' -k Return
				$icon_arl Page previous   ^ 1 ^ sxmo_type ':p' -k Return
				$icon_cls Quit            ^ 0 ^ sxmo_type q
				$icon_zmi Zoom in         ^ 1 ^ sxmo_type -M Ctrl +
				$icon_zmo Zoom out        ^ 1 ^ sxmo_type -M Ctrl -k Minus
				$icon_aru Scroll up       ^ 1 ^ sxmo_type -k Prior
				$icon_ard Scroll down     ^ 1 ^ sxmo_type -k Next
				$icon_mnu Terminal menu ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=less
		elif echo "$WMNAME" | grep -i -w "weechat"; then
			#weechat
			CHOICES="
				$icon_msg Hotlist Next            ^ 1 ^ key Alt+a
				$icon_arl History Previous        ^ 1 ^ key Alt+Shift+comma
				$icon_arr History Next            ^ 1 ^ key Alt+Shift+period
				$icon_trm Buffer                  ^ 0 ^ type '/buffer '
				$icon_aru Scroll up               ^ 1 ^ key Prior
				$icon_ard Scroll down             ^ 1 ^ key Next
				$icon_mnu St menu       ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_msg Hotlist Next            ^ 1 ^ sxmo_type -M Alt a
				$icon_arl History Previous        ^ 1 ^ sxmo_type -M Alt -k Less
				$icon_arr History Next            ^ 1 ^ sxmo_type -M Alt -k Greater
				$icon_trm Buffer                  ^ 0 ^ sxmo_type '/buffer '
				$icon_aru Scroll up               ^ 1 ^ sxmo_type -k Prior
				$icon_ard Scroll down             ^ 1 ^ sxmo_type -k Next
				$icon_mnu Terminal menu ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=weechat
		elif echo "$WMNAME" | grep -i -w "sms"; then


@@ 373,6 376,9 @@ programchoicesinit() {
			CHOICES="
				$icon_msg Reply          ^ 0 ^ sxmo_modemtext.sh sendtextmenu $number
				$icon_phn Call           ^ 0 ^ sxmo_modemdial.sh $number
				$icon_aru Scroll up       ^ 1 ^ sxmo_type -M Shift -M Ctrl b
				$icon_ard Scroll down     ^ 1 ^ sxmo_type -M Shift -M Ctrl f
				$icon_mnu Terminal menu ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=sms
		elif echo "$WMNAME" | grep -i -w "cmus"; then


@@ 386,76 392,95 @@ programchoicesinit() {
				$icon_prv Previous track  ^ 0 ^ cmus-remote -r
				$icon_rld Toggle repeat   ^ 0 ^ cmus-remote -R
				$icon_sfl Toggle random   ^ 0 ^ cmus-remote -S
				$icon_mnu St menu         ^ 0 ^ sxmo_appmenu.sh st-256color
				$icon_mnu Terminal menu   ^ 0 ^ sxmo_appmenu.sh $WMCLASS
			"
			WINNAME=cmus
		else
			STSELMODEON="$(
				echo "$XPROPOUT" | grep -E '^_ST_SELMODE.+=' | cut -d= -f2 | tr -d ' '
			)"
			CHOICES="
				$icon_itm Type complete   ^ 0 ^ key Ctrl+Shift+u
				$icon_cpy Copy complete   ^ 0 ^ key Ctrl+Shift+i
				$icon_itm Selmode $(
				  [ "$STSELMODEON" = 1 ] &&
				  printf %b 'On → Off' ||
				  printf %b 'Off → On'
				  printf %b '^ 0 ^ key Ctrl+Shift+s'
				)
				$([ "$STSELMODEON" = 1 ] && echo 'Copy selection ^ 0 ^ key Ctrl+Shift+c')
				$icon_pst Paste           ^ 0 ^ key Ctrl+Shift+v
				$icon_zmi Zoom in         ^ 1 ^ key Ctrl+Shift+Prior
				$icon_zmo Zoom out        ^ 1 ^ key Ctrl+Shift+Next
				$icon_aru Scroll up       ^ 1 ^ key Ctrl+Shift+b
				$icon_ard Scroll down     ^ 1 ^ key Ctrl+Shift+f
				$icon_a2x Invert          ^ 1 ^ key Ctrl+Shift+x
				$icon_kbd Hotkeys         ^ 0 ^ sxmo_appmenu.sh sthotkeys
			"
			WINNAME=St
			# Now we fallback to the default terminal menu
			case "$WMCLASS" in
				*st*)
					STSELMODEON="$(
						echo "$XPROPOUT" | grep -E '^_ST_SELMODE.+=' | cut -d= -f2 | tr -d ' '
					)"
					CHOICES="
						$icon_itm Type complete   ^ 0 ^ sxmo_type -M Ctrl -M Shift -k u
						$icon_cpy Copy complete   ^ 0 ^ sxmo_type -M Ctrl -M Shift -k i
						$icon_itm Selmode $(
						  [ "$STSELMODEON" = 1 ] &&
						  printf %b 'On → Off' ||
						  printf %b 'Off → On'
						  printf %b '^ 0 ^ sxmo_type -M Ctrl -M Shift -k s'
						)
						$([ "$STSELMODEON" = 1 ] && echo 'Copy selection ^ 0 ^ sxmo_type -M Ctrl -M Shift -k c')
						$icon_pst Paste           ^ 0 ^ sxmo_type -M Ctrl -M Shift -k v
						$icon_zmi Zoom in         ^ 1 ^ sxmo_type -M Ctrl -M Shift -k Prior
						$icon_zmo Zoom out        ^ 1 ^ sxmo_type -M Ctrl -M Shift -k Next
						$icon_aru Scroll up       ^ 1 ^ sxmo_type -M Ctrl -M Shift -k b
						$icon_ard Scroll down     ^ 1 ^ sxmo_type -M Ctrl -M Shift -k f
						$icon_a2x Invert          ^ 1 ^ sxmo_type -M Ctrl -M Shift -k x
						$icon_kbd Hotkeys         ^ 0 ^ sxmo_appmenu.sh sthotkeys
					"
					WINNAME=St
					;;
				*foot*)
					CHOICES="
						$icon_itm Type complete   ^ 0 ^ sxmo_type -M Shift -M Ctrl u
						$icon_cpy Copy complete   ^ 0 ^ sxmo_type -M Shift -M Ctrl i
						$icon_pst Paste           ^ 0 ^ sxmo_type -M Shift -M Ctrl v
						$icon_zmi Zoom in         ^ 1 ^ sxmo_type -M Ctrl +
						$icon_zmo Zoom out        ^ 1 ^ sxmo_type -M Ctrl -k Minus
						$icon_aru Scroll up       ^ 1 ^ sxmo_type -k Prior
						$icon_ard Scroll down     ^ 1 ^ sxmo_type -k Next
						$icon_a2x Invert          ^ 1 ^ sxmo_type -M Shift -M Ctrl x
						$icon_kbd Hotkeys         ^ 0 ^ sxmo_appmenu.sh sthotkeys
					"
					WINNAME=Foot
					;;
			esac
		fi
		;;
	*sthotkeys* )
		#  St hotkeys
		CHOICES="
			Send Ctrl-C      ^ 0 ^ key Ctrl+c
			Send Ctrl-Z      ^ 0 ^ key Ctrl+z
			Send Ctrl-L      ^ 0 ^ key Ctrl+l
			Send Ctrl-D      ^ 0 ^ key Ctrl+d
			Send Ctrl-A      ^ 0 ^ key Ctrl+a
			Send Ctrl-B      ^ 0 ^ key Ctrl+b
			Send ESC:w       ^ 0 ^ key Escape Shift+semicolon w Return
			Send ESC:wq      ^ 0 ^ key Escape Shift+semicolon w q Return
			Send ESC:wq!     ^ 0 ^ key Escape Shift+semicolon q exclam Return
			Send Ctrl-C      ^ 0 ^ sxmo_type -M Ctrl -k c
			Send Ctrl-Z      ^ 0 ^ sxmo_type -M Ctrl -k z
			Send Ctrl-L      ^ 0 ^ sxmo_type -M Ctrl -k l
			Send Ctrl-D      ^ 0 ^ sxmo_type -M Ctrl -k d
			Send Ctrl-A      ^ 0 ^ sxmo_type -M Ctrl -k a
			Send Ctrl-B      ^ 0 ^ sxmo_type -M Ctrl -k b
			Send ESC:w       ^ 0 ^ sxmo_type -k Escape -M Shift -k semicolon -m Shift -k w -k Return
			Send ESC:wq      ^ 0 ^ sxmo_type -k Escape -M Shift -k semicolon -m Shift -k w -k q -k Return
			Send ESC:wq!     ^ 0 ^ sxmo_type -k Escape -M Shift -k semicolon -m Shift -k q -k exclam -k Return
		"
		WINNAME=St
		;;
	;;
	*netsurf* )
		# Netsurf
		CHOICES="
			$icon_flt Pipe URL          ^ 0 ^ sxmo_urlhandler.sh
			$icon_zmi Zoom            ^ 1 ^ key Ctrl+plus
			$icon_zmo Zoom            ^ 1 ^ key Ctrl+minus
			$icon_arl History        ^ 1 ^ key Alt+Left
			$icon_arr History        ^ 1 ^ key Alt+Right
			$icon_zmi Zoom            ^ 1 ^ sxmo_type -M Ctrl -k plus
			$icon_zmo Zoom            ^ 1 ^ sxmo_type -M Ctrl -k minus
			$icon_arl History        ^ 1 ^ sxmo_type -M Alt -k Left
			$icon_arr History        ^ 1 ^ sxmo_type -M Alt -k Right
		"
		WINNAME=Netsurf
		;;
	*surf* )
		# Surf
		CHOICES="
			$icon_glb Navigate    ^ 0 ^ key Ctrl+g
			$icon_lnk Link Menu   ^ 0 ^ key Ctrl+d
			$icon_glb Navigate    ^ 0 ^ sxmo_type -M Ctrl g
			$icon_lnk Link Menu   ^ 0 ^ sxmo_type -M Ctrl d
			$icon_flt Pipe URL    ^ 0 ^ sxmo_urlhandler.sh
			$icon_fnd Search Page ^ 0 ^ key Ctrl+f
			$icon_fnd Find Next   ^ 0 ^ key Ctrl+n
			$icon_zmi Zoom      ^ 1 ^ key Ctrl+Shift+k
			$icon_zmo Zoom      ^ 1 ^ key Ctrl+Shift+j
			$icon_aru Scroll    ^ 1 ^ key Shift+space
			$icon_ard Scroll    ^ 1 ^ key space
			$icon_itm JS Toggle   ^ 1 ^ key Ctrl+Shift+s
			$icon_arl History   ^ 1 ^ key Ctrl+h
			$icon_arr History   ^ 1 ^ key Ctrl+l
			$icon_rld Refresh     ^ 0 ^ key Ctrl+Shift+r
			$icon_fnd Search Page ^ 0 ^ sxmo_type -M Ctrl f
			$icon_fnd Find Next   ^ 0 ^ sxmo_type -M Ctrl n
			$icon_zmi Zoom      ^ 1 ^ sxmo_type -M Shift -M Ctrl k
			$icon_zmo Zoom      ^ 1 ^ sxmo_type -M Shift -M Ctrl j
			$icon_aru Scroll    ^ 1 ^ sxmo_type -M Shift -k Space
			$icon_ard Scroll    ^ 1 ^ sxmo_type -k Space
			$icon_itm JS Toggle   ^ 1 ^ sxmo_type -M Shift -M Ctrl s
			$icon_arl History   ^ 1 ^ sxmo_type -M Ctrl h
			$icon_arr History   ^ 1 ^ sxmo_type -M Ctrl l
			$icon_rld Refresh     ^ 0 ^ sxmo_type -M Shift -M Ctrl r
		"
		WINNAME=Surf
		;;


@@ 463,29 488,29 @@ programchoicesinit() {
		# Firefox
		CHOICES="
			$icon_flt Pipe URL          ^ 0 ^ sxmo_urlhandler.sh
			$icon_tab New Tab           ^ 0 ^ key Ctrl+t
			$icon_win New Window        ^ 0 ^ key Ctrl+n
			$icon_cls Close Tab         ^ 0 ^ key Ctrl+w
			$icon_zmi Zoom            ^ 1 ^ key Ctrl+plus
			$icon_zmo Zoom            ^ 1 ^ key Ctrl+minus
			$icon_arl History        ^ 1 ^ key Alt+Left
			$icon_arr History        ^ 1 ^ key Alt+Right
			$icon_rld Refresh     ^ 0 ^ key Ctrl+Shift+r
			$icon_tab New Tab           ^ 0 ^ sxmo_type -M Ctrl t
			$icon_win New Window        ^ 0 ^ sxmo_type -M Ctrl n
			$icon_cls Close Tab         ^ 0 ^ sxmo_type -M Ctrl w
			$icon_zmi Zoom            ^ 1 ^ sxmo_type -M Ctrl -k plus
			$icon_zmo Zoom            ^ 1 ^ sxmo_type -M Ctrl -k minus
			$icon_arl History        ^ 1 ^ sxmo_type -M Alt -k Left
			$icon_arr History        ^ 1 ^ sxmo_type -M Alt -k Right
			$icon_rld Refresh     ^ 0 ^ sxmo_type -M Shift -M Ctrl r
		"
		WINNAME=Firefox
		;;
	*lagrange* )
		# Lagrange
		CHOICES="
			$icon_mnu Toggle sidebar ^ 0 ^ key Ctrl+Shift+p
			$icon_bok Open bookmarks ^ 0 ^ key Ctrl+l && typeenter 'about:bookmarks'
			$icon_pls Add bookmark   ^ 0 ^ key Ctrl+d
			$icon_zmi Zoom           ^ 1 ^ key Ctrl+equal
			$icon_zmo Zoom           ^ 1 ^ key Ctrl+minus
			$icon_aru Parent dir     ^ 1 ^ key Alt+Up
			$icon_arl History        ^ 1 ^ key Alt+Left
			$icon_arr History        ^ 1 ^ key Alt+Right
			$icon_rld Refresh        ^ 0 ^ key Ctrl+r
			$icon_mnu Toggle sidebar ^ 0 ^ sxmo_type -M Shift -M Ctrl p
			$icon_bok Open bookmarks ^ 0 ^ sxmo_type -M Ctrl l && sxmo_type 'about:bookmarks' -k Return
			$icon_pls Add bookmark   ^ 0 ^ sxmo_type -M Ctrl d
			$icon_zmi Zoom           ^ 1 ^ sxmo_type -M Ctrl -k equal
			$icon_zmo Zoom           ^ 1 ^ sxmo_type -M Ctrl -k minus
			$icon_aru Parent dir     ^ 1 ^ sxmo_type -M Alt -k Up
			$icon_arl History        ^ 1 ^ sxmo_type -M Alt -k Left
			$icon_arr History        ^ 1 ^ sxmo_type -M Alt -k Right
			$icon_rld Refresh        ^ 0 ^ sxmo_type -M Ctrl r
		"
		WINNAME=Lagrange
		;;


@@ 498,11 523,11 @@ programchoicesinit() {
			$icon_itm Drop Pin            ^ 0 ^ sxmo_gpsutil.sh droppin
			$icon_fnd Region Search       ^ 0 ^ sxmo_gpsutil.sh menuregionsearch
			$icon_itm Region Details      ^ 0 ^ sxmo_gpsutil.sh details
			$icon_zmi Zoom              ^ 1 ^ key i
			$icon_zmo Zoom              ^ 1 ^ key o
			$icon_zmi Zoom              ^ 1 ^ sxmo_type i
			$icon_zmo Zoom              ^ 1 ^ sxmo_type o
			$icon_itm Map Type            ^ 0 ^ sxmo_gpsutil.sh menumaptype
			$icon_itm Panel Toggle        ^ 1 ^ key m
			$icon_itm GPSD Toggle         ^ 1 ^ key a
			$icon_itm Panel Toggle        ^ 1 ^ sxmo_type m
			$icon_itm GPSD Toggle         ^ 1 ^ sxmo_type a
			$icon_usr Locate Me           ^ 0 ^ sxmo_gpsutil.sh gpsgeoclueset
		"
		WINNAME=Maps


@@ 571,22 596,6 @@ getprogchoices() {
	PROGCHOICES="$(echo "$CHOICES" | xargs -0 echo | sed '/^[[:space:]]*$/d' | awk '{$1=$1};1')"
}

key() {
	xdotool windowactivate "$WIN"
	xdotool key --delay 50 --clearmodifiers "$@"
	#--window $WIN
}

type() {
	xdotool windowactivate "$WIN"
	xdotool type --delay 50 --clearmodifiers "$@"
}

typeenter() {
	type "$@"
	xdotool key Return
}

quit() {
	exit 0
}


@@ 595,7 604,7 @@ mainloop() {
	getprogchoices "$ARGS"
	echo "$PROGCHOICES" |
	cut -d'^' -f1 |
	dmenu -idx "$DMENUIDX" -l 16 -c -p "$WINNAME" | (
	dmenu -i -p "$WINNAME" | (
		PICKED="$(cat)"
		echo "$PICKED" | grep . || quit
		LOOP="$(echo "$PROGCHOICES" | grep -m1 -F "$PICKED" | cut -d '^' -f2)"

M scripts/core/sxmo_bluetoothmenu.sh => scripts/core/sxmo_bluetoothmenu.sh +1 -1
@@ 50,7 50,7 @@ devicemenu() {

		PICKED="$(
			echo "$ENTRIES" |
			dmenu -i -c -l 10 -p "Devices"
			dmenu -i -p "Devices"
		)" || exit

		if echo "$PICKED" | grep -q "Refresh"; then

M scripts/core/sxmo_brightness.sh => scripts/core/sxmo_brightness.sh +12 -24
@@ 4,37 4,25 @@
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

BACKLIGHT="${BACKLIGHT:-/sys/devices/platform/backlight/backlight/backlight}"
if [ ! -e "$BACKLIGHT" ] && [ -e /sys/class/backlight/edp-backlight ]; then
	BACKLIGHT=/sys/class/backlight/edp-backlight
fi

[ ! -e "$BACKLIGHT" ] && echo "unable to find backlight device" && exit 1

MAX=$(cat $BACKLIGHT/max_brightness)
MIN=2
MINSTEP=1
STEP=$(echo "($MAX - $MIN) / 10" | bc | xargs -ISTP echo -e "$MINSTEP\nSTP" | sort -r | head -n1)

setdelta() {
	VAL="$(
		xargs -IB echo B "$1" < $BACKLIGHT/brightness |
		bc |
		xargs -INUM echo -e "$MIN\nNUM" | sort -n | tail -n1 |
		xargs -INUM echo -e "$MAX\nNUM" | sort -n | head -n1
	)"
	echo "$VAL" > "$BACKLIGHT/brightness" || exit 1
	echo "set brightness to $VAL"
notify() {
	light | xargs notify-send
}

	dunstify -i 0 -u normal -r 999 "☀ $(cat $BACKLIGHT/brightness)/${MAX}"
setvalue() {
	light -S "$1"
}

up() {
	setdelta "+${STEP}"
	light -A 5
}

down() {
	setdelta "-${STEP}"
	light -U 5
}

getvalue() {
	light
}

"$@"
notify

M scripts/core/sxmo_common.sh => scripts/core/sxmo_common.sh +1 -0
@@ 40,6 40,7 @@ command -v "$EDITOR" > /dev/null || export EDITOR=vis
command -v shopt > /dev/null && shopt -s expand_aliases

alias dmenu="sxmo_dmenu.sh"
alias jq="gojq" # better performances

alias find="busybox find"
# Use native commands if busybox was compile without those apples (for example Debians busybox)

M scripts/core/sxmo_contactmenu.sh => scripts/core/sxmo_contactmenu.sh +9 -9
@@ 17,7 17,7 @@ valid_number() {

	notify-send "\"$1\" is not a valid phone number"

	PICKED="$(printf "Ok\nUse as it is\n" | dmenu -c -l 2 -p "Invalid Number")"
	PICKED="$(printf "Ok\nUse as it is\n" | dmenu -p "Invalid Number")"
	if [ "$PICKED" = "Use as it is" ]; then
		echo "$1"
		return


@@ 27,10 27,10 @@ valid_number() {
}

newcontact() {
	name="$(echo | sxmo_dmenu_with_kb.sh -c -l 2 -p "$icon_usr Name")"
	name="$(echo | sxmo_dmenu_with_kb.sh -p "$icon_usr Name")"
	number=
	while [ -z "$number" ]; do
		number="$(sxmo_contacts.sh --unknown | sxmo_dmenu_with_kb.sh -t -c -l 10 -p "$icon_phl Number")"
		number="$(sxmo_contacts.sh --unknown | sxmo_dmenu_with_kb.sh -p "$icon_phl Number")"
		number="$(valid_number "$number")"
	done



@@ 45,7 45,7 @@ editcontactname() {
	ENTRIES="$(printf %b "Old name: $oldname")"
	PICKED="$(
		echo "$ENTRIES" |
		sxmo_dmenu_with_kb.sh -c -l 3 -p "$icon_edt Edit Contact"
		sxmo_dmenu_with_kb.sh -p "$icon_edt Edit Contact"
	)"

	if ! echo "$PICKED" | grep -q "^Old name: "; then


@@ 66,7 66,7 @@ editcontactnumber() {
	while [ -z "$PICKED" ]; do
		PICKED="$(
			echo "$ENTRIES" |
			sxmo_dmenu_with_kb.sh -t -c -l 10 -p "$icon_edt Edit Contact"
			sxmo_dmenu_with_kb.sh -p "$icon_edt Edit Contact"
		)"
		if echo "$PICKED" | grep -q "(Old number)$"; then
			editcontact "$1"


@@ 87,7 87,7 @@ deletecontact() {
	ENTRIES="$(printf "$icon_cls No\n$icon_chk Yes")"
	PICKED="$(
		echo "$ENTRIES" |
		dmenu -c -l 3 -p "$icon_del Delete $name ?"
		dmenu -p "$icon_del Delete $name ?"
	)"

	echo "$PICKED" | grep -q "Yes" && sed -i "/^$1$/d" "$CONTACTFILE"


@@ 100,7 100,7 @@ editcontact() {

	PICKED="$(
		echo "$ENTRIES" |
		dmenu -c -l 4 -p "$icon_edt Edit Contact"
		dmenu -p "$icon_edt Edit Contact"
	)"

	if echo "$PICKED" | grep -q "Name: "; then


@@ 119,7 119,7 @@ showcontact() {

	PICKED="$(
		echo "$ENTRIES" |
		dmenu -c -l 6 -p "$icon_usr $name"
		dmenu -p "$icon_usr $name"
	)"

	if echo "$PICKED" | grep -q "List Messages"; then


@@ 145,7 145,7 @@ main() {

		PICKED="$(
			echo "$ENTRIES" |
			sxmo_dmenu_with_kb.sh -i -c -l 10 -p "$icon_lst Contacts"
			sxmo_dmenu_with_kb.sh -i -p "$icon_lst Contacts"
		)"

		echo "$PICKED" | grep -q "Close Menu" && exit

M scripts/core/sxmo_dmenu.sh => scripts/core/sxmo_dmenu.sh +37 -6
@@ 1,9 1,40 @@
#!/usr/bin/env sh

TERMMODE=$([ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] && echo "true")
# We still use dmenu in dwm|worgs cause pointer/touch events
# are not implemented yet in the X11 library of bemenu

if [ "$TERMMODE" != "true" ]; then
	exec dmenu "$@"
else
	exec vis-menu -i -l 10
fi
case "$1" in
	isopen)
		case "$(sxmo_wm.sh)" in
			sway|ssh)
				exec pgrep bemenu
				;;
			xorg|dwm)
				exec pgrep dmenu
				;;
		esac
		;;
	close)
		case "$(sxmo_wm.sh)" in
			sway|ssh)
				exec pkill bemenu
				;;
			xorg|dwm)
				exec pkill dmenu
				;;
		esac
		;;
esac > /dev/null

case "$(sxmo_wm.sh)" in
	sway)
		exec bemenu --scrollbar autohide -n -w -c -l "$(sxmo_rotate.sh isrotated && printf 7 ||  printf 23)" "$@"
		;;
	xorg|dwm)
		exec dmenu -c -l "$(sxmo_rotate.sh isrotated && printf 7 || printf 23)" "$@"
		;;
	ssh)
		export BEMENU_BACKEND=curses
		exec bemenu "$@"
		;;
esac

M scripts/core/sxmo_dmenu_with_kb.sh => scripts/core/sxmo_dmenu_with_kb.sh +12 -9
@@ 1,15 1,18 @@
#!/usr/bin/env sh

TERMMODE=$([ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ] && echo "true")
if [ "$TERMMODE" = "true" ]; then
	exec vis-menu -i -l 10
if [ "$(sxmo_wm.sh)" != "ssh" ]; then
	if sxmo_keyboard.sh isopen; then
		wasopen="1"
	fi
	sxmo_keyboard.sh open
fi

wasopen="$(sxmo_keyboard.sh isopen && echo "yes")"

sxmo_keyboard.sh open
OUTPUT="$(cat | dmenu "$@")"
OUTPUT="$(cat | sxmo_dmenu.sh "$@")"
exitcode=$?
[ -z "$wasopen" ] && sxmo_keyboard.sh close
echo "$OUTPUT"

if [ -z "$wasopen" ]; then
	sxmo_keyboard.sh close
fi

printf %s "$OUTPUT"
exit $exitcode

M scripts/core/sxmo_gpsutil.sh => scripts/core/sxmo_gpsutil.sh +3 -3
@@ 171,7 171,7 @@ menuregionsearch() {
		printf %b "$POIS" |
		sed '/^[[:space:]]*$/d' |
		awk '{$1=$1};1' |
		sxmo_dmenu_with_kb.sh -i -c -l 10 -p Search
		sxmo_dmenu_with_kb.sh -i -p Search
	)"

	if [ "$QUERY" = "Close Menu" ]; then


@@ 197,7 197,7 @@ menulocations() {
		)" |
		grep -vE '^#' |
		sed "s/\t/: /g" |
		sxmo_dmenu_with_kb.sh -i -c -l 10 -p "Locations"
		sxmo_dmenu_with_kb.sh -i -p "Locations"
	)"
	ZOOM=14
	if [ "$CHOICE" = "Close Menu" ]; then


@@ 223,7 223,7 @@ menumaptype() {
		CHOICE="$(
			echo "$CHOICES" |
			awk -F^ '{ print $1 }' |
			dmenu -idx "$IDX" -c -l 10 -p "Map Type" |
			dmenu -ix "$IDX" -p "Map Type" |
			awk '{$1=$1};1'
		)"
		echo "$CHOICE" | grep "Close Menu" && exit 0

M scripts/core/sxmo_hotspot.sh => scripts/core/sxmo_hotspot.sh +4 -4
@@ 2,19 2,19 @@

while [ -z "$SSID" ]; do
	SSID="$(
		echo "$ENTRIES" | sxmo_dmenu_with_kb.sh -c -p "SSID"
		echo "$ENTRIES" | sxmo_dmenu_with_kb.sh -p "SSID"
	)"
done

while [ -z "$key" ]; do
	key="$(
		echo "$ENTRIES" | sxmo_dmenu_with_kb.sh -c -p "pass"
		echo "$ENTRIES" | sxmo_dmenu_with_kb.sh -p "pass"
	)"
done

while [ -z "$key1" ]; do
	key1="$(
		echo "$ENTRIES" | sxmo_dmenu_with_kb.sh -c -p "confirm"
		echo "$ENTRIES" | sxmo_dmenu_with_kb.sh -p "confirm"
	)"
done



@@ 25,7 25,7 @@ fi

while [ -z "$channel" ]; do
	channel="$(
		echo "11" | sxmo_dmenu_with_kb.sh -l 1 -c -p "channels"
		echo "11" | sxmo_dmenu_with_kb.sh -p "channels"
	)"
done


A scripts/core/sxmo_idle.sh => scripts/core/sxmo_idle.sh +122 -0
@@ 0,0 1,122 @@
#!/bin/sh

# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

set -e

LOCK=0
OFF=0
SUSPEND=0

readconfig() {
	if [ ! -f "$CACHEDIR"/sxmo.idle.state ]; then
		printf "LOCK 0\nOFF 0\nSUSPEND 0\n" >"$CACHEDIR"/sxmo.idle.state
	fi
	IDLE_STATE="$(cat "$CACHEDIR"/sxmo.idle.state)"

	LOCK="$(
		printf %s "$IDLE_STATE" |
			grep ^LOCK |
			cut -d' ' -f2
		)"

	OFF="$(
		printf %s "$IDLE_STATE" |
			grep ^OFF |
			cut -d' ' -f2
		)"

	SUSPEND="$(
		printf %s "$IDLE_STATE" |
			grep ^SUSPEND |
			cut -d' ' -f2
		)"
}

start() {
	if pgrep swayidle; then
		notify-send "Already running !"
		exit 1
	fi

	set --

	if [ "$LOCK" -gt 0 ]; then
		set -- "$@" timeout "$LOCK" "sxmo_screenlock.sh lock"
	fi

	if [ "$OFF" -gt 0 ]; then
		set -- "$@" timeout "$OFF" "sxmo_screenlock.sh off"
	fi

	if [ "$SUSPEND" -gt 0 ]; then
		set -- "$@" timeout "$SUSPEND" "sxmo_screenlock.sh off"
	fi

	if [ "$#" -eq 0 ]; then
		notify-send "Idle monitor disabled"
		exit 1
	fi

	exec swayidle "$@"
}

stop() {
	pkill swayidle || return 0
	sleep 1
}

configmenu() {
	PICKED="$(
		printf "LOCK %d\nOFF %d\nSUSPEND %d\n" "$LOCK" "$OFF" "$SUSPEND" | \
			sxmo_dmenu_with_kb.sh
	)"

	target="$(printf %s "$PICKED" | cut -d" " -f1)"
	old_value="$(printf %s "$PICKED" | cut -d" " -f2)"

	while [ -z "$new_value" ]; do
		new_value="$(
			printf "" | \
				sxmo_dmenu_with_kb.sh -p "New value"
		)"
		[ "$new_value" -gt 5 ] || unset new_value
	done

	sed -i "s|$target $old_value|$target $new_value|" "$CACHEDIR"/sxmo.idle.state
}

readconfig

action="${1:-start}"
case "$action" in
	start)
		start
		sleep 1
		if pgrep swayidle; then
			notify-send "Dpms Started"
		fi
		;;
	stop)
		stop
		sleep 1
		if ! pgrep swayidle; then
			notify-send "Dpms Stopped"
		fi
		;;
	restart)
		stop
		swaymsg exec "$(basename "$0")" start
		sleep 1
		if pgrep swayidle; then
			notify-send "Dpms Restarted"
		fi
		;;
	config)
		configmenu
		swaymsg exec "$(basename "$0")" restart
		;;
esac


M scripts/core/sxmo_inputhandler.sh => scripts/core/sxmo_inputhandler.sh +92 -98
@@ 20,24 20,9 @@ lock_screen() {
	fi
}

key() {
	xdotool windowactivate "$WIN"
	xdotool key --delay 50 --clearmodifiers "$@"
}

type() {
	xdotool windowactivate "$WIN"
	xdotool type --delay 50 --clearmodifiers "$@"
}

typeenter() {
	type "$@"
	xdotool key Return
}

XPROPOUT="$(xprop -id "$(xdotool getactivewindow)")"
WMCLASS="$(echo "$XPROPOUT" | grep WM_CLASS | cut -d ' ' -f3-)"
WMNAME=$(echo "$XPROPOUT" | grep -E "^WM_NAME" | cut -d ' ' -f3-)
XPROPOUT="$(sxmo_wm.sh focusedwindow)"
WMCLASS="$(printf %s "$XPROPOUT" | grep app: | cut -d" " -f2- | tr '[:upper:]' '[:lower:]')"
WMNAME="$(printf %s "$XPROPOUT" | grep title: | cut -d" " -f2- | tr '[:upper:]' '[:lower:]')"

if [ -x "$XDG_CONFIG_HOME"/sxmo/hooks/inputhandler ]; then
	#hook script must exit with a zero exit code ONLY if it has handled the gesture!


@@ 63,44 48,61 @@ if [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; then
	exit
fi

if sxmo_dmenu.sh isopen; then
	case "$ACTION" in
		"volup_one")
			sxmo_type.sh -k Up
			exit
			;;
		"voldown_one")
			sxmo_type.sh -k Down
			exit
			;;
		"powerbutton_one")
			sxmo_type.sh -k Return
			exit
			;;
	esac
fi

#special context-sensitive handling
case "$WMCLASS" in
	*"st-256color"*)
	*"foot"*)
		# First we try to handle the app running inside st:
		case "$WMNAME" in
			*"tuir"*)
				if [ "$ACTION" = "rightbottomcorner" ]; then
					type o
					sxmo_type.sh o
					exit 0
				elif [ "$ACTION" = "leftbottomcorner" ]; then
					type s
					sxmo_type.sh s
					exit 0
				fi
				;;
			*"less"*)
				case "$ACTION" in
					"leftbottomcorner")
						type q
						sxmo_type.sh q
						exit 0
						;;
					"leftrightcorner_short")
						type q
						sxmo_type.sh q
						exit 0
						;;
					*"onedown")
						type u
						sxmo_type.sh u
						exit 0
						;;
					*"oneup")
						type  d
						sxmo_type.sh d
						exit 0
						;;
					*"oneleft")
						typeenter ":n"
						sxmo_type.sh ":n" -k Return
						exit 0
						;;
					*"oneright")
						typeenter ":p"
						sxmo_type.sh ":p" -k Return
						exit 0
						;;
				esac


@@ 108,35 110,35 @@ case "$WMCLASS" in
			*"amfora"*)
				case "$ACTION" in
					"downright")
						key Tab
						sxmo_type.sh -k Tab
						exit 0
						;;
					"upleft")
						key Shift+Tab
						sxmo_type.sh -M Shift -k Tab
						exit 0
						;;
					*"onedown")
						key u
						sxmo_type.sh u
						exit 0
						;;
					*"oneup")
						key d
						sxmo_type.sh d
						exit 0
						;;
					*"oneright")
						key Return
						sxmo_type.sh -k Return
						exit 0
						;;
					"upright")
						key Ctrl+t
						sxmo_type.sh -M Ctrl t
						exit 0
						;;
					*"oneleft")
						key b
						sxmo_type.sh b
						exit 0
						;;
					"downleft")
						key Ctrl+w
						sxmo_type.sh -M Ctrl w
						exit 0
						;;
				esac


@@ 145,11 147,11 @@ case "$WMCLASS" in
		# Now we try generic st actions
		case "$ACTION" in
			*"onedown")
				key Ctrl+Shift+B
				sxmo_type.sh -M Shift -k Page_Up
				exit 0
				;;
			*"oneup")
				key Ctrl+Shift+F
				sxmo_type.sh -M Shift -k Page_Down
				exit 0
				;;
		esac


@@ 157,28 159,60 @@ esac

#standard handling
case "$ACTION" in
	"rightleftcorner")
		key Super+Shift+e
	"powerbutton_one")
		if echo "$WMCLASS" | grep -i "megapixels"; then
			sxmo_type.sh -k space
		else
			sxmo_keyboard.sh toggle
		fi
			exit 0
		;;
	"powerbutton_two")
		sxmo_blinkled.sh blue && $TERMCMD "$SHELL"
		exit 0
		;;
	"leftrightcorner")
		key Super+Shift+r
	"powerbutton_three")
		sxmo_blinkled.sh blue && $BROWSER
		exit 0
		;;
	"twoleft") # Move window previous
		key Super+e
	"voldown_one")
		swaymsg layout toggle splith splitv tabbed
		exit
		;;
	"voldown_two")
		swaymsg focus tiling
		exit
		;;
	"voldown_three")
		sxmo_killwindow.sh
		exit
		;;
	"volup_one")
		sxmo_appmenu.sh
		exit
		;;
	"volup_two")
		sxmo_appmenu.sh sys
		exit
		;;
	"volup_three")
		sxmo_screenlock.sh lock
		exit
		;;
	"rightleftcorner")
		sxmo_workspace.sh previous
		exit 0
		;;
	"tworight") # Move window next
		key Super+r
	"leftrightcorner")
		sxmo_workspace.sh next
		exit 0
		;;
	"unmute")
		sxmo_vol.sh unmute &
	"twoleft")
		sxmo_workspace.sh move-previous
		exit 0
		;;
	"mute")
		sxmo_vol.sh mute &
	"tworight")
		sxmo_workspace.sh move-next
		exit 0
		;;
	"righttopcorner")


@@ 206,15 240,15 @@ case "$ACTION" in
		exit 0
		;;
	"downtopcorner")
		pidof dmenu || setsid -f sxmo_appmenu.sh &
		sxmo_dmenu.sh isopen || sxmo_appmenu.sh &
		exit 0
		;;
	"twodowntopcorner")
		pidof dmenu || setsid -f sxmo_appmenu.sh sys &
		sxmo_dmenu.sh isopen || sxmo_appmenu.sh sys &
		exit 0
		;;
	"uptopcorner")
		pkill -9 dmenu
		sxmo_dmenu.sh close
		dunstctl close-all
		exit 0
		;;


@@ 223,67 257,27 @@ case "$ACTION" in
		exit 0
		;;
	"uprightcorner")
		xdotool key Up
		sxmo_type.sh -k Up
		exit 0
		;;
	"downrightcorner")
		xdotool key Down
		sxmo_type.sh -k Down
		exit 0
		;;
	"leftrightcorner_short")
		xdotool key Left
		sxmo_type.sh -k Left
		exit 0
		;;
	"rightrightcorner_short")
		xdotool key Right
		sxmo_type.sh -k Right
		exit 0
		;;
	"rightbottomcorner")
		xdotool key Return
		sxmo_type.sh -k Return
		exit 0
		;;
	"leftbottomcorner")
		xdotool key BackSpace
		exit 0
		;;
	"powerbutton_one")
		if echo "$WMCLASS" | grep -i "megapixels"; then
			key "space"
		else
			sxmo_keyboard.sh toggle
		fi
		exit 0
		;;
	"powerbutton_two")
		sxmo_blinkled.sh blue && $TERMCMD "$SHELL"
		exit 0
		;;
	"powerbutton_three")
		sxmo_blinkled.sh blue && $BROWSER
		exit 0
		;;
	"volup_one")
		sxmo_appmenu.sh
		exit 0
		;;
	"volup_two")
		sxmo_appmenu.sh sys
		exit 0
		;;
	"volup_three")
		lock_screen
		exit 0
		;;
	"voldown_one")
		key Super+space
		exit 0
		;;
	"voldown_two")
		key Super+x
		exit 0
		;;
	"voldown_three")
		sxmo_blinkled.sh red && sxmo_killwindow.sh
		sxmo_type.sh -k BackSpace
		exit 0
		;;
	"topleftcorner")

M scripts/core/sxmo_killwindow.sh => scripts/core/sxmo_killwindow.sh +4 -5
@@ 4,8 4,7 @@
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

if [ "$1" = "close" ]; then
	xdotool windowclose "$(xdotool getactivewindow)"
else
	xdotool windowkill "$(xdotool getactivewindow)"
fi
case "$(sxmo_wm.sh)" in
	sway) swaymsg kill;;
	xorg|dwm) xdotool windowkill "$(xdotool getactivewindow)";;
esac

M scripts/core/sxmo_migrate.sh => scripts/core/sxmo_migrate.sh +9 -1
@@ 60,5 60,13 @@ checkhooks() {
	fi
}

defaultconfig /usr/share/sxmo/appcfg/xinit_template "$XDG_CONFIG_HOME/sxmo/xinit" 744
case "$(sxmo_wm.sh)" in
	sway)
		defaultconfig /usr/share/sxmo/appcfg/sway_template "$XDG_CONFIG_HOME/sxmo/sway" 744
		;;
	xorg|dwm)
		defaultconfig /usr/share/sxmo/appcfg/xinit_template "$XDG_CONFIG_HOME/sxmo/xinit" 744
		;;
esac

checkhooks

A scripts/core/sxmo_multikey.sh => scripts/core/sxmo_multikey.sh +38 -0
@@ 0,0 1,38 @@
#!/bin/sh

if [ "$1" = clear ]; then
	rm -f "$XDG_RUNTIME_DIR"/sxmo.multikey.count.*
	exit
fi

identifier="$1"
threshold="${SXMO_THRESHOLD:-0.30}"

count_file="$XDG_RUNTIME_DIR"/sxmo.multikey.count."$identifier"

if [ -f "$count_file" ]; then
	counter="$(($(cat "$count_file")+1))"
else
	counter=1
fi

shift "$counter"
if [ "$#" -eq 0 ]; then
	exit
fi
printf %s "$counter" > "$count_file"

sleep "$threshold"

if [ "$counter" != "$(cat "$count_file")" ]; then
	exit
fi

eval "$1" &

if [ "$#" -eq 1 ]; then
	sleep "$threshold" # prevent holded presses to chain
fi

rm "$count_file"


M scripts/core/sxmo_networks.sh => scripts/core/sxmo_networks.sh +6 -6
@@ 24,7 24,7 @@ toggleconnection() {
deletenetworkmenu() {
	CHOICE="$(
		printf %b "Close Menu\n$(connections)" |
			dmenu -c -p "Delete Network" -l 14
			dmenu -p "Delete Network"
	)"
	if [ "$CHOICE" = "Close Menu" ]; then
		return


@@ 45,13 45,13 @@ getifname() {
addnetworkgsmmenu() {
	CONNNAME="$(
		echo "Close Menu" |
			sxmo_dmenu_with_kb.sh -c -p "Add GSM: Alias" -l 20
			sxmo_dmenu_with_kb.sh -p "Add GSM: Alias"
	)"
	[ "$CONNNAME" = "Close Menu" ] && return

	APN="$(
		echo "Close Menu" |
			sxmo_dmenu_with_kb.sh -c -p "Add GSM: APN" -l 20
			sxmo_dmenu_with_kb.sh -p "Add GSM: APN"
	)"
	[ "$APN" = "Close Menu" ] && return



@@ 67,13 67,13 @@ addnetworkwpamenu() {
	SSID="$(
		nmcli d wifi list | tail -n +2 | grep -v '^\*' | awk -F'  ' '{ print $6 }' | grep -v '\-\-' |
		xargs -0 printf 'Close Menu\n%s' |
		sxmo_dmenu_with_kb.sh -c -p "Add WPA: SSID" -l 20
		sxmo_dmenu_with_kb.sh -p "Add WPA: SSID"
	)"
	[ "$SSID" = "Close Menu" ] && return

	PASSPHRASE="$(
		echo "Close Menu" |
			sxmo_dmenu_with_kb.sh -c -p "Add WPA: Passphrase" -l 20
			sxmo_dmenu_with_kb.sh -p "Add WPA: Passphrase"
	)"
	[ "$PASSPHRASE" = "Close Menu" ] && return



@@ 102,7 102,7 @@ networksmenu() {
				System Menu
				Close Menu
			" |
			awk '{$1=$1};1' | grep '\w' | dmenu -c -p 'Networks' -l 14
			awk '{$1=$1};1' | grep '\w' | dmenu -p 'Networks'
		)"
		case "$CHOICE" in
			"System Menu" )

M scripts/core/sxmo_pipecomplete.sh => scripts/core/sxmo_pipecomplete.sh +1 -1
@@ 7,7 7,7 @@ menu() {
		printf %b "$(
		echo "Close Menu";
			echo "$INPUT" | grep -Eo '\S+' | tr -d '[:blank:]' | sort | uniq
		)" | sxmo_dmenu_with_kb.sh -p "$PROMPT" -l 10 -i -c
		)" | sxmo_dmenu_with_kb.sh -p "$PROMPT" -i
	)"
}


M scripts/core/sxmo_postwake.sh => scripts/core/sxmo_postwake.sh +32 -4
@@ 1,5 1,13 @@
#!/usr/bin/env sh

# The goal of this script is to handle post hibernation behavior
# If we woke up cause of the button :
# We want to trigger the hook and wait for it to finish while blinking.
# Or at least, blink for some seconds.
# If we woke up cause of the modem or rtc :
# The modem monitor or rtcwake scripts will handle everything
# We still trigger the hooks without doing anything else

# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. "$(which sxmo_common.sh)"


@@ 19,11 27,15 @@ REDLED_PATH="/sys/class/leds/red:indicator/brightness"
BLUELED_PATH="/sys/class/leds/blue:indicator/brightness"

finish() {
	kill "$SLEEPPID"
	kill "$CHECKPID"
	kill "$BLINKPID"

	echo 0 > "$REDLED_PATH"
	echo 0 > "$BLUELED_PATH"

	wait $HOOKPID

	# Going back to crust
	if [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; then
		echo "[$(date)] Going back to crust" >&2


@@ 36,7 48,7 @@ finish() {
trap 'finish' TERM INT EXIT

blink() {
	while [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ]; do
	while : ; do
		echo 1 > "$REDLED_PATH"
		echo 0 > "$BLUELED_PATH"
		sleep 0.25


@@ 46,13 58,29 @@ blink() {
	done
}

blink &
BLINKPID=$!
checkstate() {
	while [ "$(sxmo_screenlock.sh getCurState)" != "unlock" ] ; do
		sleep 0.25
	done
	finish
}

sxmo_wm.sh dpms off

# call the user hook, but ensure we wait at least 5 seconds which is essential for
# the unlock functionality to function well
sleep 5 &
SLEEPPID=$!

blink &
BLINKPID=$!

echo "sxmo_postwake: invoking postwake hook after wakeup (reason=$UNSUSPENDREASON, 1, $(date))" >&2
sxmo_hooks.sh postwake "$UNSUSPENDREASON"
sxmo_hooks.sh postwake "$UNSUSPENDREASON" &
HOOKPID=$!

checkstate &
CHECKPID=$!

wait $SLEEPPID
wait $HOOKPID

M scripts/core/sxmo_rotate.sh => scripts/core/sxmo_rotate.sh +65 -16
@@ 9,43 9,92 @@ applyptrmatrix() {
	xinput set-prop "$TOUCH_POINTER_ID" --type=float --type=float "Coordinate Transformation Matrix" "$@"
}

isrotated() {
	xrandr | grep primary | cut -d' ' -f 5 | grep right && return 0
	xrandr | grep primary | cut -d' ' -f 5 | grep left && return 0
	return 1
swaytransforms() {
	swaymsg -p -t get_outputs | awk '
		/Output/ { printf $2 " " };
		/Transform/ { print $2 }'
}

xorgisrotated() {
	case "$(xrandr | grep primary | cut -d' ' -f 5)" in
		*right*|*left*) return 0;;
		*) return 1;;
	esac
}

swayisrotated() {
	swaytransforms | grep DSI-1 | grep -q 0
}

rotnormal() {
xorgrotnormal() {
	sxmo_keyboard.sh close
	xrandr -o normal
	applyptrmatrix 0 0 0 0 0 0 0 0 0
	pidof lisgd && pkill lisgd | sxmo_hooks.sh lisgdstart -o 0 &
	sxmo_hooks.sh lisgdstart
	exit 0
}

swayrotnormal() {
	swaymsg -- output  DSI-1 transform 0
	sxmo_hooks.sh lisgdstart &
	exit 0
}

rotright() {
xorgrotright() {
	sxmo_keyboard.sh close
	xrandr -o right
	applyptrmatrix 0 1 0 -1 0 1 0 0 1
	pidof lisgd && pkill lisgd | sxmo_hooks.sh lisgdstart -o 1 &
	sxmo_hooks.sh lisgdstart &
	exit 0
}

rotleft() {
swayrotright() {
	swaymsg -- output  DSI-1 transform 90
	sxmo_hooks.sh lisgdstart
	exit 0
}

xorgrotleft() {
	sxmo_keyboard.sh close
	xrandr -o left
	applyptrmatrix 0 -1 1 1 0 0 0 0 1
	pidof lisgd && pkill lisgd | sxmo_hooks.sh lisgdstart -o 3 &
	sxmo_hooks.sh lisgdstart
	exit 0
}

swayrotleft() {
	swaymsg -- output  DSI-1 transform 270
	sxmo_hooks.sh lisgdstart
	exit 0
}

rotate() {
	if isrotated; then rotnormal; else rotright; fi
isrotated() {
	case "$wm" in
		sway)
			"swayisrotated"
			;;
		dwm|xorg)
			"xorgisrotated"
			;;
	esac
}

if [ -z "$1" ]; then
	rotate
else
	"$1"
wm="$(sxmo_wm.sh)"

if [ -z "$1" ] || [ "rotate" = "$1" ]; then
	shift
	if isrotated; then
		set -- rotnormal "$@"
	else
		set -- rotright "$@"
	fi
fi

case "$wm" in
	sway)
		"sway$1" "$@"
		;;
	dwm|xorg)
		"xorg$1" "$@"
		;;
esac

M scripts/core/sxmo_rtcwake.sh => scripts/core/sxmo_rtcwake.sh +9 -3
@@ 6,6 6,15 @@
REDLED_PATH="/sys/class/leds/red:indicator/brightness"
BLUELED_PATH="/sys/class/leds/blue:indicator/brightness"

SWAYSOCK="$(cat "$CACHEDIR"/sxmo.swaysock)"
export SWAYSOCK
if ! swaymsg 2> /dev/null; then
	unset SWAYSOCK
fi
if [ -z "$DISPLAY" ]; then
	export DISPLAY=":0"
fi

finish() {
	kill "$BLINKPID"



@@ 49,9 58,6 @@ if [ "$1" = "--strict" ]; then
	fi
fi

if [ -z "$DISPLAY" ]; then
	export DISPLAY=":0"
fi

trap 'finish' TERM INT EXIT


M scripts/core/sxmo_screenlock.sh => scripts/core/sxmo_screenlock.sh +12 -41
@@ 43,14 43,12 @@ whichWake() {

getCurState() {
	#get the current state of the lock
	if xinput list-props "$TOUCH_POINTER_ID" | grep "Device Enabled" | grep -q "0$"; then
		if xset q | grep -q "Off: 3"; then
			echo "off" #locked, and screen off
		else
			echo "lock" #locked, but screen on
		fi
	if sxmo_wm.sh inputevent | grep -q on ; then
		printf "unlock" #normal mode, not locked
	elif sxmo_wm.sh dpms | grep -q off; then
		printf "lock" #locked, but screen on
	else
		echo "unlock" #normal mode, not locked
		printf "off" #locked, and screen off
	fi
}



@@ 84,17 82,8 @@ if [ "$1" = "lock" ] ; then
	# TODO: Document LASTSTATE
	getCurState > "$LASTSTATE"

	#turn screen on
	xset dpms 0 0 0
	xset dpms force on


	# TODO: Could be improved by running xinput and disabling ALL input devices automatically but would need
	# to decide on the hook issues. Do we want a prelock and postlock? Or should users
	# be expected to edit the source code for disabling certain input devices?
	# this code allows us to not use the slock locking mechanism in the original sxmo_lock.sh
	# when combined with a working slock (see ~iv's) implementation, this should be secure.
	xinput disable "$TOUCH_POINTER_ID"
	sxmo_wm.sh dpms off
	sxmo_wm.sh inputevent off
	killall lisgd

	updateLed


@@ 107,14 96,10 @@ elif [ "$1" = "unlock" ] ; then

	getCurState > "$LASTSTATE"

	#turn screen back on
	xset dpms 0 0 0
	xset dpms force on
	sxmo_wm.sh dpms off
	sxmo_wm.sh inputevent on
	sxmo_hooks.sh lisgdstart &

	#start responding to touch input again
	xinput enable "$TOUCH_POINTER_ID"
	[ "$(xrandr  | grep DSI-1  | cut -d ' ' -f 5)" = "right" ] && ORIENTATION=1 || ORIENTATION=0
	sxmo_hooks.sh lisgdstart -o "$ORIENTATION" &
	echo 16000 > "$NETWORKRTCSCAN"

	updateLed


@@ 126,13 111,8 @@ elif [ "$1" = "off" ] ; then

	getCurState > "$LASTSTATE"

	#turn screen off, but have dpms temporarily enable
	#the screen when a button is pressed
	xset dpms 0 0 3
	xset dpms force off

	# stop responding to touch input
	xinput disable "$TOUCH_POINTER_ID"
	sxmo_wm.sh dpms on
	sxmo_wm.sh inputevent off
	killall lisgd

	updateLed


@@ 149,9 129,6 @@ elif [ "$1" = "crust" ] ; then

	sxmo_hooks.sh presuspend

	#turn screen off
	xset dpms force off

	YEARS8_TO_SEC=268435455
	if command -v mnc > /dev/null; then
		#wake up 10 seconds before the next cron event


@@ 176,12 153,6 @@ elif [ "$1" = "crust" ] ; then

	d=$(date)
	echo "sxmo_screenlock: woke up from crust (reason=$UNSUSPENDREASON) ($d)" >&2

	if [ "$UNSUSPENDREASON" != "rtc" ]; then
		#turn screen on only when we didn't wake up from an rtc event
		xset dpms force on
	fi

	if [ "$UNSUSPENDREASON" != "modem" ]; then
		echo 1200 > "$NETWORKRTCSCAN"
	fi

M scripts/core/sxmo_statusbar.sh => scripts/core/sxmo_statusbar.sh +7 -4
@@ 5,7 5,6 @@
. "$(dirname "$0")/sxmo_common.sh"

trap "update" USR1
pgrep -f sxmo_statusbar.sh | grep -v $$ | xargs -r kill -9

update() {
	# In-call.. show length of call


@@ 134,14 133,18 @@ update() {
	TIME="$(date +%R)"

	BAR="$(echo "${CALLINFO} ${MODEMMON} ${WIRELESS} ${VPN} ${AUDIOSYMBOL}${VOLUMESYMBOL} ${BATSTATUS} ${TIME}" | sed 's| \+| |g')"
	xsetroot -name "$BAR"

	case "$(sxmo_wm.sh)" in
		sway) printf "%s\n" "$BAR";;
		dwm) xsetroot -name "$BAR";;
	esac
}

# E.g. on first boot justs to make sure the bar comes in quickly
update && sleep 1 && update && sleep 1
update

while :
do
	update
	sleep 30 & wait
	update
done

M scripts/core/sxmo_surf_linkselect.sh => scripts/core/sxmo_surf_linkselect.sh +1 -1
@@ 68,7 68,7 @@ link_select() {
		dump_links_with_titles |
		awk '!x[$0]++' |
		# sort | uniq
		dmenu -p "$DMENU_PROMPT" -l 10 -i -c |
		dmenu -p "$DMENU_PROMPT" -i |
		awk -F' ' '{print $NF}' |
		link_normalize "$(xprop -id "$SURF_WINDOW" _SURF_URI | cut -d '"' -f 2)"
}

M scripts/core/sxmo_terminal.sh => scripts/core/sxmo_terminal.sh +14 -11
@@ 1,19 1,22 @@
#!/usr/bin/env sh
# shellcheck disable=SC2086

if [ -n "$TERMNAME" ]; then
	case "$TERMCMD" in
		"st -e")
			set -- st -T "$TERMNAME" -e "$@"
			;;
		*)
			printf "%s: '%s'\n" "Not implemented for TERMCMD" "$TERMCMD" >&2
			set -- $TERMCMD "$@"
	esac
else
	set -- $TERMCMD "$@"
if [ -z "$TERMNAME" ]; then
	TERMNAME="$*"
fi

case "$TERMCMD" in
	"st -e")
		set -- st -T "$TERMNAME" -e "$@"
		;;
	"foot")
		set -- foot -T "$TERMNAME" "$@"
		;;
	*)
		printf "%s: '%s'\n" "Not implemented for TERMCMD" "$TERMCMD" >&2
		set -- $TERMCMD "$@"
esac

if [ -z "$*" ]; then
	echo "sxmo_terminal.sh called in TERMMODE without any arguments (returning, nothing to do)" >&2
else

M scripts/core/sxmo_timezonechange.sh => scripts/core/sxmo_timezonechange.sh +1 -1
@@ 13,7 13,7 @@ menu() {
		find /usr/share/zoneinfo -type f |
		sed  's#^/usr/share/zoneinfo/##g' |
		sort |
		sxmo_dmenu_with_kb.sh -p Timezone -c -l 10 -i
		sxmo_dmenu_with_kb.sh -p Timezone -i
	)"
	sxmo_terminal.sh "$0" change "$T"
}

A scripts/core/sxmo_type.sh => scripts/core/sxmo_type.sh +48 -0
@@ 0,0 1,48 @@
#!/bin/sh

wtype_to_xdotool() {
	if [ "$#" -eq 0 ]; then
		exit
	fi

	if [ "-M" = "$1" ] || [ "-P" = "$1" ]; then
		key="$2"
		shift 2
		xdotool keydown "$key"
		sxmo_type.sh -f xorg "$@"
		xdotool keyup "$key"
		exit
	elif [ "-m" = "$1" ] || [ "-p" = "$1" ]; then
		xdotool keyup "$2"
		shift 2
	elif [ "-k" = "$1" ]; then
		xdotool key "$2"
		shift 2
	elif [ "-s" = "$1" ]; then
		printf 'scale=2; %s/1000\n' "$2" | bc -l | xargs xdotool sleep
		shift 2
	else
		xdotool type "$1"
		shift
	fi

	wtype_to_xdotool "$@"
}

# enforce wm
# usefull to recurse without reprobing the wm
if [ "$1" = "-f" ]; then
	wm="$2"
	shift 2
else
	wm="$(sxmo_wm.sh)"
fi

case "$wm" in
	sway)
		wtype "$@"
		;;
	dwm|xorg)
		wtype_to_xdotool "$@"
		;;
esac

M scripts/core/sxmo_urlhandler.sh => scripts/core/sxmo_urlhandler.sh +1 -1
@@ 46,7 46,7 @@ COMMAND=$(
		sed "s/URL/'URL'/g" |
		sed -e '/^\s*$/d' |
		sed -e 's/^\s*//' |
		dmenu -p "Pipe URL" -c -l 20
		dmenu -p "Pipe URL"
)

[ "$COMMAND" = "Close Menu" ] && exit 1

A scripts/core/sxmo_winit.sh => scripts/core/sxmo_winit.sh +91 -0
@@ 0,0 1,91 @@
#!/usr/bin/env sh


envvars() {
	# shellcheck disable=SC1091
	[ -f /etc/profile ] && . /etc/profile
	# shellcheck source=/dev/null
	export BEMENU_OPTS='--fn "Monospace 11"'
	[ -f "$HOME"/.profile ] && . "$HOME"/.profile
	export MOZ_ENABLE_WAYLAND=1
	command -v "$TERMCMD" || export TERMCMD="foot"
	command -v "$BROWSER" || export BROWSER=firefox
	command -v "$EDITOR" || export EDITOR=vis
	command -v "$SHELL" || export SHELL=/bin/sh
	command -v "$KEYBOARD" || defaultkeyboard
	[ -z "$MPV_HOME" ] && export MPV_HOME=/usr/share/sxmo/mpv
	[ -z "$MOZ_USE_XINPUT2" ] && export MOZ_USE_XINPUT2=1
	[ -z "$XDG_CONFIG_HOME" ] && export XDG_CONFIG_HOME=~/.config
	[ -z "$XDG_CACHE_HOME" ] && export XDG_CACHE_HOME=~/.cache
	[ -z "$XDG_DATA_HOME" ] && export XDG_DATA_HOME=~/.local/share
	[ -z "$XDG_RUNTIME_DIR" ] && export XDG_RUNTIME_DIR=~/.local/run
	[ -z "$XDG_PICTURES_DIR" ] && export XDG_PICTURES_DIR=~/Pictures
}

device_envvars() {
	device="$(cut -d ',' -f 2 < /sys/firmware/devicetree/base/compatible)"
	deviceprofile="$(which "sxmo_deviceprofile_$device.sh")"
	# shellcheck disable=SC1090
	[ -f "$deviceprofile" ] && . "$deviceprofile"
}

setupxdgdir() {
	mkdir -p $XDG_RUNTIME_DIR
	chmod 700 $XDG_RUNTIME_DIR
	chown "$USER:$USER" "$XDG_RUNTIME_DIR"

	mkdir -p "$XDG_CACHE_HOME/sxmo/"
	chmod 700 "$XDG_CACHE_HOME"
	chown "$USER:$USER" "$XDG_CACHE_HOME"
}

defaults() {
	alsactl --file /usr/share/sxmo/alsa/default_alsa_sound.conf restore
	[ -e "$HOME"/.Xresources ] && xrdb -merge "$HOME"/.Xresources
}

defaultkeyboard() {
	export KEYBOARD=wvkbd
}

defaultconfig() {
	if [ ! -r "$2" ]; then
		mkdir -p "$(dirname "$2")"
		cp "$1" "$2"
		chmod "$3" "$2"
	fi
}

defaultconfigs() {
	[ -r "$XDG_CONFIG_HOME/sxmo/sway" ] && return

	defaultconfig /usr/share/sxmo/appcfg/sway_template "$XDG_CONFIG_HOME/sxmo/sway" 744
	defaultconfig /usr/share/sxmo/appcfg/mako.conf "$XDG_CONFIG_HOME/mako/config" 744
	defaultconfig /usr/share/sxmo/appcfg/foot.ini "$XDG_CONFIG_HOME/foot/foot.ini" 744
}

startsway() {
	exec dbus-run-session sh -c "
		/usr/bin/sway -c "$XDG_CONFIG_HOME/sxmo/sway" 2> "$XDG_CACHE_HOME/sxmo/sway.log"
	"
}

init() {
	envvars
	device_envvars # set device env vars here to allow potentially overriding envvars

	# include common definitions
	# shellcheck source=scripts/core/sxmo_common.sh
	. "$(dirname "$0")/sxmo_common.sh"

	setupxdgdir
	defaults
	defaultconfigs
	startsway
}

if [ -z "$1" ]; then
	init 2> ~/.init.log #hard-coded location because at this stage we're not sure the xdg dirs exist yet
else
	"$1"
fi

A scripts/core/sxmo_wm.sh => scripts/core/sxmo_wm.sh +146 -0
@@ 0,0 1,146 @@
#!/bin/sh

# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

TOUCH_POINTER_ID="${TOUCH_POINTER_ID:-"8"}"

xorgdpms() {
	STATE=off
	if xset q | grep -q "Off: 3"; then
		STATE=on
	fi

	if [ "$1" = on ] && [ "$STATE" != on ]; then
		xset dpms 0 0 3
		xset dpms force off
	elif [ "$1" = off ] && [ "$STATE" != off ] ; then
		xset dpms 0 0 0
		xset dpms force on
	else
		printf %s "$STATE"
	fi
}

swaydpms() {
	STATE=off
	if swaymsg -t get_outputs \
		| jq '.[] | select(.name == "DSI-1") | .dpms' \
		| grep -q "false"; then
		STATE=on
	fi

	if [ "$1" = on ] && [ "$STATE" != on ]; then
		swaymsg -- output DSI-1 dpms false
	elif [ "$1" = off ] && [ "$STATE" != off ] ; then
		swaymsg -- output DSI-1 dpms true
	else
		printf %s "$STATE"
	fi
}

xorginputevent() {
	STATE=off
	if xinput list-props "$TOUCH_POINTER_ID" | \
		grep "Device Enabled" | \
		grep -q "1$"; then
		STATE=on
	fi

	if [ "$1" = on ] && [ "$STATE" != on ]; then
		xinput enable "$TOUCH_POINTER_ID"
	elif [ "$1" = off ] && [ "$STATE" != off ] ; then
		xinput disable "$TOUCH_POINTER_ID"
	else
		printf %s "$STATE"
	fi
}

swayinputevent() {
	DEVICE=1046:4097:Goodix_Capacitive_TouchScreen
	STATE=on
	if swaymsg -t get_inputs \
		| jq -r '.[] | select(.type == "touch" ) | .libinput.send_events' \
		| grep -q "disabled"; then
		STATE=off
	fi

	if [ "$1" = on ] && [ "$STATE" != on ]; then
		swaymsg -- input "$DEVICE" events enabled
	elif [ "$1" = off ] && [ "$STATE" != off ] ; then
		swaymsg -- input "$DEVICE" events disabled
	else
		printf %s "$STATE"
	fi
}

xorgfocusedwindow() {
	activeoutput="$(xprop -id "$(xdotool getactivewindow)")"
	printf %s "$activeoutput" | \
		grep ^WM_CLASS | cut -d" " -f3- | cut -d"," -f1 | \
		xargs printf 'app: %s'
	printf "\n"
	printf %s "$activeoutput" | \
		grep ^WM_NAME | cut -d" " -f3- | cut -d"," -f1 |
		xargs printf 'title: %s'
}

swayfocusedwindow() {
	swaymsg -t get_tree \
		| jq -r '
			recurse(.nodes[]) |
			select(.focused == true) |
			{app_id: .app_id, name: .name} |
			"app: " + .app_id, "title: " + .name
		'
}

swayexec() {
	swaymsg exec -- "$@"
}

swayexecwait() {
	PIDFILE="$(mktemp)"
	printf '"%s" & printf %%s "$!" > "%s"' "$*" "$PIDFILE" \
		| xargs swaymsg exec -- sh -c
	while : ; do
		sleep 0.5
		kill -0 "$(cat "$PIDFILE")" 2> /dev/null || break
	done
	rm "$PIDFILE"
}

xorgexec() {
	"$@" &
}

xorgexecwait() {
	exec "$@"
}

guesswm() {
	if [ -n "$SWAYSOCK" ]; then
		printf "sway"
	elif [ -n "$DISPLAY" ]; then
		printf "dwm"
	elif [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
		printf "ssh"
	else
		printf "none"
	fi
}

wm="$(guesswm)"

if [ -z "$1" ]; then
	printf %s "$wm"
	exit
fi

action="$1"
shift
case "$wm" in
	dwm|xorg) "xorg$action" "$@";;
	*) "$wm$action" "$@";;
esac

A scripts/core/sxmo_wmtoggle.sh => scripts/core/sxmo_wmtoggle.sh +14 -0
@@ 0,0 1,14 @@
#!/bin/sh

wm="$(sxmo_wm.sh)"

case "$(realpath /var/lib/tinydm/default-session.desktop)" in
	/usr/share/wayland-sessions/swmo.desktop)
		sudo tinydm-set-session -f -s /usr/share/xsessions/sxmo.desktop
		;;
	/usr/share/xsessions/sxmo.desktop)
		sudo tinydm-set-session -f -s /usr/share/wayland-sessions/swmo.desktop
		;;
esac

sudo reboot

A scripts/core/sxmo_workspace.sh => scripts/core/sxmo_workspace.sh +66 -0
@@ 0,0 1,66 @@
#!/bin/bash

# include common definitions
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

current() {
	swaymsg -t get_outputs  | \
		jq -r '.[] | select(.focused == true) | .current_workspace'
}

next() {
	value="$(($(current)+1))"
	if [ "$value" -eq "$((${SXMO_WORKSPACE_WRAPPING:-4}+1))" ]; then
		printf 1
	else
		printf %s "$value"
	fi
}

previous() {
	value="$(($(current)-1))"
	if [ "$value" -lt 1 ]; then
		if [ "${SXMO_WORKSPACE_WRAPPING:-4}" -ne 0 ]; then
			printf %s "${SXMO_WORKSPACE_WRAPPING:-4}"
		fi
	else
		printf %s "$value"
	fi
}

sway() {
	case "$1" in
		next)
			printf "workspace "
			next;;
		previous)
			printf "workspace "
			previous;;
		move-next)
			printf "move container to workspace "
			next;;
		move-previous)
			printf "move container to workspace "
			previous;;
	esac | xargs swaymsg
}

dwm() {
	case "$1" in
		next)
			xdotool key Super+Shift+r
			;;
		previous)
			xdotool key Super+Shift+e
			;;
		move-next)
			xdotool key Super+r
			;;
		move-previous)
			xdotool key Super+e
			;;
	esac
}

"$(sxmo_wm.sh)" "$@"

M scripts/core/sxmo_xinit.sh => scripts/core/sxmo_xinit.sh +3 -2
@@ 112,12 112,13 @@ startdwm() {
}

xinit() {
	envvars
	device_envvars # set device env vars here to allow potentially overriding envvars

	# include common definitions
	# shellcheck source=scripts/core/sxmo_common.sh
	. "$(dirname "$0")/sxmo_common.sh"

	envvars
	device_envvars # set device env vars here to allow potentially overriding envvars
	setupxdgdir
	xdefaults
	daemons

M scripts/modem/sxmo_modemcall.sh => scripts/modem/sxmo_modemcall.sh +5 -5
@@ 26,7 26,7 @@ finish() {
		notify-send "$1"
	fi
	[ -n "$LOCKPID" ] && kill "$LOCKPID"
	pkill -9 dmenu
	sxmo_dmemu.sh close
	exit 1
}



@@ 181,13 181,13 @@ incallmenuloop() {
		$icon_phx Hangup                                                            ^ hangup $CALLID
	"

	pkill -9 dmenu # E.g. just incase user is playing with btns or hits a menu by mistake
	pkill -9 bemenu # E.g. just incase user is playing with btns or hits a menu by mistake
	echo "$CHOICES" |
		xargs -0 echo |
		cut -d'^' -f1 |
		sed '/^[[:space:]]*$/d' |
		awk '{$1=$1};1' | #this cryptic statement trims leading/trailing whitespace from a string
		dmenu -idx $DMENUIDX -l 14 "$([ "$WINDOWIFIED" = 0 ] && echo "-c" || echo "-wm")" -p "$NUMBER" |
		dmenu -ix $DMENUIDX "$([ "$WINDOWIFIED" = 0 ] && echo "" || echo "-wm")" -p "$NUMBER" |
		(
			PICKED="$(cat)";
			echo "sxmo_modemcall: Picked is $PICKED">&2


@@ 207,7 207,7 @@ dtmfmenu() {
	while true; do
		PICKED="$(
			echo "$NUMS" | grep -o . | sed '1 iReturn to Call Menu' |
			dmenu "$([ "$WINDOWIFIED" = 0 ] && echo "-c" || echo "-wm")" -l 20 -c -p "DTMF Tone"
			dmenu "$([ "$WINDOWIFIED" = 0 ] && echo "" || echo "-wm")" -p "DTMF Tone"
		)"
		echo "$PICKED" | grep "Return to Call Menu" && return
		modem_cmd_errcheck -m "$(modem_n)" -o "$CALLID" --send-dtmf="$PICKED"


@@ 234,7 234,7 @@ incomingcallmenu() {

	PICKED="$(
		printf %b "$icon_phn Pickup\n$icon_phx Hangup\n$icon_mut Mute\n" |
		dmenu -c -l 5 -p "$CONTACTNAME"
		dmenu -p "$CONTACTNAME"
	)" || exit

	if echo "$PICKED" | grep -q "Pickup"; then

M scripts/modem/sxmo_modemdial.sh => scripts/modem/sxmo_modemdial.sh +2 -2
@@ 28,14 28,14 @@ dialmenu() {
		NUMBER="$(
			printf %b "Close Menu\nMore contacts\n$CONTACTS" |
			grep . |
			sxmo_dmenu_with_kb.sh -l 10 -p Number -c -i
			sxmo_dmenu_with_kb.sh -p Number -i
		)"
		echo "$NUMBER" | grep "Close Menu" && kill -9 0

		echo "$NUMBER" | grep -q "More contacts" && NUMBER="$(
			printf %b "Close Menu\n$(sxmo_contacts.sh --all)" |
			grep . |
			sxmo_dmenu_with_kb.sh -l 10 -p Number -c -i
			sxmo_dmenu_with_kb.sh -p Number -i
		)"
		NUMBER="$(echo "$NUMBER" | cut -d: -f1 | tr -d -- '- ')"
	fi

M scripts/modem/sxmo_modeminfo.sh => scripts/modem/sxmo_modeminfo.sh +1 -1
@@ 1,7 1,7 @@
#!/usr/bin/env sh

err() {
	printf %b "$1" | dmenu -c -l 10
	printf %b "$1" | dmenu
	exit
}


M scripts/modem/sxmo_modemmonitor.sh => scripts/modem/sxmo_modemmonitor.sh +2 -6
@@ 161,8 161,6 @@ checkforincomingcalls() {
	INCOMINGNUMBER="$(cleanupnumber "$INCOMINGNUMBER")"
	CONTACTNAME=$(lookupcontactname "$INCOMINGNUMBER")

	xset dpms force on

	echo "sxmo_modemmonitor: Invoking ring hook (async)">&2
	sxmo_hooks.sh ring "$CONTACTNAME" &



@@ 188,8 186,6 @@ checkfornewtexts() {
	)"
	echo "$TEXTIDS" | grep -v . && return

	xset dpms force on

	# Loop each textid received and read out the data into appropriate logfile
	for TEXTID in $TEXTIDS; do
		TEXTDATA="$(mmcli -m "$(modem_n)" -s "$TEXTID" -K)"


@@ 321,8 317,8 @@ mainloop() {
					sleep 3
					if [ "$TRIES" -eq 10 ]; then
						echo failed > "$MODEMSTATEFILE"
						echo "sxmo_modemmonitor: forcing modem reset">&2
						sxmo_modemmonitortoggle.sh reset #will kill the modemmonitor too
						echo "sxmo_modemmonitor: forcing modem restart">&2
						sxmo_modemmonitortoggle.sh restart #will kill the modemmonitor too
						break
					fi
				fi

M scripts/modem/sxmo_modemmonitortoggle.sh => scripts/modem/sxmo_modemmonitortoggle.sh +62 -19
@@ 10,31 10,74 @@
# shellcheck source=scripts/core/sxmo_common.sh
. "$(dirname "$0")/sxmo_common.sh"

if [ "$1" = "reset" ]; then
	#does a hard reset of the entire modem
	echo "sxmo_modemmonitortoggle: forcing modem reset">&2
	notify-send "Resetting modem, this may take a minute..."
	pkill -TERM -f sxmo_modemmonitor.sh
ensure_daemon() {
	TRIES=0
	while ! rc-service "$1" status | grep -q started; do
		if [ "$TRIES" -eq 10 ]; then
			return 1
		fi
		TRIES=$((TRIES+1))
		sudo rc-service "$1" start
		sleep 5
	done

	return 0
}

ensure_daemons() {
	if (rc-service eg25-manager status | grep -q started) &&
		(rc-service modemmanager status | grep -q started); then
		return
	fi

	echo "sxmo_modemmonitortoggle: forcing modem restart" >&2
	notify-send "Resetting modem daemons, this may take a minute..."

	sudo rc-service modemmanager stop
	sudo rc-service eg25-manager stop
	sleep 5
	while ! rc-service eg25-manager status | grep -q started; do
		sudo rc-service eg25-manager start
		sleep 2
	sleep 2

	if ! (ensure_daemon eg25-manager && ensure_daemon modemmanager); then
		printf "failed\n" > "$MODEMSTATEFILE"
		notify-send --urgency=critical "We failed to start the modem daemons. We may need hard reboot."
		return 1
	fi
}

on() {
	rm "$NOTIFDIR"/incomingcall*

	TRIES=0
	while ! printf %s "$(mmcli -L)" 2> /dev/null | grep -qoE 'Modem\/([0-9]+)'; do
		TRIES=$((TRIES+1))
		if [ "$TRIES" -eq 10 ]; then
			printf "failed\n" > "$MODEMSTATEFILE"
			notify-send --urgency=critical "We failed to start the modem monitor. We may need hard reboot."
		fi
		sleep 5
	done
	sleep 5
	sudo rc-service modemmanager start
	sleep 30

	setsid -f sxmo_modemmonitor.sh &
elif [ "$1" != "on" ] && pgrep -f sxmo_modemmonitor.sh; then

	sleep 1
}

off() {
	pkill -TERM -f sxmo_modemmonitor.sh
elif [ "$1" != "off" ] && ! pgrep -f sxmo_modemmonitor.sh; then
	setsid -f sxmo_modemmonitor.sh &
fi
}

rm "$NOTIFDIR"/incomingcall*
if [ -z "$1" ]; then
	if pgrep -f sxmo_modemmonitor.sh; then
		set -- off
	else
		set -- on
	fi
fi

# E.g. wait until process killed or started -- maybe there's a better way..
sleep 1
case "$1" in
	restart) off; ensure_daemons && on;;
	on) ensure_daemons && on;;
	off) off;;
esac

sxmo_statusbarupdate.sh

M scripts/modem/sxmo_modemtext.sh => scripts/modem/sxmo_modemtext.sh +5 -5
@@ 6,7 6,7 @@

err() {
	echo "$1">&2
	echo "$1" | dmenu -c -l 10
	echo "$1" | dmenu
	kill $$
}



@@ 15,7 15,7 @@ choosenumbermenu() {
	NUMBER="$(
		printf %b "\n$icon_cls Cancel\n$icon_grp More contacts\n$(sxmo_contacts.sh | grep -E "^\+?[0-9]+:")" |
		awk NF |
		sxmo_dmenu_with_kb.sh -p "Number" -l 10 -c -i |
		sxmo_dmenu_with_kb.sh -p "Number" -i |
		cut -d: -f1 |
		tr -d -- '- '
	)"


@@ 23,7 23,7 @@ choosenumbermenu() {
		NUMBER="$( #joined words without space is not a bug
			printf %b "\nCancel\n$(sxmo_contacts.sh --all)" |
				grep . |
				sxmo_dmenu_with_kb.sh -l 10 -p "Number" -c -i |
				sxmo_dmenu_with_kb.sh -p "Number" -i |
				cut -d: -f1 |
				tr -d -- '- '
		)"


@@ 57,7 57,7 @@ sendtextmenu() {
	do
		CONFIRM="$(
			printf %b "$icon_edt Edit\n$icon_snd Send\n$icon_cls Cancel" |
			dmenu -c -idx 1 -p "Confirm" -l 10
			dmenu -i -p "Confirm"
		)" || exit
		if echo "$CONFIRM" | grep -q "Send"; then
			(sxmo_modemsendsms.sh "$NUMBER" - < "$DRAFT") && \


@@ 85,7 85,7 @@ readtextmenu() {
	printf %b "$icon_cls Close Menu\n$icon_edt Send a Text\n";
		sxmo_contacts.sh --texted | xargs -IL echo "L logfile"
	)"
	PICKED="$(printf %b "$ENTRIES" | dmenu -p Texts -c -l 10 -i)" || exit
	PICKED="$(printf %b "$ENTRIES" | dmenu -p Texts -i)" || exit

	if echo "$PICKED" | grep "Close Menu"; then
		exit 1

M scripts/notifications/sxmo_notificationsmenu.sh => scripts/notifications/sxmo_notificationsmenu.sh +1 -1
@@ 22,7 22,7 @@ notificationmenu() {
		sed '/^[[:space:]]*$/d' |
		awk '{$1=$1};1' |
		cut -d^ -f1 |
		dmenu -c -i -p "Notifs" -l 20
		dmenu -i -p "Notifs"
	)"

	echo "$PICKEDCONTENT" | grep -q "Close Menu" && exit 1