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