diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 7c5664d29..0c7640276 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1137,7 +1137,6 @@ PRIVATE platform/platform_integration.h platform/platform_main_window.h platform/platform_notifications_manager.h - platform/platform_specific.cpp platform/platform_specific.h platform/platform_tray.h platform/platform_window_title.h diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 880efc840..53b47b185 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #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 "platform/platform_specific.h" #include "core/application.h" #include "core/sandbox.h" #include "core/core_settings.h" @@ -319,6 +318,18 @@ Glib::ustring GetImageKey(const QVersionNumber &specificationVersion) { 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 { public: using NotificationId = Window::Notifications::Manager::NotificationId; @@ -378,7 +389,7 @@ NotificationData::NotificationData( NotificationId id) : _manager(manager) , _id(id) -, _application(Gio::Application::get_default()) { +, _application(UseGNotification() ? Gio::Application::get_default() : {}) { } bool NotificationData::init( @@ -811,13 +822,13 @@ bool WaitForInputForCustom() { } bool Supported() { - return ServiceRegistered || Gio::Application::get_default(); + return ServiceRegistered || UseGNotification(); } bool Enforced() { // Wayland doesn't support positioning // and custom notifications don't work here - return IsWayland() || OptionGApplication.value(); + return IsWayland() || Window::Notifications::OptionGNotification.value(); } bool ByDefault() { @@ -841,7 +852,7 @@ bool ByDefault() { } void Create(Window::Notifications::System *system) { - static auto ServiceWatcher = CreateServiceWatcher(); + static const auto ServiceWatcher = CreateServiceWatcher(); const auto managerSetter = [=] { 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(2); const auto oneReady = [=] { if (!--*counter) { - // GApplication may be created while the reply is received - if (Gio::Application::get_default()) { - Core::App().notifications().createManager(); - return; - } managerSetter(); } }; // snap doesn't allow access when the daemon is not running :( StartServiceAsync([=] { - // GApplication may be created while the reply is received - if (Gio::Application::get_default()) { - Core::App().notifications().createManager(); - return; - } - ServiceRegistered = GetServiceRegistered(); if (!ServiceRegistered) { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index b71ab2794..0d90b7dce 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -240,187 +240,140 @@ bool PortalAutostart(bool start, bool silent) { } void LaunchGApplication() { - const auto connection = [] { - try { - return Gio::DBus::Connection::get_sync( - Gio::DBus::BusType::SESSION); - } catch (...) { - return Glib::RefPtr(); - } - }(); + Glib::signal_idle().connect_once([] { + const auto appId = QGuiApplication::desktopFileName() + .chopped(8) + .toStdString(); - using namespace base::Platform::DBus; - const auto activatableNames = [&] { - try { - if (connection) { - return ListActivatableNames(connection); - } - } catch (...) { - } + 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))); - return std::vector(); - }(); + app->signal_startup().connect([=] { + // GNotification + InvokeQueued(qApp, [] { + Core::App().notifications().createManager(); + }); - const auto freedesktopNotifications = [&] { - try { - if (connection && NameHasOwner( - connection, - "org.freedesktop.Notifications")) { - return true; - } - } catch (...) { - } + QEventLoop().exec(); + app->quit(); + }, true); - if (ranges::contains( - activatableNames, - "org.freedesktop.Notifications", - &Glib::ustring::raw)) { - return true; - } + app->signal_activate().connect([] { + Core::Sandbox::Instance().customEnterFromEventLoop([] { + const auto window = Core::IsAppLaunched() + ? Core::App().primaryWindow() + : nullptr; + if (window) { + window->activate(); + } + }); + }, true); - return false; - }; - - if (OptionGApplication.value() - || (KSandbox::isFlatpak() && !freedesktopNotifications())) { - 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([] { - const auto window = Core::IsAppLaunched() - ? Core::App().primaryWindow() - : nullptr; - if (window) { - window->activate(); + app->signal_open().connect([]( + const Gio::Application::type_vec_files &files, + const Glib::ustring &hint) { + Core::Sandbox::Instance().customEnterFromEventLoop([&] { + for (const auto &file : files) { + if (file->get_uri_scheme() == "file") { + gSendPaths.append( + QString::fromStdString(file->get_path())); + continue; } - }); - }, true); + const auto url = QString::fromStdString(file->get_uri()); + 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([]( - const Gio::Application::type_vec_files &files, - const Glib::ustring &hint) { + if (!cSendPaths().isEmpty()) { + Core::App().checkSendPaths(); + } + }); + }, 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 ¶meter) { Core::Sandbox::Instance().customEnterFromEventLoop([&] { - for (const auto &file : files) { - if (file->get_uri_scheme() == "file") { - gSendPaths.append( - QString::fromStdString(file->get_path())); - continue; - } - const auto url = QString::fromStdString( - file->get_uri()); - 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(); + try { + const auto &app = Core::App(); + app.notifications().manager().notificationActivated( + NotificationId::FromTuple( + base::Platform::GlibVariantCast< + NotificationIdTuple + >(parameter))); + } catch (...) { } - - if (!cSendPaths().isEmpty()) { - Core::App().checkSendPaths(); - } - }); - }, 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 ¶meter) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - try { - const auto &app = Core::App(); - const auto ¬ifications = app.notifications(); - 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->add_action_with_parameter( - "notification-mark-as-read", - notificationIdVariantType, - [](const Glib::VariantBase ¶meter) { - Core::Sandbox::Instance().customEnterFromEventLoop([&] { - try { - const auto &app = Core::App(); - const auto ¬ifications = app.notifications(); - notifications.manager().notificationReplied( - NotificationId::FromTuple( - base::Platform::GlibVariantCast< - NotificationIdTuple - >(parameter)), - {}); - } catch (...) { - } - }); - }); - - app->hold(); - app->run(0, nullptr); - }); - } + app->hold(); + app->run(0, nullptr); + }); } bool GenerateDesktopFile( diff --git a/Telegram/SourceFiles/platform/platform_specific.cpp b/Telegram/SourceFiles/platform/platform_specific.cpp deleted file mode 100644 index b0387f82a..000000000 --- a/Telegram/SourceFiles/platform/platform_specific.cpp +++ /dev/null @@ -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 diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 725ecdb7b..dc863b179 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -7,20 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -namespace base::options { - -template -class option; - -using toggle = option; - -} // namespace base::options - namespace Platform { -extern const char kOptionGApplication[]; -extern base::options::toggle OptionGApplication; - void start(); void finish(); diff --git a/Telegram/SourceFiles/settings/settings_experimental.cpp b/Telegram/SourceFiles/settings/settings_experimental.cpp index 9731130dc..209260059 100644 --- a/Telegram/SourceFiles/settings/settings_experimental.cpp +++ b/Telegram/SourceFiles/settings/settings_experimental.cpp @@ -17,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/options.h" #include "core/application.h" #include "core/launcher.h" -#include "platform/platform_specific.h" #include "chat_helpers/tabbed_panel.h" #include "dialogs/dialogs_inner_widget.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_session_controller.h" #include "window/window_controller.h" +#include "window/notifications_manager.h" #include "settings/settings_common.h" #include "storage/localimageloader.h" #include "styles/style_settings.h" @@ -148,7 +148,7 @@ void SetupExperimental( addToggle(Settings::kOptionMonoSettingsIcons); addToggle(Webview::kOptionWebviewDebugEnabled); addToggle(kOptionAutoScrollInactiveChat); - addToggle(Platform::kOptionGApplication); + addToggle(Windows::Notifications::kOptionGNotification); } } // namespace diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index 3c7e1e2d3..665b2d754 100644 --- a/Telegram/SourceFiles/window/notifications_manager.cpp +++ b/Telegram/SourceFiles/window/notifications_manager.cpp @@ -77,6 +77,17 @@ QString TextWithPermanentSpoiler(const TextWithEntities &textWithEntities) { } // 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 { NotificationInHistoryKey key; UserData *reactionSender = nullptr; diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h index c33048fcd..4ea6308f9 100644 --- a/Telegram/SourceFiles/window/notifications_manager.h +++ b/Telegram/SourceFiles/window/notifications_manager.h @@ -74,8 +74,20 @@ struct custom_is_fast_copy_type : std::true_t } // namespace base +namespace base::options { + +template +class option; + +using toggle = option; + +} // namespace base::options + namespace Window::Notifications { +extern const char kOptionGNotification[]; +extern base::options::toggle OptionGNotification; + class Manager; class System final {