Add two standalone X11 games (not DWM plugins) for the Nokia 8110 keypad: - src/games/snake.cpp: Nokia Snake II-style game, 240x296, built-in 5x7 font - src/games/tetris.cpp: Tetris with next-piece preview, levels, line clears Both float as dialog windows in dwm, use a self-contained bitmap font (no font-file dependency), and are controlled via the numeric keypad (2/4/6/8 directions, 5 action) with arrow-key fallbacks. - scripts/build-games.sh: Docker armv7 cross-compile (mirrors build-sxmo-x11.sh) - overlay/rootfs/usr/share/sxmo/default_hooks/sxmo_hook_games.sh: Games menu hook - overlay/rootfs/usr/bin/sxmo_appmenu.sh: add 'Games' entry after 'Apps' and a games submenu case Binaries committed to prebuilt/games and overlay/rootfs/usr/bin per repo convention. Deployed and verified on the live device (window maps, dwm focuses it, keypad input reaches the game).
338 lines
7.9 KiB
Bash
Executable File
338 lines
7.9 KiB
Bash
Executable File
#!/bin/sh
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# Copyright 2022 Sxmo Contributors
|
|
|
|
if [ "${1:-}" = "--fallback" ]; then
|
|
shift
|
|
elif [ -p /tmp/dwm_plugin_dmenu.fifo ]; then
|
|
case "${1:-}" in
|
|
""|sys|applications|scripts|modem|config|power|games|sthotkeys)
|
|
exec dmenu "${1:-ctx}"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# include common definitions
|
|
# shellcheck source=configs/default_hooks/sxmo_hook_icons.sh
|
|
. sxmo_hook_icons.sh
|
|
# shellcheck source=scripts/core/sxmo_common.sh
|
|
. sxmo_common.sh
|
|
|
|
unalias dmenu 2>/dev/null || true
|
|
unalias bemenu 2>/dev/null || true
|
|
|
|
confirm() {
|
|
PICKED="$(printf "Yes\nNo\n" | run_dmenu -p "Confirm $1")"
|
|
|
|
if [ "$PICKED" = "Yes" ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
run_dmenu() {
|
|
if [ "${SXMO_WM:-dwm}" = "dwm" ] && command -v dmenu >/dev/null 2>&1; then
|
|
dmenu -c -l "${SXMO_DMENU_PORTRAIT_LINES:-10}" "$@"
|
|
else
|
|
sxmo_dmenu.sh "$@"
|
|
fi
|
|
}
|
|
|
|
supertoggle_daemon() {
|
|
if superctl status "$1" | grep -q started; then
|
|
superctl stop "$1"
|
|
sxmo_notify_user.sh "$1 Stopped"
|
|
else
|
|
superctl start "$1"
|
|
sxmo_notify_user.sh "$1 Started"
|
|
fi
|
|
}
|
|
|
|
toggle_daemon() {
|
|
name="$1"
|
|
shift
|
|
|
|
if sxmo_jobs.sh running "$1" -q; then
|
|
sxmo_jobs.sh stop "$@"
|
|
notify-send "$name Stopped"
|
|
else
|
|
sxmo_jobs.sh start "$@" &
|
|
notify-send "$name Started"
|
|
fi
|
|
}
|
|
|
|
sxmo_type() {
|
|
sxmo_type.sh -s 200 "$@"
|
|
}
|
|
|
|
get_focused_window() {
|
|
if [ -r "${XDG_RUNTIME_DIR:-/run/user/10000}/sxmo.focusedwin" ]; then
|
|
{
|
|
read -r WMCLASS || WMCLASS=""
|
|
read -r WMNAME || WMNAME=""
|
|
} < "${XDG_RUNTIME_DIR:-/run/user/10000}/sxmo.focusedwin"
|
|
return
|
|
fi
|
|
exec 0<<EOF
|
|
$(sxmo_wm.sh focusedwindow -r)
|
|
EOF
|
|
read -r WMCLASS
|
|
read -r WMNAME
|
|
}
|
|
|
|
has_tracked_calls() {
|
|
[ -d "$XDG_RUNTIME_DIR/sxmo_calls" ] || return 1
|
|
for f in "$XDG_RUNTIME_DIR/sxmo_calls"/*; do
|
|
[ -e "$f" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
call_entries() {
|
|
has_tracked_calls || return 0
|
|
shown_incall_menu=
|
|
sxmo_modemcall.sh list_active_calls | while read -r line; do
|
|
case "$line" in
|
|
*"(ringing-in)")
|
|
CALLID="${line%% *}"
|
|
CALLID="${CALLID##*/}"
|
|
NUMBER="$(sxmo_modemcall.sh vid_to_number "$CALLID")"
|
|
CONTACT="$(sxmo_contacts.sh --name "$NUMBER")"
|
|
|
|
printf "%s Incoming call %s ^ 0 ^ sxmo_jobs.sh start incall_menu sxmo_modemcall.sh incoming_call_menu %s\n" \
|
|
"$icon_phn" "$CONTACT" "$CALLID"
|
|
;;
|
|
*)
|
|
[ -n "$shown_incall_menu" ] && continue
|
|
shown_incall_menu=1
|
|
printf "%s Incall Menu ^ 0 ^ sxmo_jobs.sh start incall_menu sxmo_modemcall.sh incall_menu\n" \
|
|
"$icon_phn"
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
count_notifications() {
|
|
n=0
|
|
if [ -d "$SXMO_NOTIFDIR" ]; then
|
|
for f in "$SXMO_NOTIFDIR"/*; do
|
|
[ -f "$f" ] && n=$((n + 1))
|
|
done
|
|
fi
|
|
printf "%s" "$n"
|
|
}
|
|
|
|
bt_is_unblocked_fast() {
|
|
for rfk in /sys/class/rfkill/rfkill*; do
|
|
[ -r "$rfk/type" ] || continue
|
|
read -r rtype < "$rfk/type" 2>/dev/null || continue
|
|
if [ "$rtype" = "bluetooth" ]; then
|
|
read -r soft < "$rfk/soft" 2>/dev/null || soft=0
|
|
read -r hard < "$rfk/hard" 2>/dev/null || hard=0
|
|
[ "$soft" = "0" ] && [ "$hard" = "0" ] && return 0
|
|
return 1
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
fast_sys_choices() {
|
|
WINNAME="Sys"
|
|
_bt_line=""
|
|
if bt_is_unblocked_fast; then
|
|
_bt_line="$icon_bth Bluetooth^1^sxmo_bluetoothmenu.sh
|
|
"
|
|
fi
|
|
_flash_line=""
|
|
_bl=""
|
|
if [ -r /sys/class/leds/white:torch/brightness ]; then
|
|
read -r _bl < /sys/class/leds/white:torch/brightness 2>/dev/null || _bl=""
|
|
elif [ -r /sys/class/leds/white:flash/brightness ]; then
|
|
read -r _bl < /sys/class/leds/white:flash/brightness 2>/dev/null || _bl=""
|
|
fi
|
|
if [ -n "$_bl" ]; then
|
|
if [ "$_bl" -gt 0 ] 2>/dev/null; then
|
|
_flash_line="$icon_fll Flashlight $icon_ton^1^sxmo_flashtoggle.sh
|
|
"
|
|
else
|
|
_flash_line="$icon_fll Flashlight $icon_tof^1^sxmo_flashtoggle.sh
|
|
"
|
|
fi
|
|
fi
|
|
CHOICES="$icon_trm Terminal^0^st -e ${SHELL:-/bin/sh}
|
|
$icon_grd Apps^0^sxmo_appmenu.sh applications
|
|
$icon_gam Games^0^sxmo_appmenu.sh games
|
|
$icon_grd Scripts^0^sxmo_appmenu.sh scripts
|
|
$icon_dir Files^0^xfiles
|
|
$icon_phn Dialer^0^xdialer
|
|
$icon_phl Call Log^0^xcalllog
|
|
$icon_msg Texts^0^xsms
|
|
$icon_usr Contacts^0^xcontacts
|
|
${_bt_line}$icon_cam Camera^0^xcamera
|
|
${_flash_line}$icon_net Networks^0^sxmo_networks.sh
|
|
$icon_mus Audio^0^sxmo_audio.sh
|
|
$icon_phn Modem^0^sxmo_appmenu.sh modem
|
|
$icon_win Windows^0^sxmo_wmmenu.sh
|
|
$icon_cfg Themes^0^xthemes
|
|
$icon_cfg Config^0^sxmo_appmenu.sh config
|
|
$icon_pwr Power^0^sxmo_appmenu.sh power"
|
|
}
|
|
|
|
getprogchoices() {
|
|
case "$WMCLASS" in
|
|
""|sys)
|
|
fast_sys_choices
|
|
;;
|
|
applications)
|
|
WINNAME="Apps"
|
|
if [ -s "${XDG_RUNTIME_DIR:-/tmp}/sxmo_apps.cache" ]; then
|
|
CHOICES="$(cat "${XDG_RUNTIME_DIR:-/tmp}/sxmo_apps.cache")"
|
|
else
|
|
CHOICES="$(sxmo_hook_apps.sh)"
|
|
fi
|
|
;;
|
|
games)
|
|
WINNAME="Games"
|
|
CHOICES="$(sxmo_hook_games.sh)"
|
|
;;
|
|
scripts)
|
|
WINNAME="Scripts"
|
|
if [ -s "${XDG_RUNTIME_DIR:-/tmp}/sxmo_scripts.cache" ]; then
|
|
CHOICES="$(cat "${XDG_RUNTIME_DIR:-/tmp}/sxmo_scripts.cache")"
|
|
else
|
|
CHOICES="$(sxmo_hook_scripts.sh)"
|
|
fi
|
|
;;
|
|
power)
|
|
WINNAME="Power"
|
|
CHOICES="$icon_lck Lock^0^sxmo_state.sh set lock
|
|
$icon_lck Lock (Screen off)^0^sxmo_state.sh set screenoff
|
|
$icon_out Logout^0^confirm Logout && sxmo_power.sh logout
|
|
$icon_rld Reboot^0^confirm Reboot && sxmo_power.sh reboot
|
|
$icon_pwr Poweroff^0^confirm Poweroff && sxmo_power.sh poweroff"
|
|
;;
|
|
modem)
|
|
WINNAME="Modem"
|
|
CHOICES="$icon_plk Modem PIN^0^sxmo_unlocksim.sh
|
|
$icon_inf Modem Info^0^sxmo_modeminfo.sh
|
|
$icon_phl Modem Log^0^sxmo_modemlog.sh"
|
|
;;
|
|
config)
|
|
WINNAME="Config"
|
|
_bt_icon="$icon_tof"
|
|
bt_is_unblocked_fast && _bt_icon="$icon_ton"
|
|
_susp_icon="$icon_ton"
|
|
[ -e "${XDG_CACHE_HOME:-$HOME/.cache}/sxmo/sxmo.nosuspend" ] && _susp_icon="$icon_tof"
|
|
CHOICES="$icon_cfg Themes^0^xthemes
|
|
$icon_aru Brightness^1^sxmo_brightness.sh up
|
|
$icon_ard Brightness^1^sxmo_brightness.sh down
|
|
$icon_cfg Toggle Bar^0^sxmo_wm.sh togglebar
|
|
$icon_bth Bluetooth $_bt_icon^1^doas sxmo_bluetoothtoggle.sh && sxmo_hook_statusbar.sh bluetooth
|
|
$icon_clk Change Timezone^1^sxmo_timezonechange.sh
|
|
$icon_zzz Auto-suspend $_susp_icon^1^(rm ${XDG_CACHE_HOME:-$HOME/.cache}/sxmo/sxmo.nosuspend 2>/dev/null || touch ${XDG_CACHE_HOME:-$HOME/.cache}/sxmo/sxmo.nosuspend)
|
|
$icon_trm Hooks^0^sxmo_hookmenu.sh
|
|
$icon_cfg Suspend Blockers^0^sxmo_terminal.sh sxmo_debug_suspend.sh
|
|
$icon_inf Log^0^sxmo_terminal.sh tail -n 100 -f ${XDG_STATE_HOME:-$HOME}/sxmo.log
|
|
$icon_inf Version^0^sxmo_terminal.sh sxmo_version.sh --block"
|
|
;;
|
|
*)
|
|
RES="$(sxmo_hook_contextmenu.sh "$WMCLASS" "$WMNAME")"
|
|
if [ -n "$RES" ]; then
|
|
nl='
|
|
'
|
|
WINNAME="${RES%%"$nl"*}"
|
|
CHOICES="${RES#*"$nl"}"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [ "$WINNAME" = "Sys" ]; then
|
|
NNOTIFICATIONS="$(count_notifications)"
|
|
if [ "$NNOTIFICATIONS" -gt 0 ]; then
|
|
CHOICES="$icon_bel Notifications ($NNOTIFICATIONS)^0^sxmo_notifs.sh menu
|
|
$CHOICES"
|
|
fi
|
|
fi
|
|
|
|
if has_tracked_calls; then
|
|
CHOICES="$(call_entries)
|
|
$CHOICES"
|
|
fi
|
|
|
|
case "$WINNAME" in
|
|
*Sys*) ;;
|
|
*)
|
|
CHOICES="$CHOICES
|
|
$icon_mnu System Menu^0^sxmo_appmenu.sh sys"
|
|
;;
|
|
esac
|
|
|
|
CHOICES="$CHOICES
|
|
$icon_cls Close Menu^0^quit"
|
|
|
|
case "$WMCLASS" in
|
|
""|sys|applications|scripts|power|modem|config)
|
|
;;
|
|
*)
|
|
CHOICES="$(printf "%s\n" "$CHOICES" | awk 'NF {$1=$1; print}')"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
quit() {
|
|
exit 0
|
|
}
|
|
|
|
mainloop() {
|
|
getprogchoices
|
|
PICKED="$(
|
|
printf "%s\n" "$CHOICES" |
|
|
cut -d'^' -f1 |
|
|
run_dmenu -i -p "$WINNAME"
|
|
)" || quit
|
|
|
|
CHOICE="$(printf "%s\n" "$CHOICES" | awk -F '^' -v picked="$PICKED" \
|
|
'$1 == picked || $1 == picked " " {print $2 "^" $3; exit}'
|
|
)"
|
|
|
|
LOOP="${CHOICE%%^*}"
|
|
CMD="${CHOICE#*^}"
|
|
CMD="${CMD#"${CMD%%[![:space:]]*}"}"
|
|
|
|
if [ -z "$CHOICE" ] || [ -z "$CMD" ]; then
|
|
printf "%s\n" "sxmo_appmenu: Fallback: unknown choice <$PICKED> to contextmenu_fallback hook">&2
|
|
sxmo_hook_contextmenu_fallback.sh "$WINNAME" "$PICKED"
|
|
quit
|
|
fi
|
|
|
|
case "$CMD" in
|
|
"sxmo_appmenu.sh "*)
|
|
set -- ${CMD#sxmo_appmenu.sh }
|
|
WMCLASS="$1"
|
|
WMNAME="$2"
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
eval "$CMD"
|
|
|
|
case "$LOOP" in
|
|
*1*) ;;
|
|
*) quit ;;
|
|
esac
|
|
}
|
|
|
|
if [ -z "$SHELLSPEC_PATH" ]; then
|
|
if [ $# -gt 0 ] ; then
|
|
WMCLASS="$1"
|
|
WMNAME="$2"
|
|
else
|
|
get_focused_window
|
|
fi
|
|
|
|
while true; do
|
|
mainloop
|
|
done
|
|
fi
|