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/9] 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/9] 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}" From ba2f4d87f3da0f7390e00065a5f192b3b6cadee7 Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Mon, 9 Feb 2026 15:30:30 +0000 Subject: [PATCH 3/9] Refactoring of wrapper and scripts modernizations. Narrower scope of changes. --- .../com.secondlife.SecondLifeViewer.desktop | 24 +++++++ .../linux_tools/handle_secondlifeprotocol.sh | 7 +- indra/newview/linux_tools/install.sh | 25 ++++--- .../linux_tools/refresh_desktop_app_entry.sh | 66 +++---------------- .../register_secondlifeprotocol.sh | 65 +----------------- indra/newview/linux_tools/wrapper.sh | 39 +++++++++-- indra/newview/viewer_manifest.py | 1 + 7 files changed, 90 insertions(+), 137 deletions(-) create mode 100644 indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop mode change 100755 => 100644 indra/newview/linux_tools/handle_secondlifeprotocol.sh mode change 100755 => 100644 indra/newview/linux_tools/install.sh mode change 100755 => 100644 indra/newview/linux_tools/refresh_desktop_app_entry.sh mode change 100755 => 100644 indra/newview/linux_tools/register_secondlifeprotocol.sh mode change 100755 => 100644 indra/newview/linux_tools/wrapper.sh diff --git a/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop b/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop new file mode 100644 index 00000000000..9226261ac50 --- /dev/null +++ b/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop @@ -0,0 +1,24 @@ +[Desktop Entry] +Version=1.5 +Name=Second Life +GenericName=Second Life Viewer +Comment=Client for the Online Virtual World, Second Life +Path=@INSTALLATION_PREFIX@ +Exec=@INSTALLATION_PREFIX@/secondlife %u +Icon=com.secondlife.SecondLifeViewer +Terminal=false +Type=Application +Categories=Game;Simulation; +StartupNotify=true +StartupWMClass="com.secondlife.indra.viewer" +MimeType=x-scheme-handler/secondlife +PrefersNonDefaultGPU=true +Actions=DefaultGPU;AssociateMIME; + +[Desktop Action DefaultGPU] +Exec=env __GLX_VENDOR_LIBRARY_NAME=\"\" @INSTALLATION_PREFIX@/secondlife +Name=Launch on default GPU + +[Desktop Action AssociateMIME] +Exec=@INSTALLATION_PREFIX@/etc/register_secondlifeprotocol.sh +Name=Associate SLURLs diff --git a/indra/newview/linux_tools/handle_secondlifeprotocol.sh b/indra/newview/linux_tools/handle_secondlifeprotocol.sh old mode 100755 new mode 100644 index a5a67aaea4b..3fdabc7f842 --- a/indra/newview/linux_tools/handle_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/handle_secondlifeprotocol.sh @@ -1,9 +1,11 @@ -#!/usr/bin/env sh +#!/bin/bash + +# Note: This script is no longer used, as the main wrapper script is now handling SLURLs directly. # Send a URL of the form secondlife://... to any running viewer, if not, launch the default viewer. # -sl_url="$*" +sl_url="$1" echo "Got SLURL: ${sl_url}" if [ -z "${sl_url}" ]; then @@ -24,3 +26,4 @@ else #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 old mode 100755 new mode 100644 index 1cdfc711fd1..9eecff61a15 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -71,15 +71,17 @@ function homedir_install() fi 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). + local install_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. + local install_prefix="$HOME/.local/share/$installdir_name" fi + install_to_prefix "$install_prefix" + update_desktop_entry "$install_prefix" } function root_install() { - local default_prefix="/opt/secondlife-install" + local default_prefix="/opt/$installdir_name" echo -n "Enter the desired installation directory [${default_prefix}]: "; read @@ -92,6 +94,7 @@ function root_install() install_to_prefix "$install_prefix" mkdir -p /usr/local/share/applications + update_desktop_entry "$install_prefix" } function install_to_prefix() @@ -102,9 +105,6 @@ 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() @@ -115,17 +115,24 @@ function backup_previous_installation() mv "$1" "$backup_dir" || die "Failed to create backup of existing installation!" } -set_slurl_handler() +#Below function is not currently used as the desktop environment should prompt the user to associate SLURLs upon first use following installation. +function set_slurl_handler() { - install_dir=$1 + local install_prefix=$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. + "${install_prefix}"/etc/register_secondlifeprotocol.sh #Should prompt the desktop environment to set association. Normally not needed as it will prompt upon the first use of a SLURL after installation. } +function update_desktop_entry() +{ + local install_prefix=$1 + sed -i "s|@INSTALLATION_PREFIX@|$install_prefix|g" "$install_prefix/etc/com.secondlife.SecondLifeViewer.desktop" + "${install_prefix}"/etc/refresh_desktop_app_entry.sh +} 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 old mode 100755 new mode 100644 index ef413f56d53..4b0f36aba25 --- a/indra/newview/linux_tools/refresh_desktop_app_entry.sh +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh @@ -1,69 +1,21 @@ #!/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 desktop_entry="\ -[Desktop Entry]\n\ -Version=1.4\n\ -Name=${launcher_name}\n\ -GenericName=Second Life Viewer\n\ -Comment=Client for the Online Virtual World, Second Life\n\ -Path=${installation_prefix}\n\ -Exec=${installation_prefix}/secondlife\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 -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. - -#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.) + local installation_prefix="$1" + local desktop_entries_dir="$2" 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 + xdg-icon-resource install --novendor --size 256 "${installation_prefix}/secondlife_icon.png" "com.secondlife.SecondLifeViewer" + #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 "xViewer" to avoid potential naming conflicts, as per XDG spec. + xdg-desktop-menu install --novendor "${installation_prefix}"/etc/com.secondlife.SecondLifeViewer.desktop + + update-desktop-database "${desktop_entries_dir}" #Above command should update the menu system, but do it a second time just in case. } if [ "$UID" == "0" ]; then diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh old mode 100755 new mode 100644 index 4886a22024a..0531c20e337 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -1,66 +1,7 @@ -#!/bin/env sh +#!/bin/bash # Register a protocol handler (default: handle_secondlifeprotocol.sh) for # URLs of the form secondlife://... # - -desired_handler="${1}" - -print() { - log_prefix="RegisterSLProtocol:" - printf "%s %s\n" "${log_prefix}" "$*" -} -run_path=$(dirname "$0" || echo .) -cd "${run_path}/.." || exit - -if [ -z "${desired_handler}" ]; then - desired_handler="$(pwd)/etc/handle_secondlifeprotocol.sh" -fi - -# Ensure the handle_secondlifeprotocol.sh file is executeable (otherwise, xdg-mime won't work) -chmod +x "$desired_handler" - -# 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 - 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" +# Instead of forcing through an association, this should get the desktop environment to prompt the user if they wish to change their SLURL handler. +xdg-settings set default-url-scheme-handler secondlife com.secondlife.SecondLifeViewer.desktop diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh old mode 100755 new mode 100644 index bb76f41f2a5..cb3924b833c --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -35,7 +35,22 @@ cd "${RUN_PATH}" # Re-register the application with the desktop system every launch, for now. #./etc/refresh_desktop_app_entry.sh -# Above re-registering no longer used as viewer now registers itself via XDG. +# Above re-registering no longer used as viewer now registers itself via XDG and the Desktop Environment. + +#Below is a function to check if any additional parameters passed are a valid SLURL. +function is_valid_secondlife_uri() { + local uri="$1" + # Check if it starts with secondlife:// + if [[ ! "$uri" =~ ^secondlife:// ]]; then + return 1 + fi + # Pattern: secondlife:///// with optional additional parameters + if [[ "$uri" =~ ^secondlife://[^/]+/[0-9]+/[0-9]+/[0-9]+(/.*)?$ ]]; then + return 0 + else + return 1 + fi +} ## Before we mess with LD_LIBRARY_PATH, save the old one to restore for ## subprocesses that care. @@ -54,12 +69,22 @@ for ARG in "$@"; do fi done -# Run the program. -# Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the -# command line. But DO quote "${ARGS[@]}": preserve separate args as -# individually quoted. -$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${ARGS[@]}" -LL_RUN_ERR=$? +#Check if any additional arguments are valid SLURLs, and if so, check if a viewer instance is already running. If so, send the SLURL to be handled by the running viewer, instead of starting a new instance. +#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 is_valid_secondlife_uri "${ARGS[@]}" && \ + dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep -q "${service_name}"; then + echo "Found a Second Life compatible Viewer running, sending SLURL to DBus..."; + exec dbus-send --type=method_call --dest="${service_name}" /com/secondlife/ViewerAppAPI com.secondlife.ViewerAppAPI.GoSLURL string:"${ARGS[@]}" +else + # Run the program. + # Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the + # command line. But DO quote "${ARGS[@]}": preserve separate args as + # individually quoted. + echo "No running Second Life Viewer found, launching new instance..."; + $LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${ARGS[@]}" + LL_RUN_ERR=$? +fi # Handle any resulting errors if [ $LL_RUN_ERR -ne 0 ]; then diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 12705c4295e..8ce9b2c36c4 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1129,6 +1129,7 @@ def construct(self): self.path("handle_secondlifeprotocol.sh") self.path("register_secondlifeprotocol.sh") self.path("refresh_desktop_app_entry.sh") + self.path("com.secondlife.SecondLifeViewer.desktop") self.path("install.sh") with self.prefix(dst="bin"): From 955bb7dc076ee04bda34c70891474df9148bfe61 Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Mon, 9 Feb 2026 15:49:20 +0000 Subject: [PATCH 4/9] Pick up missed change --- indra/newview/linux_tools/install.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh index 9eecff61a15..51c84379014 100644 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -3,16 +3,6 @@ # 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' @@ -22,6 +12,16 @@ SCRIPTSRC=`readlink -f "$0" || echo "$0"` RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` tarball_path=${RUN_PATH} +build_data_file="${RUN_PATH}/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 + function prompt() { local prompt=$1 From 33118cda391f02166d5113dc966912a92a6d6d1b Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Mon, 9 Feb 2026 15:52:13 +0000 Subject: [PATCH 5/9] Second round of missed changes --- indra/newview/linux_tools/install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh index 51c84379014..ba11bc1a253 100644 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -70,7 +70,7 @@ function homedir_install() exit 0 fi - if [ -d "$XDG_DATA_HOME" ] ; then + if [ -n "$XDG_DATA_HOME" ] ; then local install_prefix="$XDG_DATA_HOME/$installdir_name" #$XDG_DATA_HOME is a synonym for $HOME/.local/share/ unless the user has specified otherwise (unlikely). else local install_prefix="$HOME/.local/share/$installdir_name" @@ -120,9 +120,9 @@ function set_slurl_handler() { local install_prefix=$1 echo - prompt "Would you like to set Second Life as your default SLurl handler? [Y/N]: " + prompt "Would you like to set Second Life as your default SLURL handler? [Y/N]: " if [ $? -eq 0 ]; then - exit 0 + return 0 fi "${install_prefix}"/etc/register_secondlifeprotocol.sh #Should prompt the desktop environment to set association. Normally not needed as it will prompt upon the first use of a SLURL after installation. } From 803a0fec4154200e8176c1c7c90347b198a639b7 Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:30:51 +0000 Subject: [PATCH 6/9] Address Copilot review round 2 --- .../linux_tools/com.secondlife.SecondLifeViewer.desktop | 2 +- indra/newview/linux_tools/install.sh | 4 ++-- indra/newview/linux_tools/refresh_desktop_app_entry.sh | 2 +- indra/newview/linux_tools/register_secondlifeprotocol.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop b/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop index 9226261ac50..047bfb9a674 100644 --- a/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop +++ b/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop @@ -11,7 +11,7 @@ Type=Application Categories=Game;Simulation; StartupNotify=true StartupWMClass="com.secondlife.indra.viewer" -MimeType=x-scheme-handler/secondlife +MimeType=x-scheme-handler/secondlife; PrefersNonDefaultGPU=true Actions=DefaultGPU;AssociateMIME; diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh index ba11bc1a253..9740c2151fe 100644 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -3,8 +3,6 @@ # Install the Second Life Viewer. This script can install the viewer both # system-wide and for an individual user. -echo "Installing ${channel} version ${version}" - VT102_STYLE_NORMAL='\E[0m' VT102_COLOR_RED='\E[31m' @@ -22,6 +20,8 @@ else exit 1 fi +echo "Installing ${channel} version ${version}" + function prompt() { local prompt=$1 diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh index 4b0f36aba25..7cf8dde8eaa 100644 --- a/indra/newview/linux_tools/refresh_desktop_app_entry.sh +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh @@ -15,7 +15,7 @@ function install_desktop_entry() #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 "xViewer" to avoid potential naming conflicts, as per XDG spec. xdg-desktop-menu install --novendor "${installation_prefix}"/etc/com.secondlife.SecondLifeViewer.desktop - update-desktop-database "${desktop_entries_dir}" #Above command should update the menu system, but do it a second time just in case. + xdg-desktop-menu forceupdate #Above command should update the menu system, but do it a second time just in case. } if [ "$UID" == "0" ]; then diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh index 0531c20e337..986cf21be51 100644 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -3,5 +3,5 @@ # Register a protocol handler (default: handle_secondlifeprotocol.sh) for # URLs of the form secondlife://... # -# Instead of forcing through an association, this should get the desktop environment to prompt the user if they wish to change their SLURL handler. +# Ask the Desktop Environment to change it's SLURL handler to this viewer. May prompt the user to select their preferred handler or do so silently depending on Desktop Environment. xdg-settings set default-url-scheme-handler secondlife com.secondlife.SecondLifeViewer.desktop From 81f6060103f991a83283c70b483a52723f7d338e Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:33:24 +0000 Subject: [PATCH 7/9] Update comment --- indra/newview/linux_tools/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh index 9740c2151fe..ee9b43161ee 100644 --- a/indra/newview/linux_tools/install.sh +++ b/indra/newview/linux_tools/install.sh @@ -115,7 +115,7 @@ function backup_previous_installation() mv "$1" "$backup_dir" || die "Failed to create backup of existing installation!" } -#Below function is not currently used as the desktop environment should prompt the user to associate SLURLs upon first use following installation. +#Below function is not currently used as the desktop environment should prompt the user to associate SLURLs upon first use following installation, however is included here if it's determined in future to be needed. function set_slurl_handler() { local install_prefix=$1 From 7b3a2362e19f8f4e432538056d183c95bea453f0 Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:04:02 +0000 Subject: [PATCH 8/9] Change to correct appid --- ...LifeViewer.desktop => com.secondlife.indra.viewer.desktop} | 0 indra/newview/linux_tools/refresh_desktop_app_entry.sh | 4 ++-- indra/newview/linux_tools/register_secondlifeprotocol.sh | 2 +- indra/newview/viewer_manifest.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename indra/newview/linux_tools/{com.secondlife.SecondLifeViewer.desktop => com.secondlife.indra.viewer.desktop} (100%) diff --git a/indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop b/indra/newview/linux_tools/com.secondlife.indra.viewer.desktop similarity index 100% rename from indra/newview/linux_tools/com.secondlife.SecondLifeViewer.desktop rename to indra/newview/linux_tools/com.secondlife.indra.viewer.desktop diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh index 7cf8dde8eaa..7bfaa906d25 100644 --- a/indra/newview/linux_tools/refresh_desktop_app_entry.sh +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh @@ -11,9 +11,9 @@ function install_desktop_entry() local desktop_entries_dir="$2" printf "Installing menu entries via XDG..." - xdg-icon-resource install --novendor --size 256 "${installation_prefix}/secondlife_icon.png" "com.secondlife.SecondLifeViewer" + xdg-icon-resource install --novendor --size 256 "${installation_prefix}/secondlife_icon.png" "com.secondlife.indra.viewer" #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 "xViewer" to avoid potential naming conflicts, as per XDG spec. - xdg-desktop-menu install --novendor "${installation_prefix}"/etc/com.secondlife.SecondLifeViewer.desktop + xdg-desktop-menu install --novendor "${installation_prefix}"/etc/com.secondlife.indra.viewer.desktop xdg-desktop-menu forceupdate #Above command should update the menu system, but do it a second time just in case. } diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh index 986cf21be51..69527d3c915 100644 --- a/indra/newview/linux_tools/register_secondlifeprotocol.sh +++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh @@ -4,4 +4,4 @@ # URLs of the form secondlife://... # # Ask the Desktop Environment to change it's SLURL handler to this viewer. May prompt the user to select their preferred handler or do so silently depending on Desktop Environment. -xdg-settings set default-url-scheme-handler secondlife com.secondlife.SecondLifeViewer.desktop +xdg-settings set default-url-scheme-handler secondlife com.secondlife.indra.viewer.desktop diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 8ce9b2c36c4..13219a7a97b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1129,7 +1129,7 @@ def construct(self): self.path("handle_secondlifeprotocol.sh") self.path("register_secondlifeprotocol.sh") self.path("refresh_desktop_app_entry.sh") - self.path("com.secondlife.SecondLifeViewer.desktop") + self.path("com.secondlife.indra.viewer.desktop") self.path("install.sh") with self.prefix(dst="bin"): From 9b7db585d3443a46d07c8b9883af0b68406f0e4b Mon Sep 17 00:00:00 2001 From: Ross Brown <128988672+Quinn-Elara@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:28:11 +0000 Subject: [PATCH 9/9] Fix icon line --- indra/newview/linux_tools/com.secondlife.indra.viewer.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/linux_tools/com.secondlife.indra.viewer.desktop b/indra/newview/linux_tools/com.secondlife.indra.viewer.desktop index 047bfb9a674..4ce2765714a 100644 --- a/indra/newview/linux_tools/com.secondlife.indra.viewer.desktop +++ b/indra/newview/linux_tools/com.secondlife.indra.viewer.desktop @@ -5,7 +5,7 @@ GenericName=Second Life Viewer Comment=Client for the Online Virtual World, Second Life Path=@INSTALLATION_PREFIX@ Exec=@INSTALLATION_PREFIX@/secondlife %u -Icon=com.secondlife.SecondLifeViewer +Icon=com.secondlife.indra.viewer Terminal=false Type=Application Categories=Game;Simulation;