Experimental: use yad for graphical menus that should work better with orca and Cthulhu screen readers.

This commit is contained in:
Storm Dragon
2025-08-04 18:02:58 -04:00
parent 6fcfdeca09
commit 37a731bab6

View File

@ -44,6 +44,158 @@ EOF
# Dialog accessibility
export DIALOGOPTS='--no-lines --visit-items'
# UI wrapper functions for dialog/yad switching
# Automatically switches between dialog (console) and yad (GUI) based on DISPLAY environment
# Wrapper function for menu selection
# Usage: ui_menu "title" "backtitle" "text" option1 "description1" option2 "description2" ...
ui_menu() {
local title="$1"
local back_title="$2"
local text="$3"
shift 3
if [[ "$dialog_type" == "yad" ]]; then
# Build yad list format: Display only, then map back to value
local yad_list=""
declare -A value_map
while [[ $# -gt 0 ]]; do
local option="$1"
local description="$2"
value_map["$description"]="$option"
if [[ -n "$yad_list" ]]; then
yad_list="$yad_list\n"
fi
yad_list="${yad_list}${description}"
shift 2
done
local selected_description
selected_description=$(echo -e "$yad_list" | yad --list \
--title="$title" \
--text="$text" \
--column="Option" \
--no-headers \
--selectable-labels \
--search-column=1 \
--height=400 \
--width=600)
# Strip trailing newline, pipe, and any other whitespace
selected_description=$(echo "$selected_description" | tr -d '\n\r' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/|$//')
# Return the mapped value
if [[ -n "$selected_description" ]]; then
echo "${value_map["$selected_description"]}"
fi
else
# Build dialog menu format with mapping (same approach as yad)
local dialog_args=()
declare -A value_map
while [[ $# -gt 0 ]]; do
local option="$1"
local description="$2"
value_map["$description"]="$option"
dialog_args+=("$description" "$description")
shift 2
done
local selected_description
selected_description=$(dialog --backtitle "$back_title" \
--title "$title" \
--no-tags \
--menu "$text" 0 0 0 \
"${dialog_args[@]}" \
--stdout)
# Return the mapped value
if [[ -n "$selected_description" ]]; then
echo "${value_map["$selected_description"]}"
fi
fi
}
# Wrapper function for message box
# Usage: ui_msgbox "title" "backtitle" "text"
ui_msgbox() {
local title="$1"
local back_title="$2"
local text="$3"
if [[ "$dialog_type" == "yad" ]]; then
yad --info \
--title="$title" \
--text="$text" \
--selectable-labels \
--show-cursor \
--width=400
else
dialog --backtitle "$back_title" \
--title "$title" \
--msgbox "$text" 0 0
fi
}
# Wrapper function for yes/no dialog
# Usage: ui_yesno "title" "backtitle" "text"
ui_yesno() {
local title="$1"
local back_title="$2"
local text="$3"
if [[ "$dialog_type" == "yad" ]]; then
yad --form \
--title="$title" \
--field="$text:LBL" \
--selectable-labels \
--button="Yes:0" \
--button="No:1" \
--width=400
else
dialog --backtitle "$back_title" \
--title "$title" \
--yesno "$text" 0 0
fi
}
# Wrapper function for info box (non-blocking message)
# Usage: ui_infobox "title" "backtitle" "text"
ui_infobox() {
local title="$1"
local back_title="$2"
local text="$3"
if [[ "$dialog_type" == "yad" ]]; then
# For yad, we'll use a notification since infobox is non-blocking
yad --notification \
--text="$text" \
--timeout=3
else
dialog --backtitle "$back_title" \
--title "$title" \
--infobox "$text" 0 0
fi
}
# Wrapper function for progress box
# Usage: command | ui_progressbox "title" "text"
ui_progressbox() {
local title="$1"
local text="$2"
if [[ "$dialog_type" == "yad" ]]; then
yad --progress \
--title="$title" \
--text="$text" \
--pulsate \
--auto-close \
--no-buttons \
--show-cursor \
--width=400
else
dialog --title "$title" \
--progressbox "$text" 20 70
fi
}
# Check for updates
check_update() {
@ -58,8 +210,7 @@ check_update() {
if [[ "$home" == "$remote" ]]; then
return
fi
dialog --backtitle "Linux Game manager" \
--yesno "Updates are available. Would you like to update now?" -1 -1 --stdout || return
ui_yesno "Linux Game Manager" "Linux Game manager" "Updates are available. Would you like to update now?" || return
# Store the current commit before pulling
local beforePull=$(git rev-parse HEAD)
git pull
@ -81,8 +232,7 @@ check_architecture() {
return
fi
done
dialog --backtitle "Linux Game Manager" \
--infobox "This game is not compatible with $architecture architecture." -1 -1
ui_infobox "Linux Game Manager" "Linux Game Manager" "This game is not compatible with $architecture architecture."
exit 1
}
@ -215,18 +365,15 @@ download() {
{ if ! curl -L4 -C - --retry 10 --output "${cache}/${dest}" "${i}" ; then
echo "Could not download \"$i\"..."
exit 1
fi; } | dialog --backtitle "Linux Game Manager" \
--progressbox "Downloading \"$dest\" from \"$i\"" -1 -1
fi; } | ui_progressbox "Linux Game Manager" "Downloading \"$dest\" from \"$i\""
local downloadError=1
case "${dest##*.}" in
"pk3"|"zip")
unzip -tq "${cache}/${dest}" | dialog --backtitle "Linux Game Manager" \
--progressbox "Validating ${dest##*.} file" -1 -1 --stdout
unzip -tq "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating ${dest##*.} file"
downloadError=$?
;;
"7z")
7z t "${cache}/${dest}" | dialog --backtitle "Linux Game Manager" \
--progressbox "Validating 7z file" -1 -1 --stdout
7z t "${cache}/${dest}" | ui_progressbox "Linux Game Manager" "Validating 7z file"
downloadError=$?
;;
"exe")
@ -249,8 +396,7 @@ download() {
esac
if [[ $downloadError -ne 0 ]]; then
rm -fv "${cache}/${dest}"
dialog --backtitle "Linux Game Manager" \
--infobox "Error downloading \"${dest}\". Installation cannot continue." -1 -1 --stdout
ui_infobox "Linux Game Manager" "Linux Game Manager" "Error downloading \"${dest}\". Installation cannot continue."
alert
exit 1
fi
@ -292,9 +438,7 @@ get_installer() {
fi
echo "Manual intervention required..."
alert
dialog --ok-label "Continue" \
--backtitle "Linux Game Manager" \
--msgbox "$message" -1 -1
ui_msgbox "Linux Game Manager" "Linux Game Manager" "$message"
# Search the Desktop and Downloads directories for the installation file
for i in ~/Downloads ~/Desktop ; do
find $i -type f -name "$1" -exec mv -v {} "${cache}/" \;
@ -369,10 +513,7 @@ game_installer() {
# Add donation option at the end
menuList+=("Donate" "Donate")
# Show game selection dialog
game="$(dialog --backtitle "Game Installer" \
--clear \
--no-tags \
--menu "Please select a game to install" 0 0 0 "${menuList[@]}" --stdout)"
game="$(ui_menu "Game Installer" "Game Installer" "Please select a game to install" "${menuList[@]}")"
# Handle selection
if [[ -n "$game" ]]; then
if [[ "$game" == "Donate" ]]; then
@ -386,8 +527,7 @@ game_installer() {
# Source and execute the install script
source "$installScript"
else
dialog --backtitle "Game Installer" \
--msgbox "Installation script not found for ${game}" -1 -1
ui_msgbox "Game Installer" "Game Installer" "Installation script not found for ${game}"
exit 1
fi
fi
@ -412,18 +552,19 @@ game_removal() {
fi
)
if [[ ${#menuList} -eq 0 ]]; then
dialog --backtitle "Linux Game Manager" \
--msgbox "No games found." -1 -1
ui_msgbox "Linux Game Manager" "Linux Game Manager" "No games found."
exit 0
fi
# Create the menu of installed games
# menuList has alternating full_path, display_name pairs
declare -a menuArgs
for ((i=0; i<${#menuList[@]}; i+=2)); do
menuArgs+=("${menuList[i]}" "${menuList[i+1]}")
done
local selectedGame
selectedGame=$(dialog --backtitle "Linux Game Manager" \
--clear \
--no-tags \
--menu "Please select a game to delete" 0 0 0 "${menuList[@]}" --stdout)
selectedGame=$(ui_menu "Linux Game Manager" "Linux Game Manager" "Please select a game to delete" "${menuArgs[@]}")
exitCode=$?
[[ $exitCode -ne 0 ]] && exit 0
[[ $exitCode -ne 0 ]] || [[ -z "$selectedGame" ]] && exit 0
# Get the actual game file paths
local gameName="${selectedGame##*/}"
gameName="${gameName%.sh}"
@ -435,21 +576,17 @@ game_removal() {
gameInstallPath="${installPath}/${gameInstallPath%/*}"
if [[ -z "$gameInstallPath" ]] || [[ "${gameInstallPath%%/}" == "$installPath" ]]; then
# No install path found, just remove from list
dialog --backtitle "Linux Game Manager" \
--yesno "This will remove the game from your game list, but will not remove any files. Do you want to continue?" -1 -1 || exit 0
ui_yesno "Linux Game Manager" "Linux Game Manager" "This will remove the game from your game list, but will not remove any files. Do you want to continue?" || exit 0
# Remove only the .sh symlink
rm -fv "${0%/*}/.launch/${gameName}.sh" | \
dialog --backtitle "Linux Game Manager" \
--progressbox "Removing game from list..." -1 -1
ui_progressbox "Linux Game Manager" "Removing game from list..."
else
# Found install path, can remove game files
dialog --backtitle "Linux Game Manager" \
--yesno "This will remove the directory \"${gameInstallPath}\" and all of its contents. Do you want to continue?" -1 -1 || exit 0
ui_yesno "Linux Game Manager" "Linux Game Manager" "This will remove the directory \"${gameInstallPath}\" and all of its contents. Do you want to continue?" || exit 0
# Remove the game directory and symlink
{ rm -rfv "${gameInstallPath}"
rm -fv "${0%/*}/.launch/${gameName}.sh";
} | dialog --backtitle "Linux Game Manager" \
--progressbox "Removing game..." -1 -1
} | ui_progressbox "Linux Game Manager" "Removing game..."
fi
exit 0
}
@ -469,10 +606,7 @@ game_update() {
done
menuList+=("Donate" "Donate")
menuList+=("Become a Patron" "Become a Patron")
local game="$(dialog --backtitle "Audio Game Updater" \
--clear \
--no-tags \
--menu "Please select a game to update" 0 0 0 "${menuList[@]}" --stdout)"
local game="$(ui_menu "Audio Game Updater" "Audio Game Updater" "Please select a game to update" "${menuList[@]}")"
if [[ ${#game} -gt 0 ]]; then
if [[ "$game" == "Donate" ]]; then
open_url "https://ko-fi.com/stormux"
@ -482,8 +616,10 @@ game_update() {
open_url "https://2mb.games/product/2mb-patron/"
exit 0
fi
source "${game}"
else
exit 0
fi
source "${game}"
run_update
exit 0
}
@ -504,17 +640,18 @@ game_launcher() {
fi
)
if [[ ${#menuList} -eq 0 ]]; then
dialog --backtitle "Linux Game Manager" \
--msgbox "No games found." 5 20
ui_msgbox "Linux Game Manager" "Linux Game Manager" "No games found."
exit 0
fi
# Create the menu of all games
selectedGame="$(dialog --backtitle "Linux Game Launcher" \
--clear \
--no-tags \
--menu "Please select a game to play" 0 0 0 "${menuList[@]}" --stdout)"
# Create the menu of all games
# menuList has alternating full_path, display_name pairs
declare -a menuArgs
for ((i=0; i<${#menuList[@]}; i+=2)); do
menuArgs+=("${menuList[i]}" "${menuList[i+1]}")
done
selectedGame="$(ui_menu "Linux Game Launcher" "Linux Game Launcher" "Please select a game to play" "${menuArgs[@]}")"
local menuCode=$?
if [[ $menuCode -eq 1 ]]; then
if [[ $menuCode -ne 0 ]] || [[ -z "$selectedGame" ]]; then
exit 0
fi
. "${selectedGame}"
@ -538,11 +675,18 @@ migrate_launcher() {
done < <(sed '/^$/d' "${configFile}")
# Move the old config file and notify user
mv "${configFile}" "${configFile}.bak"
dialog --backtitle "Linux Game manager" --msgbox \
"Games have been converted to the new launch system.\nThe old game launch information has been moved to ${configFile}.bak\nIf everything works like you expect, feel free to delete ${configFile}" -1 -1
ui_msgbox "Linux Game Manager" "Linux Game manager" "Games have been converted to the new launch system.\nThe old game launch information has been moved to ${configFile}.bak\nIf everything works like you expect, feel free to delete ${configFile}"
}
# Detect dialog interface type BEFORE potentially setting DISPLAY
# This must happen before we modify DISPLAY to preserve console detection
if [[ -z "$DISPLAY" ]]; then
dialog_type="dialog"
else
dialog_type="yad"
fi
# If display isn't set assume we are launching from console and an X environment is running using display :0
# Warning, launching games from console is not recommended.
if [[ -z "$DISPLAY" ]]; then
@ -618,8 +762,7 @@ while getopts "${args}" i ; do
r) game_removal ;;
t)
gameCount=$(find .install -type f -iname "*.sh" | wc -l)
dialog --backtitle "Linux Game Manager" \
--infobox "There are currently ${gameCount} games available." -1 -1
ui_infobox "Linux Game Manager" "Linux Game Manager" "There are currently ${gameCount} games available."
exit 0
;;
u) game_update ;;