update electron to v43

This commit is contained in:
olcxja 2026-07-09 22:38:33 +02:00
commit fb6c8b6ee9
5385 changed files with 513060 additions and 123058 deletions

View file

@ -22,9 +22,7 @@
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="${minVersion}" MaxVersionTested="${maxVersionTested}" />
</Dependencies>
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
</Capabilities>
${capabilities}
<Applications>
<Application Id="${applicationId}" Executable="${executable}" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements

View file

@ -1,10 +1,57 @@
#!/bin/bash
# Link to the binary
ln -sf '/opt/${sanitizedProductName}/${executable}' '/usr/bin/${executable}'
if type update-alternatives >/dev/null 2>&1; then
# Remove previous link if it doesn't use update-alternatives
if [ -L '/usr/bin/${executable}' -a -e '/usr/bin/${executable}' -a "`readlink '/usr/bin/${executable}'`" != '/etc/alternatives/${executable}' ]; then
rm -f '/usr/bin/${executable}'
fi
update-alternatives --install '/usr/bin/${executable}' '${executable}' '/opt/${sanitizedProductName}/${executable}' 100 || ln -sf '/opt/${sanitizedProductName}/${executable}' '/usr/bin/${executable}'
else
ln -sf '/opt/${sanitizedProductName}/${executable}' '/usr/bin/${executable}'
fi
# SUID chrome-sandbox for Electron 5+
chmod 4755 '/opt/${sanitizedProductName}/chrome-sandbox' || true
# Check if user namespaces are supported by the kernel and working with a quick test:
if ! { [[ -L /proc/self/ns/user ]] && unshare --user true; }; then
# Use SUID chrome-sandbox only on systems without user namespaces:
chmod 4755 '/opt/${sanitizedProductName}/chrome-sandbox' || true
else
chmod 0755 '/opt/${sanitizedProductName}/chrome-sandbox' || true
fi
update-mime-database /usr/share/mime || true
update-desktop-database /usr/share/applications || true
if hash update-mime-database 2>/dev/null; then
update-mime-database /usr/share/mime || true
fi
if hash update-desktop-database 2>/dev/null; then
update-desktop-database /usr/share/applications || true
fi
# Install apparmor profile. (Ubuntu 24+)
# First check if the version of AppArmor running on the device supports our profile.
# This is in order to keep backwards compatibility with Ubuntu 22.04 which does not support abi/4.0.
# In that case, we just skip installing the profile since the app runs fine without it on 22.04.
#
# Those apparmor_parser flags are akin to performing a dry run of loading a profile.
# https://wiki.debian.org/AppArmor/HowToUse#Dumping_profiles
#
# Unfortunately, at the moment AppArmor doesn't have a good story for backwards compatibility.
# https://askubuntu.com/questions/1517272/writing-a-backwards-compatible-apparmor-profile
if apparmor_status --enabled > /dev/null 2>&1; then
APPARMOR_PROFILE_SOURCE='/opt/${sanitizedProductName}/resources/apparmor-profile'
APPARMOR_PROFILE_TARGET='/etc/apparmor.d/${executable}'
if apparmor_parser --skip-kernel-load --debug "$APPARMOR_PROFILE_SOURCE" > /dev/null 2>&1; then
cp -f "$APPARMOR_PROFILE_SOURCE" "$APPARMOR_PROFILE_TARGET"
# Updating the current AppArmor profile is not possible and probably not meaningful in a chroot'ed environment.
# Use cases are for example environments where images for clients are maintained.
# There, AppArmor might correctly be installed, but live updating makes no sense.
if ! { [ -x '/usr/bin/ischroot' ] && /usr/bin/ischroot; } && hash apparmor_parser 2>/dev/null; then
# Extra flags taken from dh_apparmor:
# > By using '-W -T' we ensure that any abstraction updates are also pulled in.
# https://wiki.debian.org/AppArmor/Contribute/FirstTimeProfileImport
apparmor_parser --replace --write-cache --skip-read-cache "$APPARMOR_PROFILE_TARGET"
fi
else
echo "Skipping the installation of the AppArmor profile as this version of AppArmor does not seem to support the bundled profile"
fi
fi

View file

@ -1,4 +1,27 @@
#!/bin/bash
# Delete the link to the binary
rm -f '/usr/bin/${executable}'
# update-alternatives --remove <name> <path>: 'path' must be the registered alternative binary,
# not the generic symlink — see https://man7.org/linux/man-pages/man1/update-alternatives.1.html
if type update-alternatives >/dev/null 2>&1; then
update-alternatives --remove '${executable}' '/opt/${sanitizedProductName}/${executable}'
else
rm -f '/usr/bin/${executable}'
fi
APPARMOR_PROFILE_DEST='/etc/apparmor.d/${executable}'
# Remove and unload apparmor profile.
if [ -f "$APPARMOR_PROFILE_DEST" ]; then
# Unload the profile from the running kernel before deleting the file so the
# policy is not left enforced until the next reboot. Mirror the chroot guard
# used in the after-install script — live AppArmor operations are not
# meaningful inside a chroot.
# https://wiki.debian.org/AppArmor/HowToUse
if apparmor_status --enabled > /dev/null 2>&1; then
if ! { [ -x '/usr/bin/ischroot' ] && /usr/bin/ischroot; } && hash apparmor_parser 2>/dev/null; then
apparmor_parser --remove "$APPARMOR_PROFILE_DEST" || true
fi
fi
rm -f "$APPARMOR_PROFILE_DEST"
fi

View file

@ -0,0 +1,9 @@
abi <abi/4.0>,
include <tunables/global>
profile "${executable}" "/opt/${sanitizedProductName}/${executable}" flags=(unconfined) {
userns,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/${executable}>
}

View file

@ -16,6 +16,7 @@
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage='A newer version of "[ProductName]" is already installed.'/>
<MediaTemplate CompressionLevel="${compressionLevel}" EmbedCab="yes"/>
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER"/>
<Property Id="ApplicationFolderName" Value="${installationDirectoryWixName}"/>
<Property Id="WixAppFolder" Value="WixPerUserFolder"/>
<Property Id="DISABLEADVTSHORTCUTS" Value="1"/>
@ -69,7 +70,11 @@
<Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="1" Order="4">WixAppFolder = "WixPerMachineFolder"</Publish>
<!-- Run 'FindRelatedProducts' again after changing the install scope, because its first run might have ignored an existing installation based on the default scope at the time. https://stackoverflow.com/a/35064434 -->
<Publish Dialog="InstallScopeDlg" Control="Next" Event="DoAction" Value="FindRelatedProducts" Order="5">1</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="6">1</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="6">WixAppFolder = "WixPerUserFolder"</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="7">WixAppFolder = "WixPerMachineFolder"</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="InstallScopeDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="2">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallScopeDlg" Order="2">NOT Installed</Publish>
</UI>

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<!-- https://blogs.msdn.microsoft.com/gremlininthemachine/2006/12/05/msi-wix-and-unicode/ -->
<!-- https://mistake.computer/2020/04/05/msi-exe-wrapper.html -->
<Product Id="${productId}" Name="${productName}" UpgradeCode="${upgradeCode}" Version="${version}" Language="1033" Codepage="65001" Manufacturer="${manufacturer}">
<Package Compressed="yes" InstallerVersion="500"/>
<Condition Message="Windows 7 and above is required"><![CDATA[Installed OR VersionNT >= 601]]></Condition>
<!--
AllowSameVersionUpgrades:
When set to no (the default), installing a product with the same version and upgrade code (but different product code) is allowed and treated by MSI as two products.
When set to yes, WiX sets the msidbUpgradeAttributesVersionMaxInclusive attribute, which tells MSI to treat a product with the same version as a major upgrade.
So, AllowSameVersionUpgrades="yes" allows to build and test MSI with the same version, and previously installed app will be removed.
-->
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage='A newer version of "[ProductName]" is already installed.'/>
<MediaTemplate CompressionLevel="${compressionLevel}" EmbedCab="yes"/>
<Property Id="DISABLEADVTSHORTCUTS" Value="1"/>
{{ if (iconPath) { }}
<Icon Id="${iconId}" SourceFile="${iconPath}"/>
<Property Id="ARPPRODUCTICON" Value="${iconId}"/>
{{ } -}}
<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="1"/>
<!-- Exe path will be embedded directly -->
<Binary Id="WrappedExe" SourceFile="${exeSourcePath}" />
<!-- Custom Action to Execute embedded exe -->
<CustomAction Id="RunInstaller" Return="check" Execute="deferred"
HideTarget="no" Impersonate="${impersonate}" BinaryKey="WrappedExe" ExeCommand="${wrappedInstallerArgs}" />
<!-- This is just a dummy component to allow wrapping the exe installer -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TempFolder">
<Component Id="EmptyComponent" Guid="7145262D-7149-4F1A-9A69-F377E38F04DA" KeyPath="yes">
<CreateFolder />
</Component>
</Directory>
</Directory>
<!-- Setting the feature to level 0 marks it hidden, so it can't be installed.
That prevents getting this MSI registered as an installed product,
because it has no features of its own to install. -->
<Feature Id="EmptyFeature" Level="0">
<ComponentRef Id="EmptyComponent" />
</Feature>
<InstallExecuteSequence>
<Custom Action="RunInstaller" After="ProcessComponents" />
</InstallExecuteSequence>
</Product>
</Wix>

View file

@ -1,6 +1,6 @@
# NSIS
⚠️ **It is developer documentation.** If your are looking for usage guide, see [user documentation](https://electron.build/configuration/nsis).
⚠️ **It is developer documentation.** If your are looking for usage guide, see [user documentation](https://electron.build/nsis).
NSIS stands for Nullsoft Scriptable Install System. electron-builder utilizes a [customized version](https://github.com/electron-userland/electron-builder-binaries) of it and uses `NsisMultiUser` plugin to handle installation for single user or all users on the computer.
@ -24,7 +24,7 @@ For translators, the strings to be displayed are included in [`assistedMessages.
As for other strings in NSIS, head to [electron-userland/electron-builder-binaries](https://github.com/electron-userland/electron-builder-binaries) or the upstream repository on [Sorceforge](https://sourceforge.net/p/nsis/code/HEAD/tree/).
## GUID
See [docs](https://electron.build/configuration/nsis).
See [docs](https://electron.build/nsis).
We use UUID v5 to generate sha-1 name-based UUID.

View file

@ -31,11 +31,9 @@
# sanitize the MUI_PAGE_DIRECTORY result to make sure it has a application name sub-folder
Function instFilesPre
${If} ${FileExists} "$INSTDIR\*"
${StrContains} $0 "${APP_FILENAME}" $INSTDIR
${If} $0 == ""
StrCpy $INSTDIR "$INSTDIR\${APP_FILENAME}"
${endIf}
${StrContains} $0 "${APP_FILENAME}" $INSTDIR
${If} $0 == ""
StrCpy $INSTDIR "$INSTDIR\${APP_FILENAME}"
${endIf}
FunctionEnd
!endif
@ -66,7 +64,12 @@
!endif
!else
!ifndef removeDefaultUninstallWelcomePage
!insertmacro MUI_UNPAGE_WELCOME
!ifmacrodef customUnWelcomePage
!insertmacro customUnWelcomePage
!else
!insertmacro MUI_UNPAGE_WELCOME
!endif
!endif
!ifndef INSTALL_MODE_PER_ALL_USERS
!insertmacro PAGE_INSTALL_MODE
@ -140,7 +143,11 @@
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
!else
!insertmacro setInstallModePerUser
!ifdef INSTALL_MODE_PER_ALL_USERS_DEFAULT
!insertmacro setInstallModePerAllUsers
!else
!insertmacro setInstallModePerUser
!endif
!endif
${endif}
!endif

View file

@ -90,7 +90,7 @@ whoShouldThisApplicationBeInstalledFor:
selectUserMode:
en: Please select whether you wish to make this software available to all users or just yourself
de: Bitte wählen Sie, ob Sie die Anwendung nur für sich oder für alle Benutzer installieren möchten.
ru: Выбери, хочешь ли ты сделать эту программу доступной для всех пользователей или только для себя
ru: Выберите, хотите ли Вы сделать эту программу доступной для всех пользователей, или только для себя
sk: Prosím vyberte či sa ma tento softvér inštalovať len pre Vás alebo pre všetkých uživateľov
cs: Prosím vyberte, zda se má tento software instalovat jen pro Vás, nebo pro všechny uživatele
fr: "Choisis pour qui ce logiciel doit être accessible : pour tous les utilisateurs ou juste pour toi ?"
@ -112,7 +112,7 @@ selectUserMode:
whichInstallationRemove:
en: This software is installed both per-machine (all users) and per-user.\nWhich installation you wish to remove?
de: Die Anwendung wurde für alle Benutzer und pro Benutzer installiert.\nWelche Installation möchten Sie entfernen?
ru: Эта программа установлена для всего компьютера (для всех пользователей) и для отдельного пользователя.\nКакую из установленных программ ты хочешь удалить?
ru: Эта программа установлена для всего компьютера (для всех пользователей) и для отдельного пользователя.\nКакую из установленных программ Вы хотите удалить?
sk: Tento softvér je nainštalovaný pre Vás a súčasne pre všetkých uživateľov.\nKtorú inštaláciu si želáte odstraniť?
cs: Tento software je nainstalovaný pro Vás a současně pro všechny uživatele.\nKterou instalaci si přejete odstranit?
fr: Ce logiciel est installé à la fois par machine (tous les utilisateurs) et par utilisateur.\nQuelle installation veux-tu supprimer ?
@ -134,7 +134,7 @@ whichInstallationRemove:
freshInstallForAll:
en: Fresh install for all users. (will prompt for admin credentials)
de: Neuinstallation für alle Benutzer durchführen. (Administratorrechte benötigt)
ru: Новая установка для всех пользователей. (потребуются права администратора)
ru: Новая установка для всех пользователей. (Потребуются права администратора)
sk: Nová inštalácia pre všetkých uživateľov. (Bude potrebovať prihlásenie administrátora)
cs: Nová instalace pro všechny uživatele. (Bude vyžadovat přihlášení administrátora)
fr: Nouvelle installation pour tous les utilisateurs. (demandera les identifiants administrateur)
@ -221,7 +221,7 @@ forAll:
loginWithAdminAccount:
en: You need to login with an account that is a member of the admin group to continue...
de: Um die Installation fortzusetzen müssen Sie sich mit einem Administrator-Account anmelden...
ru: Чтобы продолжить, тебе нужно войти в учетную запись, которая входит в группу администраторов...
ru: Чтобы продолжить, Вам необходимо войти в учетную запись, которая входит в группу администраторов...
sk: Pre pokračovanie sa musíte zalogovať s účtom ktorý patrí do skupiny adminstrátorov...
cs: Pro pokračování se musíte přihlásit účtem, který patří do skupiny administrátorů...
fr: Tu dois te connecter avec un compte ayant des droits d'administrateur pour continuer...

View file

@ -3,16 +3,47 @@
BrandingText "${PRODUCT_NAME} ${VERSION}"
ShowInstDetails nevershow
SpaceTexts none
!ifdef BUILD_UNINSTALLER
ShowUninstDetails nevershow
!endif
FileBufSize 64
Name "${PRODUCT_NAME}"
# Allows for a product name to display properly if it has an ampersand
# Doesn't affect anything if there is no double ampersand
!searchreplace DoubleAmpersand "${PRODUCT_NAME}" "&" "&&"
Name "${PRODUCT_NAME}" "${DoubleAmpersand}"
!define APP_EXECUTABLE_FILENAME "${PRODUCT_FILENAME}.exe"
!define UNINSTALL_FILENAME "Uninstall ${PRODUCT_FILENAME}.exe"
!macro setSpaceRequired SECTION_ID
!ifdef APP_64_UNPACKED_SIZE
!ifdef APP_32_UNPACKED_SIZE
!ifdef APP_ARM64_UNPACKED_SIZE
${if} ${IsNativeARM64}
SectionSetSize ${SECTION_ID} ${APP_ARM64_UNPACKED_SIZE}
${elseif} ${IsNativeAMD64}
SectionSetSize ${SECTION_ID} ${APP_64_UNPACKED_SIZE}
${else}
SectionSetSize ${SECTION_ID} ${APP_32_UNPACKED_SIZE}
${endif}
!else
${if} ${RunningX64}
SectionSetSize ${SECTION_ID} ${APP_64_UNPACKED_SIZE}
${else}
SectionSetSize ${SECTION_ID} ${APP_32_UNPACKED_SIZE}
${endif}
!endif
!else
SectionSetSize ${SECTION_ID} ${APP_64_UNPACKED_SIZE}
!endif
!else
!ifdef APP_32_UNPACKED_SIZE
SectionSetSize ${SECTION_ID} ${APP_32_UNPACKED_SIZE}
!endif
!endif
!macroend
!macro check64BitAndSetRegView
# https://github.com/electron-userland/electron-builder/issues/2420
${If} ${IsWin2000}
@ -107,7 +138,7 @@ Name "${PRODUCT_NAME}"
LogSet ${SETTING}
!endif
!macroend
!define LogText "!insertmacro LogTextMacroEB"
!macro LogTextMacroEB INPUT_TEXT
!ifdef ENABLE_LOGGING_ELECTRON_BUILDER

View file

@ -63,11 +63,8 @@
;
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
WriteRegNone SHELL_CONTEXT "Software\Classes\.${EXT}\OpenWithProgids" "${FILECLASS}"
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
@ -77,11 +74,8 @@
!macroend
!macro APP_ASSOCIATE_EX EXT FILECLASS DESCRIPTION ICON VERB DEFAULTVERB SHELLNEW COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
WriteRegNone SHELL_CONTEXT "Software\Classes\.${EXT}\OpenWithProgids" "${FILECLASS}"
StrCmp "${SHELLNEW}" "0" +2
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}\ShellNew" "NullFile" ""
@ -103,10 +97,7 @@
!macro APP_UNASSOCIATE EXT FILECLASS
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
DeleteRegValue SHELL_CONTEXT "Software\Classes\.${EXT}\OpenWithProgids" "${FILECLASS}"
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
!macroend
@ -129,4 +120,4 @@
; Using the system.dll plugin to call the SHChangeNotify Win32 API function so we
; can update the shell.
System::Call "shell32::SHChangeNotify(i,i,i,i) (${SHCNE_ASSOCCHANGED}, ${SHCNF_FLUSH}, 0, 0)"
!macroend
!macroend

View file

@ -30,23 +30,78 @@
!macroend
!macro CHECK_APP_RUNNING
!ifmacrodef customCheckAppRunning
!insertmacro customCheckAppRunning
!else
!insertmacro _CHECK_APP_RUNNING
!endif
!macroend
!macro FIND_PROCESS _FILE _ERR
!ifdef INSTALL_MODE_PER_ALL_USERS
${nsProcess::FindProcess} "${_FILE}" ${_ERR}
Var /GLOBAL CmdPath
Var /GLOBAL PowerShellPath
StrCpy $CmdPath "$SYSDIR\cmd.exe"
StrCpy $PowerShellPath "$SYSDIR\WindowsPowerShell\v1.0\powershell.exe"
!ifmacrodef customCheckAppRunning
!insertmacro customCheckAppRunning
!else
# find process owned by current user
nsExec::Exec `cmd /c tasklist /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME eq ${_FILE}" | %SYSTEMROOT%\System32\find.exe "${_FILE}"`
Pop ${_ERR}
!insertmacro IS_POWERSHELL_AVAILABLE
!insertmacro _CHECK_APP_RUNNING
!endif
!macroend
!macro IS_POWERSHELL_AVAILABLE
Var /GLOBAL IsPowerShellAvailable ; 0 = available, 1 = not available
# Try running PowerShell with a simple command to check if it's available
nsExec::Exec `"$PowerShellPath" -C "if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"`
Pop $0 # Return code (0 = success, other = error)
${if} $0 == 0
# PowerShell is available, check if it's not blocked by policies
nsExec::Exec `"$PowerShellPath" -C "if ((Get-ExecutionPolicy -Scope Process) -eq 'Restricted') { exit 1 } else { exit 0 }"`
Pop $0
${endIf}
${if} $0 != 0
StrCpy $0 1
${endIf}
StrCpy $IsPowerShellAvailable $0
!macroend
!macro FIND_PROCESS _FILE _RETURN
${if} $IsPowerShellAvailable == 0
nsExec::Exec `"$PowerShellPath" -C "if ((Get-CimInstance -ClassName Win32_Process | ? {$$_.Path -and $$_.Path.StartsWith('$INSTDIR', 'CurrentCultureIgnoreCase')}).Count -gt 0) { exit 0 } else { exit 1 }"`
Pop ${_RETURN}
${else}
!ifdef INSTALL_MODE_PER_ALL_USERS
# exact match via findstr anchored to the start of each CSV line
nsExec::Exec `"$CmdPath" /C tasklist /FI "IMAGENAME eq ${_FILE}" /FO CSV /NH | "$SYSDIR\findstr.exe" /B /I /C:"\"${_FILE}\""`
Pop ${_RETURN}
!else
# find process owned by current user anchored exact match
nsExec::Exec `"$CmdPath" /C tasklist /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME eq ${_FILE}" /FO CSV /NH | "$SYSDIR\findstr.exe" /B /I /C:"\"${_FILE}\""`
Pop ${_RETURN}
!endif
${endIf}
!macroend
!macro KILL_PROCESS _FILE _FORCE
Push $0
${if} ${_FORCE} == 1
${if} $IsPowerShellAvailable == 0
StrCpy $0 "-Force"
${else}
StrCpy $0 "/F"
${endIf}
${else}
StrCpy $0 ""
${endIf}
${if} $IsPowerShellAvailable == 0
nsExec::Exec `"$PowerShellPath" -C "Get-CimInstance -ClassName Win32_Process | ? {$$_.Path -and $$_.Path.StartsWith('$INSTDIR', 'CurrentCultureIgnoreCase')} | % { Stop-Process -Id $$_.ProcessId $0 }"`
${else}
!ifdef INSTALL_MODE_PER_ALL_USERS
nsExec::Exec `taskkill /IM "${_FILE}" /FI "PID ne $pid"`
!else
nsExec::Exec `"$CmdPath" /C taskkill $0 /IM "${_FILE}" /FI "PID ne $pid" /FI "USERNAME eq %USERNAME%"`
!endif
${endIf}
Pop $0
!macroend
!macro _CHECK_APP_RUNNING
${GetProcessInfo} 0 $pid $1 $2 $3 $4
${if} $3 != "${APP_EXECUTABLE_FILENAME}"
@ -67,14 +122,9 @@
doStopProcess:
DetailPrint `Closing running "${PRODUCT_NAME}"...`
DetailPrint "$(appClosing)"
# https://github.com/electron-userland/electron-builder/issues/2516#issuecomment-372009092
!ifdef INSTALL_MODE_PER_ALL_USERS
nsExec::Exec `taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"`
!else
nsExec::Exec `cmd /c taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid" /fi "USERNAME eq %USERNAME%"`
!endif
!insertmacro KILL_PROCESS "${APP_EXECUTABLE_FILENAME}" 0
# to ensure that files are not "in-use"
Sleep 300
@ -88,13 +138,9 @@
${if} $R0 == 0
# wait to give a chance to exit gracefully
Sleep 1000
!ifdef INSTALL_MODE_PER_ALL_USERS
nsExec::Exec `taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"`
!else
nsExec::Exec `cmd /c taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid" /fi "USERNAME eq %USERNAME%"`
!endif
!insertmacro KILL_PROCESS "${APP_EXECUTABLE_FILENAME}" 1 # 1 = force kill
!insertmacro FIND_PROCESS "${APP_EXECUTABLE_FILENAME}" $R0
${If} $R0 == 0
${if} $R0 == 0
DetailPrint `Waiting for "${PRODUCT_NAME}" to close.`
Sleep 2000
${else}

View file

@ -133,6 +133,26 @@
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "Publisher" "${COMPANY_NAME}"
!endif
!ifdef APP_DESCRIPTION
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "Comments" "${APP_DESCRIPTION}"
!endif
!ifdef UNINSTALL_URL_HELP
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "HelpLink" "${UNINSTALL_URL_HELP}"
!endif
!ifdef UNINSTALL_URL_INFO_ABOUT
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "URLInfoAbout" "${UNINSTALL_URL_INFO_ABOUT}"
!endif
!ifdef UNINSTALL_URL_UPDATE_INFO
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "URLUpdateInfo" "${UNINSTALL_URL_UPDATE_INFO}"
!endif
!ifdef UNINSTALL_URL_README
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "Readme" "${UNINSTALL_URL_README}"
!endif
WriteRegDWORD SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" NoModify 1
WriteRegDWORD SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" NoRepair 1

View file

@ -26,6 +26,9 @@ StrCpy $appExe "$INSTDIR\${APP_EXECUTABLE_FILENAME}"
FindWindow $0 "#32770" "" $hwndparent $0
GetDlgItem $0 $0 1000
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(installing)"
StrCpy $1 $hwndparent
System::Call 'user32::ShutdownBlockReasonCreate(${SYSTYPE_PTR}r1, w "$(installing)")'
${endif}
!insertmacro CHECK_APP_RUNNING
!else
@ -104,4 +107,4 @@ ${endIf}
${andIf} ${Silent}
!insertmacro doStartApp
${endIf}
!endif
!endif

View file

@ -10,6 +10,13 @@ Var oldMenuDirectory
!include "multiUser.nsh"
!include "allowOnlyOneInstallerInstance.nsh"
!ifdef BUILD_UNINSTALLER
!ifmacrodef customUnInstallSection
!define MUI_COMPONENTSPAGE_NODESC
!insertmacro MUI_UNPAGE_COMPONENTS
!endif
!endif
!ifdef INSTALL_MODE_PER_ALL_USERS
!ifdef BUILD_UNINSTALLER
RequestExecutionLevel user
@ -40,6 +47,8 @@ Var oldMenuDirectory
!endif
Function .onInit
Call setInstallSectionSpaceRequired
SetOutPath $INSTDIR
${LogSet} on
@ -82,7 +91,7 @@ FunctionEnd
!include "installUtil.nsh"
!endif
Section "install"
Section "install" INSTALL_SECTION_ID
!ifndef BUILD_UNINSTALLER
# If we're running a silent upgrade of a per-machine installation, elevate so extracting the new app will succeed.
# For a non-silent install, the elevation will be triggered when the install mode is selected in the UI,
@ -114,6 +123,10 @@ Section "install"
!endif
SectionEnd
Function setInstallSectionSpaceRequired
!insertmacro setSpaceRequired ${INSTALL_SECTION_ID}
FunctionEnd
!ifdef BUILD_UNINSTALLER
!include "uninstaller.nsh"
!endif

View file

@ -235,3 +235,6 @@ uninstallFailed:
sv: Det gick inte att avinstallera gamla programfiler. Försök att köra installationsprogrammet igen.
uk: Не вдалось видалити старі файли застосунку. Будь ласка, спробуйте запустити встановлювач знов.
zh_TW: 無法俺安裝舊的應用程式檔案。 請嘗試再次執行安裝程式。
appClosing:
en: "Closing running ${PRODUCT_NAME}..."
cs: "Ukončuji aplikaci ${PRODUCT_NAME}..."

View file

@ -28,20 +28,27 @@ Var installMode
StrCpy $INSTDIR $perUserInstallationFolder
${else}
StrCpy $0 "$LocalAppData\Programs"
System::Store S
# Win7 has a per-user programfiles known folder and this can be a non-default location
Push $1
Push $2
# UserProgramFiles is the per-user install root and can be a non-default location
StrCpy $2 0
System::Call 'SHELL32::SHGetKnownFolderPath(g "${FOLDERID_UserProgramFiles}", i ${KF_FLAG_CREATE}, p 0, *p .r2)i.r1'
${If} $1 == 0
System::Call '*$2(&w${NSIS_MAX_STRLEN} .s)'
StrCpy $0 $1
System::Call 'KERNEL32::lstrcpynW(w .r0, p r2, i ${NSIS_MAX_STRLEN})p'
${endif}
# SHGetKnownFolderPath may return allocated memory even on failure
${If} $2 != 0
System::Call 'OLE32::CoTaskMemFree(p r2)'
${endif}
System::Store L
Pop $2
Pop $1
StrCpy $INSTDIR "$0\${APP_FILENAME}"
${endif}
# allow /D switch to override installation path https://github.com/electron-userland/electron-builder/issues/1551
${StdUtils.GetParameter} $R0 "D" ""
!insertmacro GetDParameter $R0
${If} $R0 != ""
StrCpy $INSTDIR $R0
${endif}
@ -84,10 +91,51 @@ Var installMode
${endif}
# allow /D switch to override installation path https://github.com/electron-userland/electron-builder/issues/1551
${StdUtils.GetParameter} $R0 "D" ""
!insertmacro GetDParameter $R0
${If} $R0 != ""
StrCpy $INSTDIR $R0
${endif}
!macroend
!endif
# Custom function to handle /D parameter with spaces
# The /D parameter is special in NSIS - it must be the last parameter and cannot have quotes
# Use StdUtils.GetParameter to get the full command line, then parse /D= manually
!macro GetDParameter outVar
Push $R8
Push $R9
Push $R7
Push $R6
Push $R5
# Get the complete command line using StdUtils (including /D parameter)
${StdUtils.GetAllParameters} $R8 "0"
# Initialize result
StrCpy $R9 ""
# Search for /D= or /d= using a simple loop
StrLen $R7 $R8
IntOp $R7 $R7 - 2 # Don't check last 2 characters
StrCpy $R6 0
${Do}
StrCpy $R5 $R8 3 $R6 # Get 3 characters starting at position $R6
${If} $R5 == "/D="
${OrIf} $R5 == "/d="
# Found /D= or /d=, extract everything after it
IntOp $R6 $R6 + 3
StrCpy $R9 $R8 "" $R6
${Break}
${EndIf}
IntOp $R6 $R6 + 1
${LoopUntil} $R6 > $R7
StrCpy ${outVar} $R9
Pop $R5
Pop $R6
Pop $R7
Pop $R9
Pop $R8
!macroend

View file

@ -8,6 +8,13 @@ Function un.onInit
!insertmacro check64BitAndSetRegView
# Parse command line for /S flag and set silent mode
${GetParameters} $R0
${GetOptions} $R0 "/S" $R1
${IfNot} ${Errors}
SetSilent silent
${EndIf}
${If} ${Silent}
call un.checkAppRunning
${else}
@ -115,7 +122,7 @@ Function un.restoreFiles
Goto continue
isNotDir:
Rename $PLUGINSDIR\old-install$R0\$R2" "$INSTDIR$R0\$R2"
Rename "$PLUGINSDIR\old-install$R0\$R2" "$INSTDIR$R0\$R2"
continue:
FindNext $R1 $R2
@ -131,7 +138,12 @@ Function un.restoreFiles
Exch $R0
FunctionEnd
Section "un.install"
!ifndef UNINSTALL_SECTION_NAME
!define UNINSTALL_SECTION_NAME "Uninstall"
!endif
Section "un.${UNINSTALL_SECTION_NAME}"
SectionIn RO
# for assisted installer we check it here to show progress
!ifndef ONE_CLICK
${IfNot} ${Silent}
@ -141,6 +153,10 @@ Section "un.install"
!insertmacro setLinkVars
!ifmacrodef customUnInstall
!insertmacro customUnInstall
!endif
# delete the installed files
!ifmacrodef customRemoveFiles
!insertmacro customRemoveFiles
@ -165,6 +181,8 @@ Section "un.install"
${endif}
# Move out of $INSTDIR so it can be removed
SetOutPath $TEMP
# Remove all files (or remaining shallow directories from the block above)
RMDir /r $INSTDIR
!endif
@ -235,11 +253,11 @@ Section "un.install"
!endif
DeleteRegKey SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}"
!ifmacrodef customUnInstall
!insertmacro customUnInstall
!endif
!ifdef ONE_CLICK
!insertmacro quitSuccess
!endif
SectionEnd
!ifmacrodef customUnInstallSection
!insertmacro customUnInstallSection
!endif

View file

@ -0,0 +1,444 @@
#!/bin/bash -e
###############################################
# Launcher common exports for any desktop app #
###############################################
function prepend_dir() {
local var="$1"
local dir="$2"
if [ -d "$dir" ]; then
eval "export $var=\"\$dir\${$var:+:\$$var}\""
fi
}
function append_dir() {
local var="$1"
local dir="$2"
if [ -d "$dir" ]; then
eval "export $var=\"\${$var:+\$$var:}\$dir\""
fi
}
function can_open_file() {
head -c0 "$1" &> /dev/null
}
function update_xdg_dirs_values() {
local save_initial_values=false
local XDG_DIRS="DOCUMENTS DESKTOP DOWNLOAD MUSIC PICTURES VIDEOS PUBLICSHARE TEMPLATES"
unset XDG_SPECIAL_DIRS_PATHS
if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" ]; then
# shellcheck source=/dev/null
source "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs"
fi
if [ -z ${XDG_SPECIAL_DIRS+x} ]; then
save_initial_values=true
fi
for d in $XDG_DIRS; do
var="XDG_${d}_DIR"
value="${!var}"
if [ "$save_initial_values" = true ]; then
XDG_SPECIAL_DIRS+=("$var")
if [ -n "$value" ]; then
XDG_SPECIAL_DIRS_INITIAL_PATHS+=("$value")
fi
fi
if [ -n "$value" ]; then
XDG_SPECIAL_DIRS_PATHS+=("$value")
fi
done
}
function is_subpath() {
dir="$(realpath "$1")"
parent="$(realpath "$2")"
[ "${dir##$parent/}" != "$dir" ] && return 0 || return 1
}
if [ -n "$SNAP_DESKTOP_RUNTIME" ]; then
# add general paths not added by snapcraft due to runtime snap
append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/lib/$SNAP_DESKTOP_ARCH_TRIPLET"
append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET"
append_dir PATH "$SNAP_DESKTOP_RUNTIME/usr/bin"
fi
# XKB config
export XKB_CONFIG_ROOT="$SNAP_DESKTOP_RUNTIME/usr/share/X11/xkb"
# Give XOpenIM a chance to locate locale data.
# This is required for text input to work in SDL2 games.
export XLOCALEDIR="$SNAP_DESKTOP_RUNTIME/usr/share/X11/locale"
# Set XCursors path
export XCURSOR_PATH="$SNAP_DESKTOP_RUNTIME/usr/share/icons"
prepend_dir XCURSOR_PATH "$SNAP/data-dir/icons"
# Mesa Libs for OpenGL support
append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/mesa"
append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/mesa-egl"
# Tell libGL where to find the drivers
export LIBGL_DRIVERS_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/dri"
append_dir LD_LIBRARY_PATH "$LIBGL_DRIVERS_PATH"
export LIBVA_DRIVERS_PATH=$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/dri
# Workaround in snapd for proprietary nVidia drivers mounts the drivers in
# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH
# Without that OpenGL using apps do not work with the nVidia drivers.
# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192
append_dir LD_LIBRARY_PATH /var/lib/snapd/lib/gl
# Unity7 export (workaround for https://launchpad.net/bugs/1638405)
append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libunity"
# Pulseaudio export
append_dir LD_LIBRARY_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/pulseaudio"
# EGL vendor files on glvnd enabled systems
[ -d /var/lib/snapd/lib/glvnd/egl_vendor.d ] && \
append_dir __EGL_VENDOR_LIBRARY_DIRS /var/lib/snapd/lib/glvnd/egl_vendor.d
# Tell GStreamer where to find its plugins
export GST_PLUGIN_PATH="$SNAP/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gstreamer-1.0"
export GST_PLUGIN_SYSTEM_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gstreamer-1.0"
# gst plugin scanner doesn't install in the correct path: https://github.com/ubuntu/snapcraft-desktop-helpers/issues/43
export GST_PLUGIN_SCANNER="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner"
# XDG Config
[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir XDG_CONFIG_DIRS "$SNAP_DESKTOP_RUNTIME/etc/xdg"
prepend_dir XDG_CONFIG_DIRS "$SNAP/etc/xdg"
# Define snaps' own data dir
[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir XDG_DATA_DIRS "$SNAP_DESKTOP_RUNTIME/usr/share"
prepend_dir XDG_DATA_DIRS "$SNAP/usr/share"
prepend_dir XDG_DATA_DIRS "$SNAP/share"
prepend_dir XDG_DATA_DIRS "$SNAP/data-dir"
prepend_dir XDG_DATA_DIRS "$SNAP_USER_DATA"
# Set XDG_DATA_HOME to local path
export XDG_DATA_HOME="$SNAP_USER_DATA/.local/share"
mkdir -p "$XDG_DATA_HOME"
# Workaround for GLib < 2.53.2 not searching for schemas in $XDG_DATA_HOME:
# https://bugzilla.gnome.org/show_bug.cgi?id=741335
prepend_dir XDG_DATA_DIRS "$XDG_DATA_HOME"
# Set cache folder to local path
export XDG_CACHE_HOME="$SNAP_USER_COMMON/.cache"
if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$XDG_CACHE_HOME" ]]; then
# the .cache directory used to be stored under $SNAP_USER_DATA, migrate it
mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/"
fi
mkdir -p "$XDG_CACHE_HOME"
# Set config folder to local path
export XDG_CONFIG_HOME="$SNAP_USER_DATA/.config"
mkdir -p "$XDG_CONFIG_HOME"
# Create $XDG_RUNTIME_DIR if not exists (to be removed when LP: #1656340 is fixed)
if [ -n "$XDG_RUNTIME_DIR" ]; then
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"
fi
# Ensure the app finds locale definitions (requires locales-all to be installed)
append_dir LOCPATH "$SNAP_DESKTOP_RUNTIME/usr/lib/locale"
# If any, keep track of where XDG dirs were so we can potentially migrate the content later
update_xdg_dirs_values
# Setup user-dirs.* or run xdg-user-dirs-update if needed
needs_xdg_update=false
needs_xdg_reload=false
needs_xdg_links=false
if [ "$HOME" != "$SNAP_USER_DATA" ] && ! is_subpath "$XDG_CONFIG_HOME" "$HOME"; then
for f in user-dirs.dirs user-dirs.locale; do
if [ -f "$HOME/.config/$f" ]; then
mv "$HOME/.config/$f" "$XDG_CONFIG_HOME"
needs_xdg_reload=true
fi
done
fi
if can_open_file "$REALHOME/.config/user-dirs.dirs" && can_open_file "$REALHOME/.config/user-dirs.locale"; then
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ] || [ $needs_xdg_reload = true ]; then
sed "/^#/!s#\$HOME#${REALHOME}#g" "$REALHOME/.config/user-dirs.dirs" > "$XDG_CONFIG_HOME/user-dirs.dirs"
cp -a "$REALHOME/.config/user-dirs.locale" "$XDG_CONFIG_HOME"
for f in user-dirs.dirs user-dirs.locale; do
md5sum < "$REALHOME/.config/$f" > "$XDG_CONFIG_HOME/$f.md5sum"
done
needs_xdg_reload=true
fi
else
needs_xdg_update=true
needs_xdg_links=true
fi
if [ $needs_xdg_reload = true ]; then
update_xdg_dirs_values
needs_xdg_reload=false
fi
# Check if we can actually read the contents of each xdg dir
for ((i = 0; i < ${#XDG_SPECIAL_DIRS_PATHS[@]}; i++)); do
if ! can_open_file "${XDG_SPECIAL_DIRS_PATHS[$i]}"; then
needs_xdg_update=true
needs_xdg_links=true
break
fi
done
# If needs XDG update and xdg-user-dirs-update exists in $PATH, run it
if [ $needs_xdg_update = true ] && command -v xdg-user-dirs-update >/dev/null; then
xdg-user-dirs-update
update_xdg_dirs_values
fi
# Create links for user-dirs.dirs
if [ $needs_xdg_links = true ]; then
for ((i = 0; i < ${#XDG_SPECIAL_DIRS_PATHS[@]}; i++)); do
b="$(realpath "${XDG_SPECIAL_DIRS_PATHS[$i]}" --relative-to="$HOME")"
if [ -e "$REALHOME/$b" ]; then
if [ -d "$HOME/$b" ]; then
rmdir "$HOME/$b" 2> /dev/null
fi
if [ ! -e "$HOME/$b" ]; then
ln -s "$REALHOME/$b" "$HOME/$b"
fi
fi
done
else
# If we aren't creating new links, check if we have content saved in old locations and move it
for ((i = 0; i < ${#XDG_SPECIAL_DIRS[@]}; i++)); do
old="${XDG_SPECIAL_DIRS_INITIAL_PATHS[$i]}"
new="${XDG_SPECIAL_DIRS_PATHS[$i]}"
if [ -L "$old" ] && [ -d "$new" ] && [ "$(readlink "$old")" != "$new" ] &&
(is_subpath "$old" "$SNAP_USER_DATA" || is_subpath "$old" "$SNAP_USER_COMMON"); then
mv -vn "$old"/* "$new"/ 2>/dev/null
elif [ -d "$old" ] && [ -d "$new" ] && [ "$old" != "$new" ] &&
(is_subpath "$old" "$SNAP_USER_DATA" || is_subpath "$old" "$SNAP_USER_COMMON"); then
mv -vn "$old"/* "$new"/ 2>/dev/null
fi
done
fi
# If detect wayland server socket, then set environment so applications prefer
# wayland, and setup compat symlink (until we use user mounts. Remember,
# XDG_RUNTIME_DIR is /run/user/<uid>/snap.$SNAP so look in the parent directory
# for the socket. For details:
# https://forum.snapcraft.io/t/wayland-dconf-and-xdg-runtime-dir/186/10
# Applications that don't support wayland natively may define DISABLE_WAYLAND
# (to any non-empty value) to skip that logic entirely.
SNAP_DESKTOP_WAYLAND_AVAILABLE=false
if [[ -n "$XDG_RUNTIME_DIR" && -z "$DISABLE_WAYLAND" ]]; then
wdisplay="wayland-0"
if [ -n "$WAYLAND_DISPLAY" ]; then
# Reject values containing '/' to prevent path traversal in the symlink paths below.
# A legitimate WAYLAND_DISPLAY is always a plain socket name (e.g. "wayland-0").
if [[ "$WAYLAND_DISPLAY" != */* ]]; then
wdisplay="$WAYLAND_DISPLAY"
fi
fi
wayland_sockpath="$XDG_RUNTIME_DIR/../$wdisplay"
wayland_snappath="$XDG_RUNTIME_DIR/$wdisplay"
if [ -S "$wayland_sockpath" ]; then
# if running under wayland, use it
#export WAYLAND_DEBUG=1
SNAP_DESKTOP_WAYLAND_AVAILABLE=true
# create the compat symlink for now
if [ ! -e "$wayland_snappath" ]; then
ln -s "$wayland_sockpath" "$wayland_snappath"
fi
fi
fi
# Make PulseAudio socket available inside the snap-specific $XDG_RUNTIME_DIR
if [ -n "$XDG_RUNTIME_DIR" ]; then
pulsenative="pulse/native"
pulseaudio_sockpath="$XDG_RUNTIME_DIR/../$pulsenative"
if [ -S "$pulseaudio_sockpath" ]; then
export PULSE_SERVER="unix:${pulseaudio_sockpath}"
fi
fi
# GI repository
[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir GI_TYPELIB_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/girepository-1.0"
[ -n "$SNAP_DESKTOP_RUNTIME" ] && prepend_dir GI_TYPELIB_PATH "$SNAP_DESKTOP_RUNTIME/usr/lib/girepository-1.0"
prepend_dir GI_TYPELIB_PATH "$SNAP/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/girepository-1.0"
prepend_dir GI_TYPELIB_PATH "$SNAP/usr/lib/girepository-1.0"
prepend_dir GI_TYPELIB_PATH "$SNAP/usr/lib/gjs/girepository-1.0"
# Keep an array of data dirs, for looping through them
IFS=':' read -r -a data_dirs_array <<< "$XDG_DATA_DIRS"
# Font Config and themes
export FONTCONFIG_PATH="$SNAP_DESKTOP_RUNTIME/etc/fonts"
export FONTCONFIG_FILE="$SNAP_DESKTOP_RUNTIME/etc/fonts/fonts.conf"
function make_user_fontconfig {
echo "<fontconfig>"
if [ -d "$REALHOME/.local/share/fonts" ]; then
echo " <dir>$REALHOME/.local/share/fonts</dir>"
fi
if [ -d "$REALHOME/.fonts" ]; then
echo " <dir>$REALHOME/.fonts</dir>"
fi
for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do
if [ -d "${data_dirs_array[$i]}/fonts" ]; then
echo " <dir>${data_dirs_array[$i]}/fonts</dir>"
fi
done
echo ' <include ignore_missing="yes">conf.d</include>'
# We need to include this default cachedir first so that caching
# works: without it, fontconfig will try to write to the real user home
# cachedir and be blocked by AppArmor.
echo ' <cachedir prefix="xdg">fontconfig</cachedir>'
if [ -d "$REALHOME/.cache/fontconfig" ]; then
echo " <cachedir>$REALHOME/.cache/fontconfig</cachedir>"
fi
echo "</fontconfig>"
}
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
rm -rf "$XDG_DATA_HOME"/{fontconfig,fonts,fonts-*,themes,.themes}
# This fontconfig fragment is installed in a location that is
# included by the system fontconfig configuration: namely the
# etc/fonts/conf.d/50-user.conf file.
mkdir -p "$XDG_CONFIG_HOME/fontconfig"
make_user_fontconfig > "$XDG_CONFIG_HOME/fontconfig/fonts.conf"
# the themes symlink are needed for GTK 3.18 when the prefix isn't changed
# GTK 3.20 looks into XDG_DATA_DIR which has connected themes.
ln -sf "$SNAP/data-dir/themes" "$XDG_DATA_HOME"
ln -sfn "$SNAP/data-dir/themes" "$SNAP_USER_DATA/.themes"
fi
# Build mime.cache
# needed for gtk and qt icon
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
rm -rf "$XDG_DATA_HOME/mime"
if [ ! -f "$SNAP_DESKTOP_RUNTIME/usr/share/mime/mime.cache" ]; then
if command -v update-mime-database >/dev/null; then
cp --preserve=timestamps -dR "$SNAP_DESKTOP_RUNTIME/usr/share/mime" "$XDG_DATA_HOME"
update-mime-database "$XDG_DATA_HOME/mime"
fi
fi
fi
# Gio modules and cache (including gsettings module)
export GIO_MODULE_DIR="$XDG_CACHE_HOME/gio-modules"
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
if [ -f "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/glib-2.0/gio-querymodules" ]; then
rm -rf "$GIO_MODULE_DIR"
mkdir -p "$GIO_MODULE_DIR"
ln -sf "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gio/modules/"*.so "$GIO_MODULE_DIR"
ln -sf "$SNAP/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gio/modules/"*.so "$GIO_MODULE_DIR"
"$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/glib-2.0/gio-querymodules" "$GIO_MODULE_DIR"
fi
fi
# Setup compiled gsettings schema
GS_SCHEMA_DIR="$XDG_DATA_HOME/glib-2.0/schemas"
function compile_schemas {
if [ -f "$1" ]; then
rm -rf "$GS_SCHEMA_DIR"
mkdir -p "$GS_SCHEMA_DIR"
for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do
schema_dir="${data_dirs_array[$i]}/glib-2.0/schemas"
if [ -f "$schema_dir/gschemas.compiled" ]; then
# This directory already has compiled schemas
continue
fi
if [ -n "$(ls -A "$schema_dir"/*.xml 2>/dev/null)" ]; then
ln -s "$schema_dir"/*.xml "$GS_SCHEMA_DIR"
fi
if [ -n "$(ls -A "$schema_dir"/*.override 2>/dev/null)" ]; then
ln -s "$schema_dir"/*.override "$GS_SCHEMA_DIR"
fi
done
# Only compile schemas if we copied anything
if [ -n "$(ls -A "$GS_SCHEMA_DIR"/*.xml "$GS_SCHEMA_DIR"/*.override 2>/dev/null)" ]; then
"$1" "$GS_SCHEMA_DIR"
fi
fi
}
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
compile_schemas "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/glib-2.0/glib-compile-schemas"
fi
# Enable gsettings user changes
# symlink the dconf file if home plug is connected for read
DCONF_DEST_USER_DIR="$SNAP_USER_DATA/.config/dconf"
if [ ! -f "$DCONF_DEST_USER_DIR/user" ]; then
if [ -f "$REALHOME/.config/dconf/user" ]; then
mkdir -p "$DCONF_DEST_USER_DIR"
ln -s "$REALHOME/.config/dconf/user" "$DCONF_DEST_USER_DIR"
fi
fi
# Testability support
append_dir LD_LIBRARY_PATH "$SNAP/testability"
append_dir LD_LIBRARY_PATH "$SNAP/testability/$SNAP_DESKTOP_ARCH_TRIPLET"
append_dir LD_LIBRARY_PATH "$SNAP/testability/$SNAP_DESKTOP_ARCH_TRIPLET/mesa"
# Gdk-pixbuf loaders
export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache
export GDK_PIXBUF_MODULEDIR=$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gdk-pixbuf-2.0/2.10.0/loaders
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
rm -f "$GDK_PIXBUF_MODULE_FILE"
if [ -f "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" ]; then
"$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" > "$GDK_PIXBUF_MODULE_FILE"
fi
fi
# Icon themes cache
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
rm -rf "$XDG_DATA_HOME/icons"
mkdir -p "$XDG_DATA_HOME/icons"
for ((i = 0; i < ${#data_dirs_array[@]}; i++)); do
for theme in "${data_dirs_array[$i]}/icons/"*; do
if [ -f "$theme/index.theme" ] && [ ! -f "$theme/icon-theme.cache" ]; then
theme_dir="$XDG_DATA_HOME/icons/$(basename "$theme")"
if [ ! -d "$theme_dir" ]; then
mkdir -p "$theme_dir"
ln -s "$theme"/* "$theme_dir"
if [ -f "$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-caches" ]; then
"$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-caches" "$theme_dir"
elif [ -f "$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-cache.gtk2" ]; then
"$SNAP_DESKTOP_RUNTIME/usr/sbin/update-icon-cache.gtk2" "$theme_dir"
fi
fi
fi
done
done
fi
# GTK theme and behavior modifier
# Those can impact the theme engine used by Qt as well
gtk_configs=(gtk-3.0/settings.ini gtk-3.0/bookmarks gtk-2.0/gtkfilechooser.ini)
for f in "${gtk_configs[@]}"; do
dest="$XDG_CONFIG_HOME/$f"
if [ ! -L "$dest" ]; then
mkdir -p "$(dirname "$dest")"
ln -s "$REALHOME/.config/$f" "$dest"
fi
done
# create symbolic link to ibus socket path for ibus to look up its socket files
# (see comments #3 and #6 on https://launchpad.net/bugs/1580463)
IBUS_CONFIG_PATH="$XDG_CONFIG_HOME/ibus"
mkdir -p "$IBUS_CONFIG_PATH"
[ -d "$IBUS_CONFIG_PATH/bus" ] && rm -rf "$IBUS_CONFIG_PATH/bus"
ln -sfn "$REALHOME/.config/ibus/bus" "$IBUS_CONFIG_PATH"
export SNAP_DESKTOP_WAYLAND_AVAILABLE
exec "$@"

View file

@ -0,0 +1,31 @@
#!/bin/bash -e
##############################
# GTK launcher specific part #
##############################
if [ "$SNAP_DESKTOP_WAYLAND_AVAILABLE" = "true" ]; then
export GDK_BACKEND="wayland"
export CLUTTER_BACKEND="wayland"
# Does not hurt to specify this as well, just in case
export QT_QPA_PLATFORM=wayland-egl
fi
export GTK_PATH="$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gtk-3.0"
# ibus and fcitx integration
GTK_IM_MODULE_DIR=$XDG_CACHE_HOME/immodules
export GTK_IM_MODULE_FILE=$GTK_IM_MODULE_DIR/immodules.cache
if [ "$SNAP_DESKTOP_COMPONENTS_NEED_UPDATE" = "true" ]; then
rm -rf "$GTK_IM_MODULE_DIR"
mkdir -p "$GTK_IM_MODULE_DIR"
if [ -x "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk-3-0/gtk-query-immodules-3.0" ]; then
ln -sf "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gtk-3.0/3.0.0/immodules"/*.so "$GTK_IM_MODULE_DIR"
"$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk-3-0/gtk-query-immodules-3.0" > "$GTK_IM_MODULE_FILE"
elif [ -x "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk2.0-0/gtk-query-immodules-2.0" ]; then
ln -sf "$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/gtk-2.0/2.10.0/immodules"/*.so "$GTK_IM_MODULE_DIR"
"$SNAP_DESKTOP_RUNTIME/usr/lib/$SNAP_DESKTOP_ARCH_TRIPLET/libgtk2.0-0/gtk-query-immodules-2.0" > "$GTK_IM_MODULE_FILE"
fi
fi
exec "$@"

View file

@ -0,0 +1,52 @@
#!/bin/bash -e
#################
# Launcher init #
#################
SNAP_DESKTOP_COMPONENTS_NEED_UPDATE="true"
# shellcheck source=/dev/null
. "$SNAP_USER_DATA/.last_revision" 2>/dev/null || true
if [ "$SNAP_DESKTOP_LAST_REVISION" = "$SNAP_REVISION" ]; then
SNAP_DESKTOP_COMPONENTS_NEED_UPDATE="false"
else
echo "SNAP_DESKTOP_LAST_REVISION=$SNAP_REVISION" > "$SNAP_USER_DATA/.last_revision"
fi
# Set $REALHOME to the users real home directory
REALHOME="$(getent passwd $UID | cut -d ':' -f 6)"
# If the user has modified their user-dirs settings, force an update
if [[ -f "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum" && -f "$XDG_CONFIG_HOME/user-dirs.locale.md5sum" ]]; then
if [[ "$(md5sum < "$REALHOME/.config/user-dirs.dirs")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.dirs.md5sum")" ||
"$(md5sum < "$REALHOME/.config/user-dirs.locale")" != "$(cat "$XDG_CONFIG_HOME/user-dirs.locale.md5sum")" ]]; then
SNAP_DESKTOP_COMPONENTS_NEED_UPDATE="true"
fi
fi
if [ "$SNAP_ARCH" == "amd64" ]; then
ARCH="x86_64-linux-gnu"
elif [ "$SNAP_ARCH" == "armhf" ]; then
ARCH="arm-linux-gnueabihf"
elif [ "$SNAP_ARCH" == "arm64" ]; then
ARCH="aarch64-linux-gnu"
elif [ "$SNAP_ARCH" == "ppc64el" ]; then
ARCH="powerpc64le-linux-gnu"
else
ARCH="$SNAP_ARCH-linux-gnu"
fi
SNAP_DESKTOP_ARCH_TRIPLET="$ARCH"
if [ -f "$SNAP/lib/bindtextdomain.so" ]; then
# Use :+ to avoid a leading ':' when LD_PRELOAD is empty.
# A bare leading ':' makes the dynamic linker search CWD before snap paths.
export LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$SNAP/lib/bindtextdomain.so"
fi
export REALHOME
export SNAP_DESKTOP_COMPONENTS_NEED_UPDATE
export SNAP_DESKTOP_ARCH_TRIPLET
exec "$@"

View file

@ -1,4 +1,4 @@
base: core18
base: core20
grade: stable
confinement: strict
parts: