From 7f890122e6ad1d7e21fe1e20a4d5d197691024e3 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 25 Apr 2020 09:45:46 +0400 Subject: [PATCH] Add methods to detect appimage, static binary and forced gtk dialog --- .../platform/linux/specific_linux.cpp | 142 +++++++++++++----- .../platform/linux/specific_linux.h | 4 + 2 files changed, 108 insertions(+), 38 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index c12e5a0780..20ba053347 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -194,30 +194,31 @@ bool GenerateDesktopFile( QFile target(targetFile); if (target.open(QIODevice::WriteOnly)) { -#ifdef DESKTOP_APP_USE_PACKAGED - fileText = fileText.replace( - QRegularExpression( - qsl("^Exec=(.*) -- %u$"), - QRegularExpression::MultilineOption), - qsl("Exec=\\1") - + (args.isEmpty() ? QString() : ' ' + args)); -#else // DESKTOP_APP_USE_PACKAGED - fileText = fileText.replace( - QRegularExpression( - qsl("^TryExec=.*$"), - QRegularExpression::MultilineOption), - qsl("TryExec=") - + QFile::encodeName(cExeDir() + cExeName()) - .replace('\\', qsl("\\\\"))); - fileText = fileText.replace( - QRegularExpression( - qsl("^Exec=.*$"), - QRegularExpression::MultilineOption), - qsl("Exec=") - + EscapeShell(QFile::encodeName(cExeDir() + cExeName())) - .replace('\\', qsl("\\\\")) - + (args.isEmpty() ? QString() : ' ' + args)); -#endif // !DESKTOP_APP_USE_PACKAGED + if (IsStaticBinary() || InAppImage()) { + fileText = fileText.replace( + QRegularExpression( + qsl("^TryExec=.*$"), + QRegularExpression::MultilineOption), + qsl("TryExec=") + + QFile::encodeName(cExeDir() + cExeName()) + .replace('\\', qsl("\\\\"))); + fileText = fileText.replace( + QRegularExpression( + qsl("^Exec=.*$"), + QRegularExpression::MultilineOption), + qsl("Exec=") + + EscapeShell(QFile::encodeName(cExeDir() + cExeName())) + .replace('\\', qsl("\\\\")) + + (args.isEmpty() ? QString() : ' ' + args)); + } else { + fileText = fileText.replace( + QRegularExpression( + qsl("^Exec=(.*) -- %u$"), + QRegularExpression::MultilineOption), + qsl("Exec=\\1") + + (args.isEmpty() ? QString() : ' ' + args)); + } + target.write(fileText.toUtf8()); target.close(); @@ -249,6 +250,27 @@ bool InSnap() { return Snap; } +bool InAppImage() { + static const auto AppImage = qEnvironmentVariableIsSet("APPIMAGE"); + return AppImage; +} + +bool IsStaticBinary() { +#ifdef DESKTOP_APP_USE_PACKAGED + return false; +#else // DESKTOP_APP_USE_PACKAGED + return true; +#endif // !DESKTOP_APP_USE_PACKAGED +} + +bool IsGtkFileDialogForced() { +#ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG + return true; +#else // TDESKTOP_FORCE_GTK_FILE_DIALOG + return false; +#endif // !TDESKTOP_FORCE_GTK_FILE_DIALOG +} + bool IsXDGDesktopPortalPresent() { #ifdef TDESKTOP_DISABLE_DBUS_INTEGRATION static const auto XDGDesktopPortalPresent = false; @@ -266,7 +288,11 @@ bool UseXDGDesktopPortal() { const auto envVar = qEnvironmentVariableIsSet("TDESKTOP_USE_PORTAL"); const auto portalPresent = IsXDGDesktopPortalPresent(); - return (DesktopEnvironment::IsKDE() || envVar) && portalPresent; + return ( + DesktopEnvironment::IsKDE() + || InSnap() + || envVar + ) && portalPresent; }(); return UsePortal; @@ -288,7 +314,7 @@ QString ProcessNameByPID(const QString &pid) { return QString(); } -QString CurrentExecutablePath(int argc, char *argv[]) { +QString RealExecutablePath(int argc, char *argv[]) { const auto processName = ProcessNameByPID(qsl("self")); // Fallback to the first command line argument. @@ -299,6 +325,25 @@ QString CurrentExecutablePath(int argc, char *argv[]) { : QString(); } +QString CurrentExecutablePath(int argc, char *argv[]) { + if (InAppImage()) { + const auto appimagePath = QString::fromUtf8(qgetenv("APPIMAGE")); + const auto appimagePathList = appimagePath.split('/'); + + if (qEnvironmentVariableIsSet("ARGV0") + && appimagePathList.size() >= 5 + && appimagePathList[1] == qstr("run") + && appimagePathList[2] == qstr("user") + && appimagePathList[4] == qstr("appimagelauncherfs")) { + return QString::fromUtf8(qgetenv("ARGV0")); + } + + return appimagePath; + } + + return RealExecutablePath(argc, argv); +} + QString AppRuntimeDirectory() { static const auto RuntimeDirectory = [&] { auto runtimeDir = QStandardPaths::writableLocation( @@ -356,6 +401,20 @@ QString GetLauncherBasename() { .arg(cExeName()); } + if (InAppImage()) { + const auto appimagePath = qsl("file://%1%2") + .arg(cExeDir()) + .arg(cExeName()) + .toUtf8(); + + char md5Hash[33] = { 0 }; + hashMd5Hex(appimagePath.constData(), appimagePath.size(), md5Hash); + + return qsl("appimagekit_%1-%2") + .arg(md5Hash) + .arg(AppName.utf16().replace(' ', '_')); + } + const auto possibleBasenames = std::vector{ qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME)), qsl("Telegram") @@ -564,6 +623,10 @@ namespace Platform { void start() { LOG(("Launcher filename: %1").arg(GetLauncherFilename())); + if (InAppImage()) { + qputenv("LIBGL_ALWAYS_INDIRECT", "1"); + } + #ifdef TDESKTOP_USE_FONTCONFIG_FALLBACK FallbackFontConfig(); #endif // TDESKTOP_USE_FONTCONFIG_FALLBACK @@ -571,21 +634,24 @@ void start() { qputenv("PULSE_PROP_application.name", AppName.utf8()); qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1()); -#ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG - LOG(("Checking for XDG Desktop Portal...")); - // this can give us a chance to use a proper file dialog for current session - if (IsXDGDesktopPortalPresent()) { - LOG(("XDG Desktop Portal is present!")); - if (UseXDGDesktopPortal()) { - LOG(("Usage of XDG Desktop Portal is enabled.")); - qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal"); + if(IsStaticBinary() + || InAppImage() + || InSnap() + || IsGtkFileDialogForced()) { + LOG(("Checking for XDG Desktop Portal...")); + // this can give us a chance to use a proper file dialog for current session + if (IsXDGDesktopPortalPresent()) { + LOG(("XDG Desktop Portal is present!")); + if (UseXDGDesktopPortal()) { + LOG(("Usage of XDG Desktop Portal is enabled.")); + qputenv("QT_QPA_PLATFORMTHEME", "xdgdesktopportal"); + } else { + LOG(("Usage of XDG Desktop Portal is disabled.")); + } } else { - LOG(("Usage of XDG Desktop Portal is disabled.")); + LOG(("XDG Desktop Portal is not present :(")); } - } else { - LOG(("XDG Desktop Portal is not present :(")); } -#endif // TDESKTOP_FORCE_GTK_FILE_DIALOG } void finish() { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index 28e3ef386c..f3a79555ea 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -22,11 +22,15 @@ inline void SetWatchingMediaKeys(bool watching) { bool InSandbox(); bool InSnap(); +bool InAppImage(); +bool IsStaticBinary(); +bool IsGtkFileDialogForced(); bool IsXDGDesktopPortalPresent(); bool UseXDGDesktopPortal(); QString ProcessNameByPID(const QString &pid); +QString RealExecutablePath(int argc, char *argv[]); QString CurrentExecutablePath(int argc, char *argv[]); QString AppRuntimeDirectory();