diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 520caaf68..ad5ccedc5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -25,7 +25,12 @@ jobs: submodules: recursive - name: First set up. - run: curl -sSL https://install.python-poetry.org | python3 - + run: | + sudo apt update + curl -sSL https://install.python-poetry.org | python3 - + + - name: Free up some disk space. + uses: jlumbroso/free-disk-space@76866dbe54312617f00798d1762df7f43def6e5c - name: Docker image build. run: | diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml index 18ad071b8..4191aced9 100644 --- a/.github/workflows/snap.yml +++ b/.github/workflows/snap.yml @@ -60,6 +60,9 @@ jobs: sudo snap run lxd init --auto sudo snap run lxd waitready + - name: Free up some disk space. + uses: jlumbroso/free-disk-space@76866dbe54312617f00798d1762df7f43def6e5c + - name: Telegram Desktop snap build. run: sg lxd -c 'snap run snapcraft -v' diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 070bfd109..e343836e9 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1774,5 +1774,6 @@ if (LINUX AND DESKTOP_APP_USE_PACKAGED) install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "telegram.png") install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "telegram.png") install(FILES "../lib/xdg/org.ayugram.desktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") + install(FILES "../lib/xdg/org.telegram.desktop.service" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/org.ayugram.desktop.metainfo.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo") endif() diff --git a/Telegram/Resources/uwp/AppX/AppxManifest.xml b/Telegram/Resources/uwp/AppX/AppxManifest.xml index a46c1f439..475e3ee7e 100644 --- a/Telegram/Resources/uwp/AppX/AppxManifest.xml +++ b/Telegram/Resources/uwp/AppX/AppxManifest.xml @@ -10,7 +10,7 @@ + Version="4.8.4.0" /> Telegram Desktop Telegram Messenger LLP diff --git a/Telegram/Resources/winrc/Telegram.rc b/Telegram/Resources/winrc/Telegram.rc index eed344619..cedf12840 100644 --- a/Telegram/Resources/winrc/Telegram.rc +++ b/Telegram/Resources/winrc/Telegram.rc @@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,8,3,0 - PRODUCTVERSION 4,8,3,0 + FILEVERSION 4,8,4,0 + PRODUCTVERSION 4,8,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -62,10 +62,10 @@ BEGIN BEGIN VALUE "CompanyName", "Radolyn Labs" VALUE "FileDescription", "AyuGram Desktop" - VALUE "FileVersion", "4.8.3.0" + VALUE "FileVersion", "4.8.4.0" VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "ProductName", "AyuGram Desktop" - VALUE "ProductVersion", "4.8.3.0" + VALUE "ProductVersion", "4.8.4.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/Resources/winrc/Updater.rc b/Telegram/Resources/winrc/Updater.rc index bf88de7c8..f6f63f644 100644 --- a/Telegram/Resources/winrc/Updater.rc +++ b/Telegram/Resources/winrc/Updater.rc @@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,8,3,0 - PRODUCTVERSION 4,8,3,0 + FILEVERSION 4,8,4,0 + PRODUCTVERSION 4,8,4,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -53,10 +53,10 @@ BEGIN BEGIN VALUE "CompanyName", "Radolyn Labs" VALUE "FileDescription", "AyuGram Desktop Updater" - VALUE "FileVersion", "4.8.3.0" + VALUE "FileVersion", "4.8.4.0" VALUE "LegalCopyright", "Copyright (C) 2014-2023" VALUE "ProductName", "AyuGram Desktop" - VALUE "ProductVersion", "4.8.3.0" + VALUE "ProductVersion", "4.8.4.0" END END BLOCK "VarFileInfo" diff --git a/Telegram/SourceFiles/_other/packer.cpp b/Telegram/SourceFiles/_other/packer.cpp index 2bf651bc6..0ba79c1be 100644 --- a/Telegram/SourceFiles/_other/packer.cpp +++ b/Telegram/SourceFiles/_other/packer.cpp @@ -7,12 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "packer.h" -#include - -#ifdef Q_OS_MAC -//Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin) -#endif - bool BetaChannel = false; quint64 AlphaVersion = 0; bool OnlyAlphaKey = false; diff --git a/Telegram/SourceFiles/_other/updater_linux.cpp b/Telegram/SourceFiles/_other/updater_linux.cpp index 40e887c52..f286b05be 100644 --- a/Telegram/SourceFiles/_other/updater_linux.cpp +++ b/Telegram/SourceFiles/_other/updater_linux.cpp @@ -46,6 +46,7 @@ string updaterName; string workDir; string exeName; string exePath; +string argv0; FILE *_logFile = 0; void openLog() { @@ -388,6 +389,8 @@ int main(int argc, char *argv[]) { exeName = argv[i]; } else if (equal(argv[i], "-exepath") && ++i < argc) { exePath = argv[i]; + } else if (equal(argv[i], "-argv0") && ++i < argc) { + argv0 = argv[i]; } } if (exeName.empty() || exeName.find('/') != string::npos) { @@ -461,15 +464,14 @@ int main(int argc, char *argv[]) { writeLog("Error: short exe name!"); } - auto fullBinaryPath = exePath + exeName; - const auto path = fullBinaryPath.c_str(); + const auto fullBinaryPath = exePath + exeName; auto values = vector(); const auto push = [&](string arg) { // Force null-terminated .data() call result. values.push_back(arg + char(0)); }; - push(path); + push(!argv0.empty() ? argv0 : fullBinaryPath); push("-noupdate"); if (autostart) push("-autostart"); if (debug) push("-debug"); @@ -498,7 +500,7 @@ int main(int argc, char *argv[]) { writeLog("fork() failed!"); return 1; case 0: - execv(args[0], args.data()); + execv(fullBinaryPath.c_str(), args.data()); return 1; } } diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index 19e5a30e3..0ec9ad55d 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -143,9 +143,8 @@ struct Application::Private { Settings settings; }; -Application::Application(not_null launcher) +Application::Application() : QObject() -, _launcher(launcher) , _private(std::make_unique()) , _platformIntegration(Platform::Integration::Create()) , _batterySaving(std::make_unique()) @@ -945,11 +944,11 @@ rpl::producer<> Application::materializeLocalDraftsRequests() const { void Application::switchDebugMode() { if (Logs::DebugEnabled()) { Logs::SetDebugEnabled(false); - _launcher->writeDebugModeSetting(); + Launcher::Instance().writeDebugModeSetting(); Restart(); } else { Logs::SetDebugEnabled(true); - _launcher->writeDebugModeSetting(); + Launcher::Instance().writeDebugModeSetting(); DEBUG_LOG(("Debug logs started.")); if (_lastActivePrimaryWindow) { _lastActivePrimaryWindow->hideLayer(); @@ -957,10 +956,6 @@ void Application::switchDebugMode() { } } -void Application::writeInstallBetaVersionsSetting() { - _launcher->writeInstallBetaVersionsSetting(); -} - Main::Account &Application::activeAccount() const { return _domain->active(); } @@ -1767,10 +1762,8 @@ void Application::startShortcuts() { void Application::RegisterUrlScheme() { base::Platform::RegisterUrlScheme(base::Platform::UrlSchemeDescriptor{ - .executable = (!Platform::IsLinux() || !Core::UpdaterDisabled()) - ? (cExeDir() + cExeName()) - : cExeName(), - .arguments = Sandbox::Instance().customWorkingDir() + .executable = Platform::ExecutablePathForShortcuts(), + .arguments = Launcher::Instance().customWorkingDir() ? u"-workdir \"%1\""_q.arg(cWorkingDir()) : QString(), .protocol = u"tg"_q, diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h index ef65d170e..f9059da8d 100644 --- a/Telegram/SourceFiles/core/application.h +++ b/Telegram/SourceFiles/core/application.h @@ -103,7 +103,6 @@ class Instance; namespace Core { -class Launcher; struct LocalUrlHandler; class Settings; class Tray; @@ -126,16 +125,13 @@ public: MTP::ProxyData now; }; - Application(not_null launcher); + Application(); Application(const Application &other) = delete; Application &operator=(const Application &other) = delete; ~Application(); void run(); - [[nodiscard]] Launcher &launcher() const { - return *_launcher; - } [[nodiscard]] Platform::Integration &platformIntegration() const { return *_platformIntegration; } @@ -319,7 +315,6 @@ public: [[nodiscard]] rpl::producer<> materializeLocalDraftsRequests() const; void switchDebugMode(); - void writeInstallBetaVersionsSetting(); void preventOrInvoke(Fn &&callback); @@ -381,7 +376,6 @@ private: }; InstanceSetter _setter = { this }; - const not_null _launcher; rpl::event_stream _proxyChanges; // Some fields are just moved from the declaration. diff --git a/Telegram/SourceFiles/core/crash_report_window.cpp b/Telegram/SourceFiles/core/crash_report_window.cpp index bb0319353..1376b2f7f 100644 --- a/Telegram/SourceFiles/core/crash_report_window.cpp +++ b/Telegram/SourceFiles/core/crash_report_window.cpp @@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/crash_reports.h" #include "core/application.h" -#include "core/launcher.h" #include "core/sandbox.h" #include "core/update_checker.h" #include "core/ui_integration.h" @@ -250,7 +249,6 @@ LastCrashedWindow::UpdaterData::UpdaterData(QWidget *buttonParent) } LastCrashedWindow::LastCrashedWindow( - not_null launcher, const QByteArray &crashdump, Fn launch) : _dumpraw(crashdump) diff --git a/Telegram/SourceFiles/core/crash_report_window.h b/Telegram/SourceFiles/core/crash_report_window.h index 75e17ba23..f0c438119 100644 --- a/Telegram/SourceFiles/core/crash_report_window.h +++ b/Telegram/SourceFiles/core/crash_report_window.h @@ -20,10 +20,6 @@ namespace MTP { struct ProxyData; } // namespace MTP -namespace Core { -class Launcher; -} // namespace Core - class PreLaunchWindow : public QWidget { public: PreLaunchWindow(QString title = QString()); @@ -94,10 +90,7 @@ private: class LastCrashedWindow : public PreLaunchWindow { public: - LastCrashedWindow( - not_null launcher, - const QByteArray &crashdump, - Fn launch); + LastCrashedWindow(const QByteArray &crashdump, Fn launch); rpl::producer proxyChanges() const; diff --git a/Telegram/SourceFiles/core/crash_reports.cpp b/Telegram/SourceFiles/core/crash_reports.cpp index 9b1be851c..24e22982c 100644 --- a/Telegram/SourceFiles/core/crash_reports.cpp +++ b/Telegram/SourceFiles/core/crash_reports.cpp @@ -313,7 +313,7 @@ QString PlatformString() { Unexpected("Platform in CrashReports::PlatformString."); } -void StartCatching(not_null launcher) { +void StartCatching() { #ifndef DESKTOP_APP_DISABLE_CRASH_REPORTS ProcessAnnotations["Binary"] = cExeName().toUtf8().constData(); ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData(); @@ -324,7 +324,7 @@ void StartCatching(not_null launcher) { : u"%1"_q).arg(AppVersion)).toUtf8().constData(); ProcessAnnotations["Launched"] = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss").toUtf8().constData(); ProcessAnnotations["Platform"] = PlatformString().toUtf8().constData(); - ProcessAnnotations["UserTag"] = QString::number(launcher->installationTag(), 16).toUtf8().constData(); + ProcessAnnotations["UserTag"] = QString::number(Core::Launcher::Instance().installationTag(), 16).toUtf8().constData(); QString dumpspath = cWorkingDir() + u"tdata/dumps"_q; QDir().mkpath(dumpspath); diff --git a/Telegram/SourceFiles/core/crash_reports.h b/Telegram/SourceFiles/core/crash_reports.h index b60941642..6a1f0e1d4 100644 --- a/Telegram/SourceFiles/core/crash_reports.h +++ b/Telegram/SourceFiles/core/crash_reports.h @@ -7,10 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -namespace Core { -class Launcher; -} // namespace Core - namespace CrashReports { QString PlatformString(); @@ -53,7 +49,7 @@ inline void ClearAnnotationRef(const std::string &key) { SetAnnotationRef(key, nullptr); } -void StartCatching(not_null launcher); +void StartCatching(); void FinishCatching(); } // namespace CrashReports diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp index 93608e4c7..0bbe30a97 100644 --- a/Telegram/SourceFiles/core/launcher.cpp +++ b/Telegram/SourceFiles/core/launcher.cpp @@ -281,6 +281,8 @@ base::options::toggle OptionFractionalScalingEnabled({ const char kOptionFractionalScalingEnabled[] = "fractional-scaling-enabled"; const char kOptionFreeType[] = "freetype"; +Launcher *Launcher::InstanceSetter::Instance = nullptr; + std::unique_ptr Launcher::Create(int argc, char *argv[]) { return std::make_unique(argc, argv); } @@ -288,15 +290,18 @@ std::unique_ptr Launcher::Create(int argc, char *argv[]) { Launcher::Launcher(int argc, char *argv[]) : _argc(argc) , _argv(argv) +, _arguments(readArguments(_argc, _argv)) , _baseIntegration(_argc, _argv) { crl::toggle_fp_exceptions(true); base::Integration::Set(&_baseIntegration); } -void Launcher::init() { - _arguments = readArguments(_argc, _argv); +Launcher::~Launcher() { + InstanceSetter::Instance = nullptr; +} +void Launcher::init() { prepareSettings(); initQtMessageLogging(); @@ -343,7 +348,7 @@ int Launcher::exec() { } // Must be started before Platform is started. - Logs::start(this); + Logs::start(); base::options::init(cWorkingDir() + "tdata/experimental_options.json"); // Must be called after options are inited. @@ -425,8 +430,8 @@ QStringList Launcher::readArguments(int argc, char *argv[]) const { return result; } -QString Launcher::argumentsString() const { - return _arguments.join(' '); +const QStringList &Launcher::arguments() const { + return _arguments; } bool Launcher::customWorkingDir() const { @@ -436,17 +441,6 @@ bool Launcher::customWorkingDir() const { void Launcher::prepareSettings() { auto path = base::Platform::CurrentExecutablePath(_argc, _argv); LOG(("Executable path before check: %1").arg(path)); - if (!path.isEmpty()) { - auto info = QFileInfo(path); - if (info.isSymLink()) { - info = QFileInfo(info.symLinkTarget()); - } - if (info.exists()) { - const auto dir = info.absoluteDir().absolutePath(); - gExeDir = (dir.endsWith('/') ? dir : (dir + '/')); - gExeName = info.fileName(); - } - } if (cExeName().isEmpty()) { LOG(("WARNING: Could not compute executable path, some features will be disabled.")); } @@ -558,7 +552,7 @@ void Launcher::processArguments() { int Launcher::executeApplication() { FilteredCommandLineArguments arguments(_argc, _argv); - Sandbox sandbox(this, arguments.count(), arguments.values()); + Sandbox sandbox(arguments.count(), arguments.values()); Ui::MainQueueProcessor processor; base::ConcurrentTimerEnvironment environment; return sandbox.start(); diff --git a/Telegram/SourceFiles/core/launcher.h b/Telegram/SourceFiles/core/launcher.h index 047218951..264085f20 100644 --- a/Telegram/SourceFiles/core/launcher.h +++ b/Telegram/SourceFiles/core/launcher.h @@ -20,9 +20,15 @@ public: static std::unique_ptr Create(int argc, char *argv[]); + static Launcher &Instance() { + Expects(InstanceSetter::Instance != nullptr); + + return *InstanceSetter::Instance; + } + virtual int exec(); - QString argumentsString() const; + const QStringList &arguments() const; bool customWorkingDir() const; uint64 installationTag() const; @@ -32,7 +38,7 @@ public: void writeDebugModeSetting(); void writeInstallBetaVersionsSetting(); - virtual ~Launcher() = default; + virtual ~Launcher(); protected: enum class UpdaterLaunch { @@ -61,6 +67,17 @@ private: int executeApplication(); + struct InstanceSetter { + InstanceSetter(not_null instance) { + Expects(Instance == nullptr); + + Instance = instance; + } + + static Launcher *Instance; + }; + InstanceSetter _setter = { this }; + int _argc; char **_argv; QStringList _arguments; diff --git a/Telegram/SourceFiles/core/sandbox.cpp b/Telegram/SourceFiles/core/sandbox.cpp index ee8ff8fff..051ad5910 100644 --- a/Telegram/SourceFiles/core/sandbox.cpp +++ b/Telegram/SourceFiles/core/sandbox.cpp @@ -80,13 +80,9 @@ QString _escapeFrom7bit(const QString &str) { bool Sandbox::QuitOnStartRequested = false; -Sandbox::Sandbox( - not_null launcher, - int &argc, - char **argv) +Sandbox::Sandbox(int &argc, char **argv) : QApplication(argc, argv) -, _mainThreadId(QThread::currentThreadId()) -, _launcher(launcher) { +, _mainThreadId(QThread::currentThreadId()) { setQuitOnLastWindowClosed(false); } @@ -109,7 +105,8 @@ int Sandbox::start() { hashMd5Hex(d.constData(), d.size(), h.data()); _lockFile = std::make_unique(QDir::tempPath() + '/' + h + '-' + cGUIDStr()); _lockFile->setStaleLockTime(0); - if (!_lockFile->tryLock() && _launcher->customWorkingDir()) { + if (!_lockFile->tryLock() + && Launcher::Instance().customWorkingDir()) { // On Windows, QLockFile has problems detecting a stale lock // if the machine's hostname contains characters outside the US-ASCII character set. if constexpr (Platform::IsWindows()) { @@ -204,7 +201,7 @@ void Sandbox::launchApplication() { } setupScreenScale(); - _application = std::make_unique(_launcher); + _application = std::make_unique(); // Ideally this should go to constructor. // But we want to catch all native events and Application installs @@ -405,7 +402,6 @@ void Sandbox::singleInstanceChecked() { } _lastCrashDump = crashdump; auto window = new LastCrashedWindow( - _launcher, _lastCrashDump, [=] { launchApplication(); }); window->proxyChanges( @@ -533,14 +529,6 @@ void Sandbox::refreshGlobalProxy() { } } -bool Sandbox::customWorkingDir() const { - return _launcher->customWorkingDir(); -} - -uint64 Sandbox::installationTag() const { - return _launcher->installationTag(); -} - void Sandbox::checkForEmptyLoopNestingLevel() { // _loopNestingLevel == _eventNestingLevel means that we had a // native event in a nesting loop that didn't get a notify() call diff --git a/Telegram/SourceFiles/core/sandbox.h b/Telegram/SourceFiles/core/sandbox.h index bcf83982a..d8f47cd5a 100644 --- a/Telegram/SourceFiles/core/sandbox.h +++ b/Telegram/SourceFiles/core/sandbox.h @@ -19,7 +19,6 @@ class QLockFile; namespace Core { -class Launcher; class UpdateChecker; class Application; @@ -33,7 +32,7 @@ private: } public: - Sandbox(not_null launcher, int &argc, char **argv); + Sandbox(int &argc, char **argv); Sandbox(const Sandbox &other) = delete; Sandbox &operator=(const Sandbox &other) = delete; @@ -41,8 +40,6 @@ public: int start(); void refreshGlobalProxy(); - bool customWorkingDir() const; - uint64 installationTag() const; void postponeCall(FnMut &&callable); bool notify(QObject *receiver, QEvent *e) override; @@ -116,7 +113,6 @@ private: std::vector _previousLoopNestingLevels; std::vector _postponedCalls; - not_null _launcher; std::unique_ptr _application; QString _localServerName, _localSocketReadData; diff --git a/Telegram/SourceFiles/core/version.h b/Telegram/SourceFiles/core/version.h index 4dd89075a..9a71820ca 100644 --- a/Telegram/SourceFiles/core/version.h +++ b/Telegram/SourceFiles/core/version.h @@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D666}"_cs; constexpr auto AppNameOld = "AyuGram for Windows"_cs; constexpr auto AppName = "AyuGram Desktop"_cs; constexpr auto AppFile = "AyuGram"_cs; -constexpr auto AppVersion = 4008003; -constexpr auto AppVersionStr = "4.8.3"; +constexpr auto AppVersion = 4008004; +constexpr auto AppVersionStr = "4.8.4"; constexpr auto AppBetaVersion = false; constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION; diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp index 75ac2e87e..03cfe4c49 100644 --- a/Telegram/SourceFiles/logs.cpp +++ b/Telegram/SourceFiles/logs.cpp @@ -343,10 +343,10 @@ bool WritingEntry() { return WritingEntryFlag; } -void start(not_null launcher) { +void start() { Assert(LogsData == nullptr); - if (!launcher->checkPortableVersionFolder()) { + if (!Core::Launcher::Instance().checkPortableVersionFolder()) { return; } @@ -414,8 +414,8 @@ void start(not_null launcher) { QDir().mkpath(cWorkingDir() + u"tdata"_q); - launcher->workingFolderReady(); - CrashReports::StartCatching(launcher); + Core::Launcher::Instance().workingFolderReady(); + CrashReports::StartCatching(); if (!LogsData->openMain()) { delete LogsData; @@ -430,7 +430,7 @@ void start(not_null launcher) { LOG(("Executable dir: %1, name: %2").arg(cExeDir(), cExeName())); LOG(("Initial working dir: %1").arg(initialWorkingDir)); LOG(("Working dir: %1").arg(cWorkingDir())); - LOG(("Command line: %1").arg(launcher->argumentsString())); + LOG(("Command line: %1").arg(Core::Launcher::Instance().arguments().join(' '))); if (!LogsData) { LOG(("FATAL: Could not open '%1' for writing log!" diff --git a/Telegram/SourceFiles/logs.h b/Telegram/SourceFiles/logs.h index f45b07658..b9de4401f 100644 --- a/Telegram/SourceFiles/logs.h +++ b/Telegram/SourceFiles/logs.h @@ -11,17 +11,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/assertion.h" #include "base/debug_log.h" -namespace Core { -class Launcher; -} // namespace Core - namespace Logs { void SetDebugEnabled(bool enabled); bool DebugEnabled(); [[nodiscard]] bool WritingEntry(); -void start(not_null launcher); +void start(); bool started(); void finish(); diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp index e5d229bcf..d339bc228 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp @@ -65,7 +65,7 @@ QByteArray DnsUserAgent() { static const auto kResult = QByteArray( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/113.0.5672.63 Safari/537.36"); + "Chrome/114.0.5735.133 Safari/537.36"); return kResult; } diff --git a/Telegram/SourceFiles/platform/linux/integration_linux.cpp b/Telegram/SourceFiles/platform/linux/integration_linux.cpp index e501ce93b..d69e06030 100644 --- a/Telegram/SourceFiles/platform/linux/integration_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/integration_linux.cpp @@ -8,20 +8,89 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/integration_linux.h" #include "platform/platform_integration.h" +#include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_xdp_utilities.h" +#include "core/sandbox.h" #include "core/application.h" #include "core/core_settings.h" #include "base/random.h" -#include -#include +#include -using namespace gi::repository; +#include +#include + +typedef GApplication TDesktopApplication; +typedef GApplicationClass TDesktopApplicationClass; + +G_DEFINE_TYPE( + TDesktopApplication, + t_desktop_application, + G_TYPE_APPLICATION) + +static void t_desktop_application_class_init( + TDesktopApplicationClass *klass) { + const auto application_class = G_APPLICATION_CLASS(klass); + + application_class->local_command_line = []( + GApplication *application, + char ***arguments, + int *exit_status) -> gboolean { + return false; + }; + + application_class->command_line = []( + GApplication *application, + GApplicationCommandLine *cmdline) { + return 0; + }; + + application_class->before_emit = []( + GApplication *application, + GVariant *platformData) { + if (Platform::IsWayland()) { + static const auto keys = { + "activation-token", + "desktop-startup-id", + }; + for (const auto &key : keys) { + const char *token = nullptr; + g_variant_lookup(platformData, key, "&s", &token); + if (token) { + qputenv("XDG_ACTIVATION_TOKEN", token); + break; + } + } + } + }; + + application_class->add_platform_data = []( + GApplication *application, + GVariantBuilder *builder) { + if (Platform::IsWayland()) { + const auto token = qgetenv("XDG_ACTIVATION_TOKEN"); + if (!token.isEmpty()) { + g_variant_builder_add( + builder, + "{sv}", + "activation-token", + g_variant_new_string(token.constData())); + qunsetenv("XDG_ACTIVATION_TOKEN"); + } + } + }; +} + +static void t_desktop_application_init(TDesktopApplication *application) { +} namespace Platform { namespace { +using namespace gi::repository; +namespace Gio = gi::repository::Gio; + class LinuxIntegration final : public Integration { public: LinuxIntegration(); @@ -33,6 +102,10 @@ private: return _inhibitProxy; } + void initInhibit(); + + static void LaunchNativeApplication(); + XdpInhibit::InhibitProxy _inhibitProxy; base::Platform::XDP::SettingWatcher _darkModeWatcher; }; @@ -61,9 +134,25 @@ LinuxIntegration::LinuxIntegration() } } }) { + LOG(("Icon theme: %1").arg(QIcon::themeName())); + LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName())); + + if (!QCoreApplication::eventDispatcher()->inherits( + "QEventDispatcherGlib")) { + g_warning("Qt is running without GLib event loop integration, " + "except various functionality to not to work."); + } } void LinuxIntegration::init() { + initInhibit(); + + Glib::signal_idle().connect_once([] { + LaunchNativeApplication(); + }); +} + +void LinuxIntegration::initInhibit() { if (!_inhibitProxy) { return; } @@ -119,6 +208,111 @@ void LinuxIntegration::init() { nullptr); } +void LinuxIntegration::LaunchNativeApplication() { + const auto appId = QGuiApplication::desktopFileName() + .chopped(8) + .toStdString(); + + const auto app = Glib::wrap( + G_APPLICATION( + g_object_new( + t_desktop_application_get_type(), + "application-id", + ::Gio::Application::id_is_valid(appId) + ? appId.c_str() + : nullptr, + "flags", + G_APPLICATION_HANDLES_OPEN, + nullptr))); + + app->signal_startup().connect([=] { + // GNotification + InvokeQueued(qApp, [] { + Core::App().notifications().createManager(); + }); + + QEventLoop().exec(); + app->quit(); + }, true); + + app->signal_activate().connect([] { + Core::Sandbox::Instance().customEnterFromEventLoop([] { + Core::App().activate(); + }); + }, true); + + app->signal_open().connect([]( + const ::Gio::Application::type_vec_files &files, + const Glib::ustring &hint) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + for (const auto &file : files) { + QFileOpenEvent e( + QUrl(QString::fromStdString(file->get_uri()))); + QGuiApplication::sendEvent(qApp, &e); + } + }); + }, true); + + app->add_action("quit", [] { + Core::Sandbox::Instance().customEnterFromEventLoop([] { + Core::Quit(); + }); + }); + + using Window::Notifications::Manager; + using NotificationId = Manager::NotificationId; + using NotificationIdTuple = std::invoke_result_t< + decltype(&NotificationId::toTuple), + NotificationId* + >; + + const auto notificationIdVariantType = [] { + try { + return base::Platform::MakeGlibVariant( + NotificationId().toTuple()).get_type(); + } catch (...) { + return Glib::VariantType(); + } + }(); + + app->add_action_with_parameter( + "notification-activate", + notificationIdVariantType, + [](const Glib::VariantBase ¶meter) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + try { + const auto &app = Core::App(); + app.notifications().manager().notificationActivated( + NotificationId::FromTuple( + base::Platform::GlibVariantCast< + NotificationIdTuple + >(parameter))); + } catch (...) { + } + }); + }); + + app->add_action_with_parameter( + "notification-mark-as-read", + notificationIdVariantType, + [](const Glib::VariantBase ¶meter) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + try { + const auto &app = Core::App(); + app.notifications().manager().notificationReplied( + NotificationId::FromTuple( + base::Platform::GlibVariantCast< + NotificationIdTuple + >(parameter)), + {}); + } catch (...) { + } + }); + }); + + app->run(0, nullptr); +} + } // namespace std::unique_ptr CreateIntegration() { diff --git a/Telegram/SourceFiles/platform/linux/launcher_linux.cpp b/Telegram/SourceFiles/platform/linux/launcher_linux.cpp index a2bc1c237..e5ae4efb5 100644 --- a/Telegram/SourceFiles/platform/linux/launcher_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/launcher_linux.cpp @@ -24,8 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Platform { namespace { -Launcher *LauncherInstance = nullptr; - class Arguments { public: void push(QByteArray argument) { @@ -48,23 +46,13 @@ private: } // namespace Launcher::Launcher(int argc, char *argv[]) -: Core::Launcher(argc, argv) -, _arguments(argv, argv + argc) { - Expects(LauncherInstance == nullptr); - - LauncherInstance = this; -} - -Launcher &Launcher::Instance() { - Expects(LauncherInstance != nullptr); - - return *LauncherInstance; +: Core::Launcher(argc, argv) { } int Launcher::exec() { - for (auto i = begin(_arguments), e = end(_arguments); i != e; ++i) { - if (*i == "-webviewhelper" && std::distance(i, e) > 1) { - Webview::WebKitGTK::SetSocketPath(*(i + 1)); + for (auto i = arguments().begin(), e = arguments().end(); i != e; ++i) { + if (*i == u"-webviewhelper"_q && std::distance(i, e) > 1) { + Webview::WebKitGTK::SetSocketPath((i + 1)->toStdString()); return Webview::WebKitGTK::Exec(); } } @@ -81,17 +69,23 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { return false; } - const auto binaryPath = (action == UpdaterLaunch::JustRelaunch) - ? (cExeDir() + cExeName()) - : (cWriteProtected() + const auto justRelaunch = action == UpdaterLaunch::JustRelaunch; + const auto writeProtectedUpdate = action == UpdaterLaunch::PerformUpdate + && cWriteProtected(); + + const auto binaryPath = justRelaunch + ? QFile::encodeName(cExeDir() + cExeName()) + : QFile::encodeName(cWriteProtected() ? (cWorkingDir() + u"tupdates/temp/Updater"_q) : (cExeDir() + u"Updater"_q)); auto argumentsList = Arguments(); - if (action == UpdaterLaunch::PerformUpdate && cWriteProtected()) { + if (writeProtectedUpdate) { argumentsList.push("pkexec"); } - argumentsList.push(QFile::encodeName(binaryPath)); + argumentsList.push((justRelaunch && !arguments().isEmpty()) + ? QFile::encodeName(arguments().first()) + : binaryPath); if (cLaunchMode() == LaunchModeAutoStart) { argumentsList.push("-autostart"); @@ -107,7 +101,7 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { argumentsList.push(QFile::encodeName(cDataFile())); } - if (action == UpdaterLaunch::JustRelaunch) { + if (justRelaunch) { argumentsList.push("-noupdate"); argumentsList.push("-tosettings"); if (customWorkingDir()) { @@ -121,6 +115,10 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { argumentsList.push(QFile::encodeName(cExeName())); argumentsList.push("-exepath"); argumentsList.push(QFile::encodeName(cExeDir())); + if (!arguments().isEmpty()) { + argumentsList.push("-argv0"); + argumentsList.push(QFile::encodeName(arguments().first())); + } if (customWorkingDir()) { argumentsList.push("-workdir_custom"); } @@ -137,11 +135,15 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { pid_t pid = fork(); switch (pid) { case -1: return false; - case 0: execvp(args[0], args); return false; + case 0: + execvp( + writeProtectedUpdate ? args[0] : binaryPath.constData(), + args); + return false; } // pkexec needs an alive parent - if (action == UpdaterLaunch::PerformUpdate && cWriteProtected()) { + if (writeProtectedUpdate) { waitpid(pid, nullptr, 0); // launch new version in the same environment return launchUpdater(UpdaterLaunch::JustRelaunch); diff --git a/Telegram/SourceFiles/platform/linux/launcher_linux.h b/Telegram/SourceFiles/platform/linux/launcher_linux.h index 99d7259ee..e0a45af0f 100644 --- a/Telegram/SourceFiles/platform/linux/launcher_linux.h +++ b/Telegram/SourceFiles/platform/linux/launcher_linux.h @@ -15,16 +15,12 @@ class Launcher : public Core::Launcher { public: Launcher(int argc, char *argv[]); - static Launcher &Instance(); - int exec() override; private: void initHook() override; bool launchUpdater(UpdaterLaunch action) override; - std::vector _arguments; - }; } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp index 064fb818b..b6cc6c888 100644 --- a/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_wayland_integration.cpp @@ -123,12 +123,15 @@ WaylandIntegration::~WaylandIntegration() = default; WaylandIntegration *WaylandIntegration::Instance() { if (!IsWayland()) return nullptr; static std::optional instance(std::in_place); - base::qt_signal_producer( - QGuiApplication::platformNativeInterface(), - &QObject::destroyed - ) | rpl::start_with_next([&] { - instance = std::nullopt; - }, instance->_private->lifetime); + [[maybe_unused]] static const auto Inited = [] { + base::qt_signal_producer( + QGuiApplication::platformNativeInterface(), + &QObject::destroyed + ) | rpl::start_with_next([] { + instance = std::nullopt; + }, instance->_private->lifetime); + return true; + }(); if (!instance) return nullptr; return &*instance; } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index e865ecec7..ed85dc577 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -8,20 +8,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/linux/specific_linux.h" #include "base/random.h" -#include "base/options.h" #include "base/platform/base_platform_info.h" #include "base/platform/linux/base_linux_glibmm_helper.h" #include "base/platform/linux/base_linux_dbus_utilities.h" #include "base/platform/linux/base_linux_xdp_utilities.h" #include "platform/linux/linux_desktop_environment.h" #include "platform/linux/linux_wayland_integration.h" -#include "platform/platform_launcher.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "storage/localstorage.h" -#include "core/sandbox.h" +#include "core/launcher.h" #include "core/application.h" -#include "core/local_url_handlers.h" #include "core/core_settings.h" #include "core/update_checker.h" #include "window/window_controller.h" @@ -35,7 +32,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#include #include #include @@ -56,57 +52,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL using namespace Platform; using Platform::internal::WaylandIntegration; -typedef GApplication TDesktopApplication; -typedef GApplicationClass TDesktopApplicationClass; - -G_DEFINE_TYPE( - TDesktopApplication, - t_desktop_application, - G_TYPE_APPLICATION) - -static void t_desktop_application_class_init( - TDesktopApplicationClass *klass) { - const auto application_class = G_APPLICATION_CLASS(klass); - - application_class->before_emit = []( - GApplication *application, - GVariant *platformData) { - if (Platform::IsWayland()) { - static const auto keys = { - "activation-token", - "desktop-startup-id", - }; - for (const auto &key : keys) { - const char *token = nullptr; - g_variant_lookup(platformData, key, "&s", &token); - if (token) { - qputenv("XDG_ACTIVATION_TOKEN", token); - break; - } - } - } - }; - - application_class->add_platform_data = []( - GApplication *application, - GVariantBuilder *builder) { - if (Platform::IsWayland()) { - const auto token = qgetenv("XDG_ACTIVATION_TOKEN"); - if (!token.isEmpty()) { - g_variant_builder_add( - builder, - "{sv}", - "activation-token", - g_variant_new_string(token.constData())); - qunsetenv("XDG_ACTIVATION_TOKEN"); - } - } - }; -} - -static void t_desktop_application_init(TDesktopApplication *application) { -} - namespace Platform { namespace { @@ -138,7 +83,7 @@ bool PortalAutostart(bool start, bool silent) { std::vector commandline; commandline.push_back(cExeName().toStdString()); - if (Core::Sandbox::Instance().customWorkingDir()) { + if (Core::Launcher::Instance().customWorkingDir()) { commandline.push_back("-workdir"); commandline.push_back(cWorkingDir().toStdString()); } @@ -232,121 +177,13 @@ bool PortalAutostart(bool start, bool silent) { return !error; } -void LaunchGApplication() { - Glib::signal_idle().connect_once([] { - const auto appId = QGuiApplication::desktopFileName() - .chopped(8) - .toStdString(); - - const auto app = Glib::wrap( - G_APPLICATION( - g_object_new( - t_desktop_application_get_type(), - "application-id", - Gio::Application::id_is_valid(appId) - ? appId.c_str() - : nullptr, - "flags", - G_APPLICATION_HANDLES_OPEN, - nullptr))); - - app->signal_startup().connect([=] { - // GNotification - InvokeQueued(qApp, [] { - Core::App().notifications().createManager(); - }); - - QEventLoop().exec(); - app->quit(); - }, true); - - app->signal_activate().connect([] { - Core::Sandbox::Instance().customEnterFromEventLoop([] { - if (Core::IsAppLaunched()) { - Core::App().activate(); - } - }); - }, true); - - app->signal_open().connect([]( - const Gio::Application::type_vec_files &files, - const Glib::ustring &hint) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - for (const auto &file : files) { - QFileOpenEvent e( - QUrl(QString::fromStdString(file->get_uri()))); - QGuiApplication::sendEvent(qApp, &e); - } - }); - }, true); - - app->add_action("quit", [] { - Core::Sandbox::Instance().customEnterFromEventLoop([] { - Core::Quit(); - }); - }); - - using Window::Notifications::Manager; - using NotificationId = Manager::NotificationId; - using NotificationIdTuple = std::invoke_result_t< - decltype(&NotificationId::toTuple), - NotificationId* - >; - - const auto notificationIdVariantType = [] { - try { - return base::Platform::MakeGlibVariant( - NotificationId().toTuple()).get_type(); - } catch (...) { - return Glib::VariantType(); - } - }(); - - app->add_action_with_parameter( - "notification-activate", - notificationIdVariantType, - [](const Glib::VariantBase ¶meter) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - try { - const auto &app = Core::App(); - app.notifications().manager().notificationActivated( - NotificationId::FromTuple( - base::Platform::GlibVariantCast< - NotificationIdTuple - >(parameter))); - } catch (...) { - } - }); - }); - - app->add_action_with_parameter( - "notification-mark-as-read", - notificationIdVariantType, - [](const Glib::VariantBase ¶meter) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - try { - const auto &app = Core::App(); - app.notifications().manager().notificationReplied( - NotificationId::FromTuple( - base::Platform::GlibVariantCast< - NotificationIdTuple - >(parameter)), - {}); - } catch (...) { - } - }); - }); - - app->run(0, nullptr); - }); -} - bool GenerateDesktopFile( const QString &targetPath, const QStringList &args = {}, bool onlyMainGroup = false, bool silent = false) { - if (targetPath.isEmpty() || cExeName().isEmpty()) { + const auto executable = ExecutablePathForShortcuts(); + if (targetPath.isEmpty() || executable.isEmpty()) { return false; } @@ -388,11 +225,7 @@ bool GenerateDesktopFile( target->set_string( group, "TryExec", - KShell::joinArgs({ - !Core::UpdaterDisabled() - ? (cExeDir() + cExeName()) - : cExeName() - }).replace( + KShell::joinArgs({ executable }).replace( '\\', qstr("\\\\")).toStdString()); } @@ -400,10 +233,8 @@ bool GenerateDesktopFile( if (target->has_key(group, "Exec")) { if (group == "Desktop Entry" && !args.isEmpty()) { QStringList exec; - exec.append(!Core::UpdaterDisabled() - ? (cExeDir() + cExeName()) - : cExeName()); - if (Core::Sandbox::Instance().customWorkingDir()) { + exec.append(executable); + if (Core::Launcher::Instance().customWorkingDir()) { exec.append(u"-workdir"_q); exec.append(cWorkingDir()); } @@ -423,10 +254,8 @@ bool GenerateDesktopFile( qstr("\\"))); if (!exec.isEmpty()) { - exec[0] = !Core::UpdaterDisabled() - ? (cExeDir() + cExeName()) - : cExeName(); - if (Core::Sandbox::Instance().customWorkingDir()) { + exec[0] = executable; + if (Core::Launcher::Instance().customWorkingDir()) { exec.insert(1, u"-workdir"_q); exec.insert(2, cWorkingDir()); } @@ -479,7 +308,7 @@ bool GenerateDesktopFile( const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath()); hashMd5Hex(d.constData(), d.size(), md5Hash); - if (!Core::Sandbox::Instance().customWorkingDir()) { + if (!Core::Launcher::Instance().customWorkingDir()) { const auto exePath = QFile::encodeName( cExeDir() + cExeName()); hashMd5Hex(exePath.constData(), exePath.size(), md5Hash); @@ -493,6 +322,55 @@ bool GenerateDesktopFile( return true; } +bool GenerateServiceFile(bool silent = false) { + const auto executable = ExecutablePathForShortcuts(); + if (executable.isEmpty()) { + return false; + } + + const auto targetPath = QStandardPaths::writableLocation( + QStandardPaths::GenericDataLocation) + u"/dbus-1/services/"_q; + + const auto targetFile = targetPath + + QGuiApplication::desktopFileName().chopped(8) + + u".service"_q; + + DEBUG_LOG(("App Info: placing .service file to %1").arg(targetPath)); + if (!QDir(targetPath).exists()) QDir().mkpath(targetPath); + + const auto target = Glib::KeyFile::create(); + constexpr auto group = "D-BUS Service"; + + target->set_string( + group, + "Name", + QGuiApplication::desktopFileName().chopped(8).toStdString()); + + target->set_string( + group, + "Exec", + KShell::joinArgs({ executable }).replace( + '\\', + qstr("\\\\")).toStdString()); + + try { + target->save_to_file(targetFile.toStdString()); + } catch (const std::exception &e) { + if (!silent) { + LOG(("App Error: %1").arg(QString::fromStdString(e.what()))); + } + return false; + } + + QProcess::execute(u"systemctl"_q, { + u"--user"_q, + u"reload"_q, + u"dbus"_q, + }); + + return true; +} + void InstallLauncher() { static const auto DisabledByEnv = !qEnvironmentVariableIsEmpty( "DESKTOPINTEGRATION"); @@ -506,6 +384,7 @@ void InstallLauncher() { QStandardPaths::ApplicationsLocation) + '/'; GenerateDesktopFile(applicationsPath); + GenerateServiceFile(); const auto icons = QStandardPaths::writableLocation( QStandardPaths::GenericDataLocation) + u"/icons/"_q; @@ -615,6 +494,20 @@ bool SkipTaskbarSupported() { return false; } +QString ExecutablePathForShortcuts() { + if (Core::UpdaterDisabled()) { + const auto &arguments = Core::Launcher::Instance().arguments(); + if (!arguments.isEmpty()) { + const auto result = QFileInfo(arguments.first()).fileName(); + if (!result.isEmpty()) { + return result; + } + } + return cExeName(); + } + return cExeDir() + cExeName(); +} + } // namespace Platform QString psAppDataPath() { @@ -676,7 +569,7 @@ void start() { if (!Core::UpdaterDisabled()) { QByteArray md5Hash(h); - if (!Launcher::Instance().customWorkingDir()) { + if (!Core::Launcher::Instance().customWorkingDir()) { const auto exePath = QFile::encodeName( cExeDir() + cExeName()); @@ -726,6 +619,8 @@ void start() { h, cGUIDStr(), u"%1"_q).toStdString()); + + InstallLauncher(); } void finish() { @@ -796,17 +691,6 @@ QImage DefaultApplicationIcon() { namespace ThirdParty { void start() { - LOG(("Icon theme: %1").arg(QIcon::themeName())); - LOG(("Fallback icon theme: %1").arg(QIcon::fallbackThemeName())); - - if (!QCoreApplication::eventDispatcher()->inherits( - "QEventDispatcherGlib")) { - g_warning("Qt is running without GLib event loop integration, " - "except various functionality to not to work."); - } - - InstallLauncher(); - LaunchGApplication(); } void finish() { diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index fb63752c1..12cc59024 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -40,6 +40,10 @@ inline uint64 ActivationWindowId(not_null window) { inline void ActivateOtherProcess(uint64 processId, uint64 windowId) { } +inline QString ExecutablePathForShortcuts() { + return cExeDir() + cExeName(); +} + namespace ThirdParty { inline void start() { diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 2056b8c87..604676615 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -46,10 +46,9 @@ bool TrayIconSupported(); bool SkipTaskbarSupported(); void WriteCrashDumpDetails(); void NewVersionLaunched(int oldVersion); - [[nodiscard]] QImage DefaultApplicationIcon(); - [[nodiscard]] bool PreventsQuit(Core::QuitReason reason); +[[nodiscard]] QString ExecutablePathForShortcuts(); #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) [[nodiscard]] std::optional IsDarkMode(); diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h index db10b458e..0b0945dd5 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.h +++ b/Telegram/SourceFiles/platform/win/specific_win.h @@ -42,6 +42,10 @@ void SetWindowPriority(not_null window, uint32 priority); // Activate window with windowId (if found) or the largest priority. void ActivateOtherProcess(uint64 processId, uint64 windowId); +inline QString ExecutablePathForShortcuts() { + return cExeDir() + cExeName(); +} + namespace ThirdParty { void start(); diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp index e546b14d3..4e2f6e878 100644 --- a/Telegram/SourceFiles/settings.cpp +++ b/Telegram/SourceFiles/settings.cpp @@ -18,7 +18,7 @@ QByteArray gAlphaPrivateKey; bool gManyInstance = false; QString gKeyFile; -QString gWorkingDir, gExeDir, gExeName; +QString gWorkingDir; QStringList gSendPaths; QString gStartUrl; diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h index 298283651..c99ad9597 100644 --- a/Telegram/SourceFiles/settings.h +++ b/Telegram/SourceFiles/settings.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/integration.h" #include "ui/style/style_core.h" #define DeclareReadSetting(Type, Name) extern Type g##Name; \ @@ -56,11 +57,15 @@ inline void cForceWorkingDir(const QString &newDir) { } } -DeclareReadSetting(QString, ExeName); -DeclareReadSetting(QString, ExeDir); +inline QString cExeName() { + return base::Integration::Instance().executableName(); +} +inline QString cExeDir() { + return base::Integration::Instance().executableDir(); +} DeclareSetting(QString, DialogLastPath); DeclareSetting(QString, DialogHelperPath); -inline const QString &cDialogHelperPathFinal() { +inline QString cDialogHelperPathFinal() { return cDialogHelperPath().isEmpty() ? cExeDir() : cDialogHelperPath(); } diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index 0a105c158..0cd7c485f 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "lang/lang_keys.h" #include "core/update_checker.h" +#include "core/launcher.h" #include "core/application.h" #include "tray.h" #include "storage/localstorage.h" @@ -224,7 +225,7 @@ void SetupUpdate( return (toggled != cInstallBetaVersion()); }) | rpl::start_with_next([=](bool toggled) { cSetInstallBetaVersion(toggled); - Core::App().writeInstallBetaVersionsSetting(); + Core::Launcher::Instance().writeInstallBetaVersionsSetting(); Core::UpdateChecker checker; checker.stop(); diff --git a/Telegram/SourceFiles/support/support_helper.cpp b/Telegram/SourceFiles/support/support_helper.cpp index 642f138c2..bb0888d13 100644 --- a/Telegram/SourceFiles/support/support_helper.cpp +++ b/Telegram/SourceFiles/support/support_helper.cpp @@ -28,7 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "storage/storage_media_prepare.h" #include "storage/localimageloader.h" -#include "core/sandbox.h" +#include "core/launcher.h" #include "core/application.h" #include "core/core_settings.h" #include "main/main_session.h" @@ -138,7 +138,7 @@ void EditInfoBox::setInnerFocus() { } uint32 OccupationTag() { - return uint32(Core::Sandbox::Instance().installationTag() & 0xFFFFFFFF); + return uint32(Core::Launcher::Instance().installationTag() & 0xFFFFFFFF); } QString NormalizeName(QString name) { @@ -268,7 +268,7 @@ Helper::Helper(not_null session) }).fail([=] { setSupportName( u"[rand^"_q - + QString::number(Core::Sandbox::Instance().installationTag()) + + QString::number(Core::Launcher::Instance().installationTag()) + ']'); }).send(); } diff --git a/Telegram/build/docker/centos_env/Dockerfile b/Telegram/build/docker/centos_env/Dockerfile index 8ff098e36..e4b9ad10e 100644 --- a/Telegram/build/docker/centos_env/Dockerfile +++ b/Telegram/build/docker/centos_env/Dockerfile @@ -7,7 +7,7 @@ {%- set OPENSSL_PREFIX = "/usr/local/desktop-app/openssl-1.1.1" -%} {%- set CMAKE_VER = "3.26.3" -%} {%- set CMAKE_FILE = "cmake-" ~ CMAKE_VER ~ "-Linux-x86_64.sh" -%} -{%- set CFLAGS_DEBUG = "-g -pipe -fPIC -fstack-protector-all -fstack-clash-protection -D_GLIBCXX_ASSERTIONS" -%} +{%- set CFLAGS_DEBUG = "-g -pipe -fPIC -fstack-protector-all -fstack-clash-protection -fcf-protection -D_GLIBCXX_ASSERTIONS" -%} {%- set CFLAGS_LTO = "-flto=auto -ffat-lto-objects" -%} {%- set LibrariesPath = "/usr/src/Libraries" -%} @@ -52,14 +52,14 @@ FROM builder-base AS builder ENV AR gcc-ar ENV RANLIB gcc-ranlib ENV NM gcc-nm -ENV CFLAGS {% if DEBUG %}-g{% endif %} -O3 {% if LTO %}{{ CFLAGS_LTO }}{% endif %} -pipe -fPIC -fstack-protector-all -fstack-clash-protection -DNDEBUG -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS +ENV CFLAGS {% if DEBUG %}-g{% endif %} -O3 {% if LTO %}{{ CFLAGS_LTO }}{% endif %} -pipe -fPIC -fstack-protector-all -fstack-clash-protection -fcf-protection -DNDEBUG -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS ENV CXXFLAGS $CFLAGS FROM builder AS patches RUN git init patches \ && cd patches \ && git remote add origin {{ GIT }}/desktop-app/patches.git \ - && git fetch --depth=1 origin a1b912c90eaab470ef283622a8f890ee6264dae7 \ + && git fetch --depth=1 origin 963f5b0c2a57f7e90239e64c9e14ed5f043e637e \ && git reset --hard FETCH_HEAD \ && rm -rf .git @@ -729,10 +729,6 @@ RUN git clone -b {{ QT_TAG }} --depth=1 https://code.qt.io/qt/qt5.git qt_{{ QT } && git submodule update --init --recursive --depth=1 qtbase qtdeclarative qtwayland qtimageformats qtsvg qtshadertools \ && cd qtbase \ && find ../../patches/qtbase_{{ QT }} -type f -print0 | sort -z | xargs -r0 git apply \ - && cd ../qtdeclarative \ - && sed -i '/add_subdirectory(quickcontrols)/d' src/CMakeLists.txt \ - && sed -i '/add_subdirectory(quickdialogs)/d' src/CMakeLists.txt \ - && sed -i '/add_subdirectory(quicknativestyle)/d' src/CMakeLists.txt \ && cd .. \ && ./configure -prefix "{{ QT_PREFIX }}" \ CMAKE_BUILD_TYPE=None \ diff --git a/Telegram/build/docker/centos_env/build.sh b/Telegram/build/docker/centos_env/build.sh index b86f9911e..6aee294a4 100755 --- a/Telegram/build/docker/centos_env/build.sh +++ b/Telegram/build/docker/centos_env/build.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -e cd Telegram ./configure.sh "$@" diff --git a/Telegram/build/docker/centos_env/gen_dockerfile.py b/Telegram/build/docker/centos_env/gen_dockerfile.py index 76143aa39..997b784ca 100755 --- a/Telegram/build/docker/centos_env/gen_dockerfile.py +++ b/Telegram/build/docker/centos_env/gen_dockerfile.py @@ -3,10 +3,13 @@ from os import environ from os.path import dirname from jinja2 import Environment, FileSystemLoader +def checkEnv(envName, defaultValue): + return bool(len(environ[envName])) if envName in environ else defaultValue + def main(): print(Environment(loader=FileSystemLoader(dirname(__file__))).get_template("Dockerfile").render( - DEBUG=bool(len(environ["DEBUG"])) if "DEBUG" in environ else True, - LTO=bool(len(environ["LTO"])) if "LTO" in environ else True, + DEBUG=checkEnv("DEBUG", True), + LTO=checkEnv("LTO", True), )) if __name__ == '__main__': diff --git a/Telegram/build/prepare/prepare.py b/Telegram/build/prepare/prepare.py index 813716b75..8b8bfd1d3 100644 --- a/Telegram/build/prepare/prepare.py +++ b/Telegram/build/prepare/prepare.py @@ -673,7 +673,7 @@ mac: stage('dav1d', """ win: - git clone -b 1.0.0 --depth 1 https://code.videolan.org/videolan/dav1d.git + git clone -b 1.2.1 --depth 1 https://code.videolan.org/videolan/dav1d.git cd dav1d depends:python/Scripts/activate.bat %THIRDPARTY_DIR%\\python\\Scripts\\activate.bat @@ -710,7 +710,7 @@ release: stage('libde265', """ win: - git clone --depth 1 -b v1.0.11 https://github.com/strukturag/libde265.git + git clone --depth 1 -b v1.0.12 https://github.com/strukturag/libde265.git cd libde265 cmake . ^ -A %WIN32X64% ^ @@ -734,7 +734,7 @@ release: stage('libheif', """ win: - git clone --depth 1 -b v1.15.1 https://github.com/strukturag/libheif.git + git clone --depth 1 -b v1.16.2 https://github.com/strukturag/libheif.git cd libheif %THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/LIBHEIF_EXPORTS/LIBDE265_STATIC_BUILD/g' libheif/CMakeLists.txt %THIRDPARTY_DIR%\\msys64\\usr\\bin\\sed.exe -i 's/HAVE_VISIBILITY/LIBHEIF_STATIC_BUILD/g' libheif/CMakeLists.txt @@ -762,7 +762,7 @@ release: stage('libjxl', """ win: - git clone -b v0.8.1 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git + git clone -b v0.8.2 --depth 1 --recursive --shallow-submodules https://github.com/libjxl/libjxl.git cd libjxl cmake . ^ -A %WIN32X64% ^ diff --git a/Telegram/build/release.py b/Telegram/build/release.py index 83429b191..ce96bf9da 100644 --- a/Telegram/build/release.py +++ b/Telegram/build/release.py @@ -63,20 +63,11 @@ def getOutput(command): sys.exit(1) return output.decode('utf-8') -def prepareSources(): - workpath = os.getcwd() - os.chdir('../..') - rootpath = os.getcwd() - finalpath = rootpath + '/out/Release/sources.tar' - if os.path.exists(finalpath): - os.remove(finalpath) - if os.path.exists(finalpath + '.gz'): - os.remove(finalpath + '.gz') - tmppath = rootpath + '/out/Release/tmp.tar' - print('Preparing source tarball...') - if (call(('git archive --prefix=tdesktop-' + version + '-full/ -o ' + finalpath + ' v' + version).split()) != 0): - os.remove(finalpath) - sys.exit(1) +def invoke(command): + return call(command.split()) == 0 + +def appendSubmodules(appendTo, root, rootRevision): + startpath = os.getcwd() lines = getOutput('git submodule foreach').split('\n') for line in lines: if len(line) == 0: @@ -84,23 +75,48 @@ def prepareSources(): match = re.match(r"^Entering '([^']+)'$", line) if not match: print('Bad line: ' + line) - sys.exit(1) + return False path = match.group(1) - revision = getOutput('git rev-parse v' + version + ':' + path).split('\n')[0] + subroot = root + '/' + path + revision = getOutput('git rev-parse ' + rootRevision + ':' + path).split('\n')[0] print('Adding submodule ' + path + '...') os.chdir(path) - if (call(('git archive --prefix=tdesktop-' + version + '-full/' + path + '/ ' + revision + ' -o ' + tmppath).split()) != 0): - os.remove(finalpath) - os.remove(tmppath) - sys.exit(1) - if (call(('gtar --concatenate --file=' + finalpath + ' ' + tmppath).split()) != 0): - os.remove(finalpath) - os.remove(tmppath) - sys.exit(1) - os.remove(tmppath) - os.chdir(rootpath) + tmppath = appendTo + '_tmp' + if not invoke('git archive --prefix=' + subroot + '/ ' + revision + ' -o ' + tmppath + '.tar'): + os.remove(appendTo + '.tar') + os.remove(tmppath + '.tar') + return False + if not appendSubmodules(tmppath, subroot, revision): + return False + if not invoke('gtar --concatenate --file=' + appendTo + '.tar ' + tmppath + '.tar'): + os.remove(appendTo + '.tar') + os.remove(tmppath + '.tar') + return False + os.remove(tmppath + '.tar') + os.chdir(startpath) + return True + +def prepareSources(): + workpath = os.getcwd() + os.chdir('../..') + rootpath = os.getcwd() + finalpart = rootpath + '/out/Release/sources' + finalpath = finalpart + '.tar' + if os.path.exists(finalpath): + os.remove(finalpath) + if os.path.exists(finalpath + '.gz'): + os.remove(finalpath + '.gz') + tmppath = rootpath + '/out/Release/tmp.tar' + print('Preparing source tarball...') + revision = 'v' + version + targetRoot = 'tdesktop-' + version + '-full'; + if not invoke('git archive --prefix=' + targetRoot + '/ -o ' + finalpath + ' ' + revision): + os.remove(finalpath) + sys.exit(1) + if not appendSubmodules(finalpart, targetRoot, revision): + sys.exit(1) print('Compressing...') - if (call(('gzip -9 ' + finalpath).split()) != 0): + if not invoke('gzip -9 ' + finalpath): os.remove(finalpath) sys.exit(1) os.chdir(workpath) @@ -254,12 +270,12 @@ if r.status_code == 404: checkResponseCode(r, 201) tagname = 'v' + version -call("git fetch origin".split()) +invoke("git fetch origin") if stable == 1: - call("git push launchpad {}:master".format(tagname).split()) + invoke("git push launchpad {}:master".format(tagname)) else: - call("git push launchpad {}:beta".format(tagname).split()) -call("git push --tags launchpad".split()) + invoke("git push launchpad {}:beta".format(tagname)) +invoke("git push --tags launchpad") r = requests.get(url + 'repos/telegramdesktop/tdesktop/releases/tags/v' + version) checkResponseCode(r, 200) @@ -307,9 +323,8 @@ for file in files: checkResponseCode(r, 201) print('Success! Removing.') - return_code = call(["rm", file_path]) - if return_code != 0: - print('Bad rm code: ' + str(return_code)) + if not invoke('rm ' + file_path): + print('Bad rm return code :(') sys.exit(1) sys.exit() diff --git a/Telegram/build/version b/Telegram/build/version index 26a1c6afc..e74e8988d 100644 --- a/Telegram/build/version +++ b/Telegram/build/version @@ -1,7 +1,7 @@ -AppVersion 4008003 +AppVersion 4008004 AppVersionStrMajor 4.8 -AppVersionStrSmall 4.8.3 -AppVersionStr 4.8.3 +AppVersionStrSmall 4.8.4 +AppVersionStr 4.8.4 BetaChannel 0 AlphaVersion 0 -AppVersionOriginal 4.8.3 +AppVersionOriginal 4.8.4 diff --git a/changelog.txt b/changelog.txt index 57529e508..5906c8a22 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +4.8.4 (13.06.23) + +- Fix opening links on Linux. + 4.8.3 (31.05.23) - Fix main window focus from notifications with disabled animations. diff --git a/docs/building-mac.md b/docs/building-mac.md index c9bd02fbf..d357c66c1 100644 --- a/docs/building-mac.md +++ b/docs/building-mac.md @@ -13,7 +13,7 @@ You will require **api_id** and **api_hash** to access the Telegram API servers. Go to ***BuildPath*** and run ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - brew install git automake cmake wget pkg-config gnu-tar + brew install git automake cmake wget pkg-config gnu-tar ninja sudo xcode-select -s /Applications/Xcode.app/Contents/Developer diff --git a/lib/xdg/org.ayugram.desktop.desktop b/lib/xdg/org.ayugram.desktop.desktop index 5d0f0cd7b..e31481d16 100644 --- a/lib/xdg/org.ayugram.desktop.desktop +++ b/lib/xdg/org.ayugram.desktop.desktop @@ -11,6 +11,7 @@ Categories=Chat;Network;InstantMessaging;Qt; MimeType=x-scheme-handler/tg; Keywords=tg;chat;im;messaging;messenger;sms;tdesktop; Actions=quit; +DBusActivatable=true SingleMainWindow=true X-GNOME-UsesNotifications=true X-GNOME-SingleWindow=true diff --git a/lib/xdg/org.telegram.desktop.service b/lib/xdg/org.telegram.desktop.service new file mode 100644 index 000000000..0f9caabbc --- /dev/null +++ b/lib/xdg/org.telegram.desktop.service @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.telegram.desktop +Exec=telegram-desktop diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 1e7ab390c..d48887a61 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -28,9 +28,11 @@ apps: - camera - desktop - desktop-legacy + - gsettings - hardware-observe - home - network + - network-bind - network-status - opengl - removable-media @@ -52,7 +54,6 @@ plugs: mount-host-font-cache: false # Support for common GTK themes # https://forum.snapcraft.io/t/how-to-use-the-system-gtk-theme-via-the-gtk-common-themes-snap/6235 - gsettings: gtk-3-themes: interface: content target: $SNAP/data-dir/themes