Get GApplication out of experimental settings

GApplication will always be used on Linux now. GNotification gets a toggle instead.
This commit is contained in:
Ilya Fedin 2023-01-12 21:06:32 +04:00 committed by John Preston
parent 241be89e5c
commit 9b7826ea0d
8 changed files with 161 additions and 232 deletions

View file

@ -1137,7 +1137,6 @@ PRIVATE
platform/platform_integration.h platform/platform_integration.h
platform/platform_main_window.h platform/platform_main_window.h
platform/platform_notifications_manager.h platform/platform_notifications_manager.h
platform/platform_specific.cpp
platform/platform_specific.h platform/platform_specific.h
platform/platform_tray.h platform/platform_tray.h
platform/platform_window_title.h platform/platform_window_title.h

View file

@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/platform/linux/base_linux_glibmm_helper.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_dbus_utilities.h"
#include "platform/platform_specific.h"
#include "core/application.h" #include "core/application.h"
#include "core/sandbox.h" #include "core/sandbox.h"
#include "core/core_settings.h" #include "core/core_settings.h"
@ -319,6 +318,18 @@ Glib::ustring GetImageKey(const QVersionNumber &specificationVersion) {
return "icon_data"; return "icon_data";
} }
bool UseGNotification() {
if (!Gio::Application::get_default()) {
return false;
}
if (Window::Notifications::OptionGNotification.value()) {
return true;
}
return KSandbox::isFlatpak() && !ServiceRegistered;
}
class NotificationData final : public base::has_weak_ptr { class NotificationData final : public base::has_weak_ptr {
public: public:
using NotificationId = Window::Notifications::Manager::NotificationId; using NotificationId = Window::Notifications::Manager::NotificationId;
@ -378,7 +389,7 @@ NotificationData::NotificationData(
NotificationId id) NotificationId id)
: _manager(manager) : _manager(manager)
, _id(id) , _id(id)
, _application(Gio::Application::get_default()) { , _application(UseGNotification() ? Gio::Application::get_default() : {}) {
} }
bool NotificationData::init( bool NotificationData::init(
@ -811,13 +822,13 @@ bool WaitForInputForCustom() {
} }
bool Supported() { bool Supported() {
return ServiceRegistered || Gio::Application::get_default(); return ServiceRegistered || UseGNotification();
} }
bool Enforced() { bool Enforced() {
// Wayland doesn't support positioning // Wayland doesn't support positioning
// and custom notifications don't work here // and custom notifications don't work here
return IsWayland() || OptionGApplication.value(); return IsWayland() || Window::Notifications::OptionGNotification.value();
} }
bool ByDefault() { bool ByDefault() {
@ -841,7 +852,7 @@ bool ByDefault() {
} }
void Create(Window::Notifications::System *system) { void Create(Window::Notifications::System *system) {
static auto ServiceWatcher = CreateServiceWatcher(); static const auto ServiceWatcher = CreateServiceWatcher();
const auto managerSetter = [=] { const auto managerSetter = [=] {
using ManagerType = Window::Notifications::ManagerType; using ManagerType = Window::Notifications::ManagerType;
@ -860,35 +871,15 @@ void Create(Window::Notifications::System *system) {
} }
}; };
if (Gio::Application::get_default()) {
ServiceWatcher = nullptr;
ServiceRegistered = false;
CurrentServerInformation = std::nullopt;
CurrentCapabilities = QStringList{};
managerSetter();
return;
}
const auto counter = std::make_shared<int>(2); const auto counter = std::make_shared<int>(2);
const auto oneReady = [=] { const auto oneReady = [=] {
if (!--*counter) { if (!--*counter) {
// GApplication may be created while the reply is received
if (Gio::Application::get_default()) {
Core::App().notifications().createManager();
return;
}
managerSetter(); managerSetter();
} }
}; };
// snap doesn't allow access when the daemon is not running :( // snap doesn't allow access when the daemon is not running :(
StartServiceAsync([=] { StartServiceAsync([=] {
// GApplication may be created while the reply is received
if (Gio::Application::get_default()) {
Core::App().notifications().createManager();
return;
}
ServiceRegistered = GetServiceRegistered(); ServiceRegistered = GetServiceRegistered();
if (!ServiceRegistered) { if (!ServiceRegistered) {

View file

@ -240,187 +240,140 @@ bool PortalAutostart(bool start, bool silent) {
} }
void LaunchGApplication() { void LaunchGApplication() {
const auto connection = [] { Glib::signal_idle().connect_once([] {
try { const auto appId = QGuiApplication::desktopFileName()
return Gio::DBus::Connection::get_sync( .chopped(8)
Gio::DBus::BusType::SESSION); .toStdString();
} catch (...) {
return Glib::RefPtr<Gio::DBus::Connection>();
}
}();
using namespace base::Platform::DBus; const auto app = Glib::wrap(
const auto activatableNames = [&] { G_APPLICATION(
try { g_object_new(
if (connection) { t_desktop_application_get_type(),
return ListActivatableNames(connection); "application-id",
} Gio::Application::id_is_valid(appId)
} catch (...) { ? appId.c_str()
} : nullptr,
"flags",
G_APPLICATION_HANDLES_OPEN,
nullptr)));
return std::vector<Glib::ustring>(); app->signal_startup().connect([=] {
}(); // GNotification
InvokeQueued(qApp, [] {
Core::App().notifications().createManager();
});
const auto freedesktopNotifications = [&] { QEventLoop().exec();
try { app->quit();
if (connection && NameHasOwner( }, true);
connection,
"org.freedesktop.Notifications")) {
return true;
}
} catch (...) {
}
if (ranges::contains( app->signal_activate().connect([] {
activatableNames, Core::Sandbox::Instance().customEnterFromEventLoop([] {
"org.freedesktop.Notifications", const auto window = Core::IsAppLaunched()
&Glib::ustring::raw)) { ? Core::App().primaryWindow()
return true; : nullptr;
} if (window) {
window->activate();
}
});
}, true);
return false; app->signal_open().connect([](
}; const Gio::Application::type_vec_files &files,
const Glib::ustring &hint) {
if (OptionGApplication.value() Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|| (KSandbox::isFlatpak() && !freedesktopNotifications())) { for (const auto &file : files) {
Glib::signal_idle().connect_once([] { if (file->get_uri_scheme() == "file") {
const auto appId = QGuiApplication::desktopFileName() gSendPaths.append(
.chopped(8) QString::fromStdString(file->get_path()));
.toStdString(); continue;
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([] {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
} }
}); const auto url = QString::fromStdString(file->get_uri());
}, true); if (url.isEmpty()) {
continue;
}
if (url.startsWith(qstr("interpret://"))) {
gSendPaths.append(url);
continue;
}
if (Core::StartUrlRequiresActivate(url)) {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
}
}
cSetStartUrl(url);
Core::App().checkStartUrl();
}
app->signal_open().connect([]( if (!cSendPaths().isEmpty()) {
const Gio::Application::type_vec_files &files, Core::App().checkSendPaths();
const Glib::ustring &hint) { }
});
}, 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-reply",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] { Core::Sandbox::Instance().customEnterFromEventLoop([&] {
for (const auto &file : files) { try {
if (file->get_uri_scheme() == "file") { const auto &app = Core::App();
gSendPaths.append( app.notifications().manager().notificationActivated(
QString::fromStdString(file->get_path())); NotificationId::FromTuple(
continue; base::Platform::GlibVariantCast<
} NotificationIdTuple
const auto url = QString::fromStdString( >(parameter)));
file->get_uri()); } catch (...) {
if (url.isEmpty()) {
continue;
}
if (url.startsWith(qstr("interpret://"))) {
gSendPaths.append(url);
continue;
}
if (Core::StartUrlRequiresActivate(url)) {
const auto window = Core::IsAppLaunched()
? Core::App().primaryWindow()
: nullptr;
if (window) {
window->activate();
}
}
cSetStartUrl(url);
Core::App().checkStartUrl();
} }
if (!cSendPaths().isEmpty()) {
Core::App().checkSendPaths();
}
});
}, true);
app->add_action("Quit", [] {
Core::Sandbox::Instance().customEnterFromEventLoop([] {
Core::Quit();
}); });
}); });
using Window::Notifications::Manager; app->add_action_with_parameter(
using NotificationId = Manager::NotificationId; "notification-mark-as-read",
using NotificationIdTuple = std::invoke_result_t< notificationIdVariantType,
decltype(&NotificationId::toTuple), [](const Glib::VariantBase &parameter) {
NotificationId* Core::Sandbox::Instance().customEnterFromEventLoop([&] {
>; try {
const auto &app = Core::App();
const auto notificationIdVariantType = [] { app.notifications().manager().notificationReplied(
try { NotificationId::FromTuple(
return base::Platform::MakeGlibVariant( base::Platform::GlibVariantCast<
NotificationId().toTuple()).get_type(); NotificationIdTuple
} catch (...) { >(parameter)),
return Glib::VariantType(); {});
} } catch (...) {
}(); }
app->add_action_with_parameter(
"notification-reply",
notificationIdVariantType,
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
const auto &notifications = app.notifications();
notifications.manager().notificationActivated(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)));
} catch (...) {
}
});
}); });
});
app->add_action_with_parameter( app->hold();
"notification-mark-as-read", app->run(0, nullptr);
notificationIdVariantType, });
[](const Glib::VariantBase &parameter) {
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
try {
const auto &app = Core::App();
const auto &notifications = app.notifications();
notifications.manager().notificationReplied(
NotificationId::FromTuple(
base::Platform::GlibVariantCast<
NotificationIdTuple
>(parameter)),
{});
} catch (...) {
}
});
});
app->hold();
app->run(0, nullptr);
});
}
} }
bool GenerateDesktopFile( bool GenerateDesktopFile(

View file

@ -1,25 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/platform_specific.h"
#include "base/options.h"
namespace Platform {
const char kOptionGApplication[] = "gapplication";
base::options::toggle OptionGApplication({
.id = kOptionGApplication,
.name = "GApplication",
.description = "Force enable GLib's GApplication and GNotification."
" When disabled, autodetect is used.",
.scope = base::options::linux,
.restartRequired = true,
});
} // namespace Platform

View file

@ -7,20 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
namespace base::options {
template <typename Type>
class option;
using toggle = option<bool>;
} // namespace base::options
namespace Platform { namespace Platform {
extern const char kOptionGApplication[];
extern base::options::toggle OptionGApplication;
void start(); void start();
void finish(); void finish();

View file

@ -17,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/options.h" #include "base/options.h"
#include "core/application.h" #include "core/application.h"
#include "core/launcher.h" #include "core/launcher.h"
#include "platform/platform_specific.h"
#include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_panel.h"
#include "dialogs/dialogs_inner_widget.h" #include "dialogs/dialogs_inner_widget.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -27,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_peer_menu.h" #include "window/window_peer_menu.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/notifications_manager.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
@ -148,7 +148,7 @@ void SetupExperimental(
addToggle(Settings::kOptionMonoSettingsIcons); addToggle(Settings::kOptionMonoSettingsIcons);
addToggle(Webview::kOptionWebviewDebugEnabled); addToggle(Webview::kOptionWebviewDebugEnabled);
addToggle(kOptionAutoScrollInactiveChat); addToggle(kOptionAutoScrollInactiveChat);
addToggle(Platform::kOptionGApplication); addToggle(Windows::Notifications::kOptionGNotification);
} }
} // namespace } // namespace

View file

@ -77,6 +77,17 @@ QString TextWithPermanentSpoiler(const TextWithEntities &textWithEntities) {
} // namespace } // namespace
const char kOptionGNotification[] = "gnotification";
base::options::toggle OptionGNotification({
.id = kOptionGNotification,
.name = "GNotification",
.description = "Force enable GLib's GNotification."
" When disabled, autodetect is used.",
.scope = base::options::linux,
.restartRequired = true,
});
struct System::Waiter { struct System::Waiter {
NotificationInHistoryKey key; NotificationInHistoryKey key;
UserData *reactionSender = nullptr; UserData *reactionSender = nullptr;

View file

@ -74,8 +74,20 @@ struct custom_is_fast_copy_type<Window::Notifications::ChangeType> : std::true_t
} // namespace base } // namespace base
namespace base::options {
template <typename Type>
class option;
using toggle = option<bool>;
} // namespace base::options
namespace Window::Notifications { namespace Window::Notifications {
extern const char kOptionGNotification[];
extern base::options::toggle OptionGNotification;
class Manager; class Manager;
class System final { class System final {