Add autostart support for linux

This commit is contained in:
Ilya Fedin 2020-01-21 04:10:10 +04:00 committed by John Preston
parent 74942cd06e
commit 05eabfd539
5 changed files with 139 additions and 102 deletions

View File

@ -56,5 +56,6 @@
</qresource> </qresource>
<qresource prefix="/misc"> <qresource prefix="/misc">
<file alias="default_shortcuts-custom.json">../../default_shortcuts-custom.json</file> <file alias="default_shortcuts-custom.json">../../default_shortcuts-custom.json</file>
<file alias="telegramdesktop.desktop">../../../../lib/xdg/telegramdesktop.desktop</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -24,6 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QProcess> #include <QtCore/QProcess>
#include <QtCore/QVersionNumber> #include <QtCore/QVersionNumber>
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <QtDBus/QDBusInterface>
#endif
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <cstdlib> #include <cstdlib>
@ -38,6 +42,27 @@ using Platform::File::internal::EscapeShell;
namespace { namespace {
constexpr auto kDesktopFile = str_const(":/misc/telegramdesktop.desktop");
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
void SandboxAutostart(bool autostart) {
QVariantMap options;
options["reason"] = tr::lng_settings_auto_start(tr::now);
options["autostart"] = autostart;
options["commandline"] = QStringList({
cExeName(),
qsl("-autostart")
});
options["dbus-activatable"] = false;
QDBusInterface(
qsl("org.freedesktop.portal.Desktop"),
qsl("/org/freedesktop/portal/desktop"),
qsl("/org/freedesktop/portal/desktop")
).call(qsl("RequestBackground"), QString(), options);
}
#endif
bool RunShellCommand(const QByteArray &command) { bool RunShellCommand(const QByteArray &command) {
auto result = system(command.constData()); auto result = system(command.constData());
if (result) { if (result) {
@ -87,6 +112,61 @@ void FallbackFontConfig() {
#endif // !DESKTOP_APP_USE_PACKAGED #endif // !DESKTOP_APP_USE_PACKAGED
} }
bool GenerateDesktopFile(const QString &targetPath, const QString &args) {
DEBUG_LOG(("App Info: placing .desktop file to %1").arg(targetPath));
if (!QDir(targetPath).exists()) QDir().mkpath(targetPath);
const auto targetFile = targetPath
+ qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME) ".desktop");
QString fileText;
QFile source(str_const_toString(kDesktopFile));
if (source.open(QIODevice::ReadOnly)) {
QTextStream s(&source);
fileText = s.readAll();
source.close();
} else {
LOG(("App Error: Could not open '%1' for read")
.arg(str_const_toString(kDesktopFile)));
return false;
}
QFile target(targetFile);
if (target.open(QIODevice::WriteOnly)) {
#ifdef DESKTOP_APP_USE_PACKAGED
fileText = fileText.replace(
QRegularExpression(qsl("^Exec=(.*) -- %u$"),
QRegularExpression::MultilineOption),
qsl("Exec=\\1")
+ (args.isEmpty() ? QString() : ' ' + args));
#else
fileText = fileText.replace(
QRegularExpression(qsl("^TryExec=.*$"),
QRegularExpression::MultilineOption),
qsl("TryExec=")
+ EscapeShell(QFile::encodeName(cExeDir() + cExeName())));
fileText = fileText.replace(
QRegularExpression(qsl("^Exec=.*$"),
QRegularExpression::MultilineOption),
qsl("Exec=")
+ EscapeShell(QFile::encodeName(cExeDir() + cExeName()))
+ (args.isEmpty() ? QString() : ' ' + args));
#endif
target.write(fileText.toUtf8());
target.close();
DEBUG_LOG(("App Info: removing old .desktop file"));
QFile(qsl("%1telegram.desktop").arg(targetPath)).remove();
return true;
} else {
LOG(("App Error: Could not open '%1' for write").arg(targetFile));
return false;
}
}
} // namespace } // namespace
namespace Platform { namespace Platform {
@ -98,7 +178,7 @@ void SetApplicationIcon(const QIcon &icon) {
bool InSandbox() { bool InSandbox() {
static const auto Sandbox = QFileInfo::exists( static const auto Sandbox = QFileInfo::exists(
QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)
+ qsl("/flatpak-info")); + qsl("/flatpak-info"));
return Sandbox; return Sandbox;
} }
@ -258,104 +338,45 @@ void finish() {
void RegisterCustomScheme() { void RegisterCustomScheme() {
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
auto home = getHomeDir(); auto home = getHomeDir();
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) return; // don't update desktop file for alpha version if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty())
return; // don't update desktop file for alpha version
if (Core::UpdaterDisabled()) if (Core::UpdaterDisabled())
return; return;
const auto applicationsPath = QStandardPaths::writableLocation(
QStandardPaths::ApplicationsLocation) + '/';
#ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION #ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
DEBUG_LOG(("App Info: placing .desktop file")); GenerateDesktopFile(applicationsPath, qsl("-- %u"));
if (QDir(home + qsl(".local/")).exists()) {
QString apps = home + qsl(".local/share/applications/");
QString icons = home + qsl(".local/share/icons/");
if (!QDir(apps).exists()) QDir().mkpath(apps);
if (!QDir(icons).exists()) QDir().mkpath(icons);
QString path = cWorkingDir() + qsl("tdata/"), file = path + qsl("telegramdesktop.desktop"); const auto icons =
QDir().mkpath(path); QStandardPaths::writableLocation(
QFile f(file); QStandardPaths::GenericDataLocation)
if (f.open(QIODevice::WriteOnly)) { + qsl("/icons/");
QString icon = icons + qsl("telegram.png");
auto iconExists = QFile(icon).exists();
if (Local::oldSettingsVersion() < 10021 && iconExists) {
// Icon was changed.
if (QFile(icon).remove()) {
iconExists = false;
}
}
if (!iconExists) {
if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) {
DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
}
}
QTextStream s(&f); if (!QDir(icons).exists()) QDir().mkpath(icons);
s.setCodec("UTF-8");
s << "[Desktop Entry]\n";
s << "Version=1.0\n";
s << "Name=Telegram Desktop\n";
s << "Comment=Official desktop application for the Telegram messaging service\n";
s << "TryExec=" << EscapeShell(QFile::encodeName(cExeDir() + cExeName())) << "\n";
s << "Exec=" << EscapeShell(QFile::encodeName(cExeDir() + cExeName())) << " -- %u\n";
s << "Icon=telegram\n";
s << "Terminal=false\n";
s << "StartupWMClass=TelegramDesktop\n";
s << "Type=Application\n";
s << "Categories=Network;InstantMessaging;Qt;\n";
s << "MimeType=x-scheme-handler/tg;\n";
s << "Keywords=tg;chat;im;messaging;messenger;sms;tdesktop;\n";
s << "X-GNOME-UsesNotifications=true\n";
f.close();
if (RunShellCommand("desktop-file-install --dir=" + EscapeShell(QFile::encodeName(home + qsl(".local/share/applications"))) + " --delete-original " + EscapeShell(QFile::encodeName(file)))) { const auto icon = icons + qsl("telegram.png");
DEBUG_LOG(("App Info: removing old .desktop file")); auto iconExists = QFile(icon).exists();
QFile(qsl("%1.local/share/applications/telegram.desktop").arg(home)).remove(); if (Local::oldSettingsVersion() < 10021 && iconExists) {
// Icon was changed.
RunShellCommand("update-desktop-database " + EscapeShell(QFile::encodeName(home + qsl(".local/share/applications")))); if (QFile(icon).remove()) {
RunShellCommand("xdg-mime default telegramdesktop.desktop x-scheme-handler/tg"); iconExists = false;
} }
} else { }
LOG(("App Error: Could not open '%1' for write").arg(file)); if (!iconExists) {
if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) {
DEBUG_LOG(("App Info: Icon copied to 'tdata'"));
} }
} }
#endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION #endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
DEBUG_LOG(("App Info: registerting for Gnome")); RunShellCommand("update-desktop-database "
if (RunShellCommand("gconftool-2 -t string -s /desktop/gnome/url-handlers/tg/command " + EscapeShell(EscapeShell(QFile::encodeName(cExeDir() + cExeName())) + " -- %s"))) { + EscapeShell(QFile::encodeName(applicationsPath)));
RunShellCommand("gconftool-2 -t bool -s /desktop/gnome/url-handlers/tg/needs_terminal false");
RunShellCommand("gconftool-2 -t bool -s /desktop/gnome/url-handlers/tg/enabled true");
}
DEBUG_LOG(("App Info: placing .protocol file")); RunShellCommand("xdg-mime default "
QString services; MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME)
if (QDir(home + qsl(".kde4/")).exists()) { ".desktop x-scheme-handler/tg");
services = home + qsl(".kde4/share/kde4/services/");
} else if (QDir(home + qsl(".kde/")).exists()) {
services = home + qsl(".kde/share/kde4/services/");
}
if (!services.isEmpty()) {
if (!QDir(services).exists()) QDir().mkpath(services);
QString path = services, file = path + qsl("tg.protocol");
QFile f(file);
if (f.open(QIODevice::WriteOnly)) {
QTextStream s(&f);
s.setCodec("UTF-8");
s << "[Protocol]\n";
s << "exec=" << QFile::decodeName(EscapeShell(QFile::encodeName(cExeDir() + cExeName()))) << " -- %u\n";
s << "protocol=tg\n";
s << "input=none\n";
s << "output=none\n";
s << "helper=true\n";
s << "listing=false\n";
s << "reading=false\n";
s << "writing=false\n";
s << "makedir=false\n";
s << "deleting=false\n";
f.close();
} else {
LOG(("App Error: Could not open '%1' for write").arg(file));
}
}
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME #endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
} }
@ -417,6 +438,28 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) {
} }
void psAutoStart(bool start, bool silent) { void psAutoStart(bool start, bool silent) {
auto home = getHomeDir();
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty())
return;
if (InSandbox()) {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
SandboxAutostart(start);
#endif
} else {
const auto autostart =
QStandardPaths::writableLocation(
QStandardPaths::GenericConfigLocation)
+ qsl("/autostart/");
if (start) {
GenerateDesktopFile(autostart, qsl("-autostart"));
} else {
QFile::remove(autostart
+ qsl(MACRO_TO_STRING(TDESKTOP_LAUNCHER_BASENAME)
".desktop"));
}
}
} }
void psSendToMenu(bool send, bool silent) { void psSendToMenu(bool send, bool silent) {

View File

@ -358,7 +358,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
} }
#ifndef OS_WIN_STORE #ifndef OS_WIN_STORE
if (Platform::IsWindows()) { if (Platform::IsWindows() || Platform::IsLinux()) {
const auto minimizedToggled = [] { const auto minimizedToggled = [] {
return cStartMinimized() && !Global::LocalPasscode(); return cStartMinimized() && !Global::LocalPasscode();
}; };
@ -369,9 +369,6 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
const auto minimized = addSlidingCheckbox( const auto minimized = addSlidingCheckbox(
tr::lng_settings_start_min(tr::now), tr::lng_settings_start_min(tr::now),
minimizedToggled()); minimizedToggled());
const auto sendto = addCheckbox(
tr::lng_settings_add_sendto(tr::now),
cSendToMenu());
autostart->checkedChanges( autostart->checkedChanges(
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
@ -408,6 +405,12 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
minimized->entity()->setChecked(minimizedToggled()); minimized->entity()->setChecked(minimizedToggled());
}, minimized->lifetime()); }, minimized->lifetime());
}
if (Platform::IsWindows()) {
const auto sendto = addCheckbox(
tr::lng_settings_add_sendto(tr::now),
cSendToMenu());
sendto->checkedChanges( sendto->checkedChanges(
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {

View File

@ -2,6 +2,7 @@
Version=1.0 Version=1.0
Name=Telegram Desktop Name=Telegram Desktop
Comment=Official desktop version of Telegram messaging app Comment=Official desktop version of Telegram messaging app
TryExec=telegram-desktop
Exec=telegram-desktop -- %u Exec=telegram-desktop -- %u
Icon=telegram Icon=telegram
Terminal=false Terminal=false

View File

@ -1,11 +0,0 @@
[Protocol]
exec=/usr/bin/telegram-desktop -- %u
protocol=tg
input=none
output=none
helper=true
listing=false
reading=false
writing=false
makedir=false
deleting=false