From 72a8fa31c1d407dbe1727546fc2945bb32cabc8f Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Wed, 12 Nov 2025 12:11:39 +0000 Subject: [PATCH 1/2] Linux: Update linux scripts to use modern XDG handling for installation and SLURL handling --- .../linux_tools/handle_secondlifeprotocol.sh | 29 ++++-- indra/newview/linux_tools/install.sh | 34 ++++++- .../linux_tools/refresh_desktop_app_entry.sh | 62 +++++++++--- .../register_secondlifeprotocol.sh | 97 ++++++++++--------- indra/newview/linux_tools/wrapper.sh | 6 +- 5 files changed, 154 insertions(+), 74 deletions(-) diff --git a/indra/newview/linux_tools/handle_secondlifeprotocol.sh b/indra/newview/linux_tools/handle_secondlifeprotocol.sh index 203012132e7..a5a67aaea4b 100755 --- a/indra/newview/linux_tools/handle_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/handle_secondlifeprotocol.sh @@ -1,17 +1,26 @@ -#!/bin/bash +#!/usr/bin/env sh -# Send a URL of the form secondlife://... to Second Life. +# Send a URL of the form secondlife://... to any running viewer, if not, launch the default viewer. # -URL="$1" +sl_url="$*" -if [ -z "$URL" ]; then - echo Usage: $0 secondlife://... - exit +echo "Got SLURL: ${sl_url}" +if [ -z "${sl_url}" ]; then + echo "Usage: $0 secondlife:// ..." + exit fi -RUN_PATH=`dirname "$0" || echo .` -cd "${RUN_PATH}/.." - -exec ./secondlife -url \'"${URL}"\' +run_path=$(dirname "$0" || echo .) +#Poll DBus to get a list of registered services, then look through the list for the Second Life API Service - if present, this means a viewer is running, if not, then no viewer is running and a new instance should be launched +service_name="com.secondlife.ViewerAppAPIService" #Name of Second Life DBus service. This should be the same across all viewers. +if dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep -q "${service_name}"; then + echo "Second Life running, sending to DBus..."; + exec dbus-send --type=method_call --dest="${service_name}" /com/secondlife/ViewerAppAPI com.secondlife.ViewerAppAPI.GoSLURL string:"${sl_url}" +else + echo "Second Life not running, launching new instance..."; + cd "${run_path}"/.. || exit + #Go to .sh location (/etc), then up a directory to the viewer location + exec ./secondlife -url "${sl_url}" +fi diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh index c94510267ad..9b0eddfcc61 100755 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -3,6 +3,18 @@ # Install the Second Life Viewer. This script can install the viewer both # system-wide and for an individual user. +build_data_file="build_data.json" +if [ -f "${build_data_file}" ]; then + version=$(sed -n 's/.*"Version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "${build_data_file}") + channel=$(sed -n 's/.*"Channel"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "${build_data_file}") + installdir_name=$(echo "$channel" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' )-install +else + echo "Error: File ${build_data_file} not found." >&2 + exit 1 +fi + +echo "Installing ${channel} version ${version}" + VT102_STYLE_NORMAL='\E[0m' VT102_COLOR_RED='\E[31m' @@ -58,8 +70,11 @@ function homedir_install() exit 0 fi - install_to_prefix "$HOME/.secondlife-install" - $HOME/.secondlife-install/etc/refresh_desktop_app_entry.sh + if [ -d "$XDG_DATA_HOME" ] ; then + install_to_prefix "$XDG_DATA_HOME/$installdir_name" #$XDG_DATA_HOME is a synonym for $HOME/.local/share/ unless the user has specified otherwise (unlikely). + else + install_to_prefix "$HOME/.local/share/$installdir_name" #XDG_DATA_HOME not set, so use default path as defined by XDG spec. + fi } function root_install() @@ -77,7 +92,6 @@ function root_install() install_to_prefix "$install_prefix" mkdir -p /usr/local/share/applications - ${install_prefix}/etc/refresh_desktop_app_entry.sh } function install_to_prefix() @@ -88,6 +102,9 @@ function install_to_prefix() echo " - Installing to $1" cp -a "${tarball_path}"/* "$1/" || die "Failed to complete the installation!" + + "$1"/etc/refresh_desktop_app_entry.sh || echo "Failed to integrate into DE via XDG." + set_slurl_handler "$1" } function backup_previous_installation() @@ -98,6 +115,17 @@ function backup_previous_installation() mv "$1" "$backup_dir" || die "Failed to create backup of existing installation!" } +set_slurl_handler() +{ + install_dir=$1 + echo + prompt "Would you like to set Second Life as your default SLurl handler? [Y/N]: " + if [ $? -eq 0 ]; then + exit 0 + fi + "$install_dir"/etc/register_secondlifeprotocol.sh #Successful association comes with a notification to the user. +} + if [ "$UID" == "0" ]; then root_install diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh index 84af7505eab..ee8474ea7f6 100755 --- a/indra/newview/linux_tools/refresh_desktop_app_entry.sh +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh @@ -1,37 +1,69 @@ #!/bin/bash -SCRIPTSRC=`readlink -f "$0" || echo "$0"` -RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` +SCRIPTSRC=$(readlink -f "$0" || echo "$0") +RUN_PATH=$(dirname "${SCRIPTSRC}" || echo .) install_prefix="$(realpath -- "${RUN_PATH}/..")" +build_data_file="${install_prefix}/build_data.json" +if [ -f "${build_data_file}" ]; then + version=$(sed -n 's/.*"Version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "${build_data_file}") + channel_base=$(sed -n 's/.*"Channel Base"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "${build_data_file}") + channel=$(sed -n 's/.*"Channel"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "${build_data_file}") + desktopfilename=$(echo "$channel" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' )-viewer +else + echo "Error: File ${build_data_file} not found." >&2 + exit 1 +fi + +# Check for the Release channel. This channel should not have the channel name in its launcher. +if [ "$channel" = "$channel_base Release" ]; then + launcher_name="$channel_base" +else + launcher_name=$channel +fi + function install_desktop_entry() { - local installation_prefix="$1" - local desktop_entries_dir="$2" + local installation_prefix="${1}" + local desktop_entries_dir="${2}" local desktop_entry="\ [Desktop Entry]\n\ -Name=Second Life\n\ +Version=1.4\n\ +Name=${launcher_name}\n\ GenericName=Second Life Viewer\n\ -Comment=Client for the On-line Virtual World, Second Life\n\ +Comment=Client for the Online Virtual World, Second Life\n\ Path=${installation_prefix}\n\ Exec=${installation_prefix}/secondlife\n\ -Icon=${installation_prefix}/secondlife_icon.png\n\ +Icon=${desktopfilename}\n\ Terminal=false\n\ Type=Application\n\ Categories=Game;Simulation;\n\ StartupNotify=true\n\ -StartupWMClass="com.secondlife.indra.viewer"\n\ -X-Desktop-File-Install-Version=3.0" +StartupWMClass=\"com.secondlife.indra.viewer\"\n\ +X-Desktop-File-Install-Version=3.0 +PrefersNonDefaultGPU=true\n\ +Actions=DefaultGPU;AssociateMIME;\n\ +\n\ +[Desktop Action DefaultGPU]\n\ +Exec=env __GLX_VENDOR_LIBRARY_NAME=\"\" ${installation_prefix}/secondlife\n\ +Name=Launch on default GPU\n\ +\n\ +[Desktop Action AssociateMIME]\n\ +Exec=${installation_prefix}/etc/register_secondlifeprotocol.sh\n\ +Name=Associate SLURLs" +#The above adds some options when the shortcut is right-clicked, to launch on the default (usually integrated) GPU, and to force MIME type association. - echo " - Installing menu entries in ${desktop_entries_dir}" - WORK_DIR=`mktemp -d` - echo -e $desktop_entry > "${WORK_DIR}/secondlife-viewer.desktop" || "Failed to install application menu!" - desktop-file-install --dir="${desktop_entries_dir}" ${WORK_DIR}/secondlife-viewer.desktop - rm -r $WORK_DIR +#The "PrefersNonDefaultGPU" line should automatically run the viewer on the most powerful GPU in the system, if it is not default. If it is, this is ignored. - update-desktop-database "${desktop_entries_dir}" +# NOTE: DO NOT CHANGE THE "GenericName" FIELD - ONLY CHANGE THE "Name" FIELD. (This is to ensure that searching "Second Life" will show all the viewers installed in a user's system, regardless of their canonical name.) + + printf "Installing menu entries via XDG..." + printf "%b" "${desktop_entry}" > "${installation_prefix}/${desktopfilename}".desktop || echo "Failed to install application menu!" + xdg-icon-resource install --novendor --size 256 "${installation_prefix}/secondlife_icon.png" "${desktopfilename}" + #NOTE: Above command takes the path to the icon to install && The name of the icon to be used by XDG. This should always be in the format of "x-Viewer" to avoid potential naming conflicts, as per XDG spec. + xdg-desktop-menu install --novendor "${installation_prefix}"/"${desktopfilename}".desktop } if [ "$UID" == "0" ]; then diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh index d41e6dd6cbb..4886a22024a 100755 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -1,57 +1,66 @@ -#!/bin/bash +#!/bin/env sh # Register a protocol handler (default: handle_secondlifeprotocol.sh) for # URLs of the form secondlife://... # -HANDLER="$1" +desired_handler="${1}" -SCRIPTSRC=`readlink -f "$0" || echo "$0"` -RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` - -install_prefix="$(realpath -- "${RUN_PATH}/..")" - -cd "${RUN_PATH}/.." +print() { + log_prefix="RegisterSLProtocol:" + printf "%s %s\n" "${log_prefix}" "$*" +} +run_path=$(dirname "$0" || echo .) +cd "${run_path}/.." || exit -if [ -z "$HANDLER" ]; then - HANDLER=$install_prefix/etc/handle_secondlifeprotocol.sh +if [ -z "${desired_handler}" ]; then + desired_handler="$(pwd)/etc/handle_secondlifeprotocol.sh" fi -function install_desktop_entry() -{ - local installation_prefix="$1" - local desktop_entries_dir="$2" - - local desktop_entry="\ -[Desktop Entry]\n\ -Name=Second Life SLURL handler\n\ -Path=${installation_prefix}\n\ -Exec=${HANDLER} %u\n\ -Icon=${installation_prefix}/secondlife_icon.png\n\ -Terminal=false\n\ -Type=Application\n\ -StartupNotify=true\n\ -StartupWMClass="com.secondlife.indra.viewer"\n\ -NoDisplay=true\n\ -MimeType=x-scheme-handler/secondlife\n\ -X-Desktop-File-Install-Version=3.0" +# Ensure the handle_secondlifeprotocol.sh file is executeable (otherwise, xdg-mime won't work) +chmod +x "$desired_handler" - echo " - Installing protocol entries in ${desktop_entries_dir}" - WORK_DIR=`mktemp -d` - PROTOCOL_HANDLER="secondlife-protocol.desktop" - echo -e $desktop_entry > "${WORK_DIR}/${PROTOCOL_HANDLER}" || "Failed to create desktop file!" - desktop-file-install --dir="${desktop_entries_dir}" "${WORK_DIR}/${PROTOCOL_HANDLER}" || "Failed to install desktop file!" - rm -r $WORK_DIR - - xdg-mime default "${desktop_entries_dir}/${PROTOCOL_HANDLER}" x-scheme-handler/secondlife - - update-desktop-database "${desktop_entries_dir}" -} +# Check if xdg-mime is present, if so, use it to register new protocol. +if command -v xdg-mime >/dev/null 2>&1; then + urlhandler=$(xdg-mime query default x-scheme-handler/secondlife) + localappdir="${HOME}/.local/share/applications" + newhandler="secondlifeprotocol_$(basename "${PWD%}").desktop" + handlerpath="${localappdir}/${newhandler}" + cat >"${handlerpath}" </dev/null 2>&1; then + update-desktop-database "${localappdir}" + print "Registered ${desired_handler} as secondlife:// protocol handler with xdg-mime." + else + print "Warning: Cannot update desktop database, command missing - installation may be incomplete." + fi else - # user-specific - install_desktop_entry "$install_prefix" "$HOME/.local/share/applications" + print "Warning: Did not register secondlife:// handler with xdg-mime: Package not found." + #If XDG is not present, then do not handle, just warn. fi +notify-send -t 5000 -i info "Second Life URL Handler" "SLURL association created" diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 7e7a9a5e49c..bb76f41f2a5 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -30,10 +30,12 @@ echo "Running from ${RUN_PATH}" cd "${RUN_PATH}" # Re-register the secondlife:// protocol handler every launch, for now. -./etc/register_secondlifeprotocol.sh +#./etc/register_secondlifeprotocol.sh # Re-register the application with the desktop system every launch, for now. -./etc/refresh_desktop_app_entry.sh +#./etc/refresh_desktop_app_entry.sh + +# Above re-registering no longer used as viewer now registers itself via XDG. ## Before we mess with LD_LIBRARY_PATH, save the old one to restore for ## subprocesses that care. From d1c9d1ddbb564059255a278c5e9722f6c31b031f Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Mon, 17 Nov 2025 12:00:35 +0000 Subject: [PATCH 2/2] Remove whitespace Fixes precommit check --- indra/newview/linux_tools/install.sh | 2 +- indra/newview/linux_tools/refresh_desktop_app_entry.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh index 9b0eddfcc61..1cdfc711fd1 100755 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -102,7 +102,7 @@ function install_to_prefix() echo " - Installing to $1" cp -a "${tarball_path}"/* "$1/" || die "Failed to complete the installation!" - + "$1"/etc/refresh_desktop_app_entry.sh || echo "Failed to integrate into DE via XDG." set_slurl_handler "$1" } diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh index ee8474ea7f6..ef413f56d53 100755 --- a/indra/newview/linux_tools/refresh_desktop_app_entry.sh +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh @@ -58,7 +58,7 @@ Name=Associate SLURLs" #The "PrefersNonDefaultGPU" line should automatically run the viewer on the most powerful GPU in the system, if it is not default. If it is, this is ignored. # NOTE: DO NOT CHANGE THE "GenericName" FIELD - ONLY CHANGE THE "Name" FIELD. (This is to ensure that searching "Second Life" will show all the viewers installed in a user's system, regardless of their canonical name.) - + printf "Installing menu entries via XDG..." printf "%b" "${desktop_entry}" > "${installation_prefix}/${desktopfilename}".desktop || echo "Failed to install application menu!" xdg-icon-resource install --novendor --size 256 "${installation_prefix}/secondlife_icon.png" "${desktopfilename}"