From d2e3c01c11d42b65089266ea0d9c819703df52c7 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Tue, 26 Jul 2022 05:32:33 +0400 Subject: [PATCH] Get linux notification inhibition state asynchronously This is the last sync request in the D-Bus notifications --- .../linux/notifications_manager_linux.cpp | 142 ++++++++++-------- 1 file changed, 79 insertions(+), 63 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index ab5d1c1466..8b2d37f9ee 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -46,7 +46,6 @@ struct ServerInformation { }; bool ServiceRegistered = false; -bool InhibitionSupported = false; std::optional CurrentServerInformation; QStringList CurrentCapabilities; @@ -267,7 +266,13 @@ void GetCapabilities(Fn callback) { crl::on_main([=] { callback({}); }); } -void GetInhibitionSupported(Fn callback) { +void GetInhibited(Fn callback) { + if (!Supported() + || !CurrentCapabilities.contains(qsl("inhibitions"))) { + crl::on_main([=] { callback(false); }); + return; + } + try { const auto connection = Gio::DBus::Connection::get_sync( Gio::DBus::BusType::BUS_TYPE_SESSION); @@ -282,24 +287,23 @@ void GetInhibitionSupported(Fn callback) { }), [=](const Glib::RefPtr &result) { try { - connection->call_finish(result); + auto reply = connection->call_finish(result); + + const auto value = GlibVariantCast( + GlibVariantCast( + reply.get_child(0))); crl::on_main([=] { - callback(true); + callback(value); }); return; } catch (const Glib::Error &e) { - static const auto DontLogErrors = { - "org.freedesktop.DBus.Error.InvalidArgs", - "org.freedesktop.DBus.Error.UnknownMethod", - }; - - const auto errorName = Gio::DBus::ErrorUtils::get_remote_error(e); - if (!ranges::contains(DontLogErrors, errorName)) { - LOG(("Native Notification Error: %1").arg( - QString::fromStdString(e.what()))); - } + LOG(("Native Notification Error: %1").arg( + QString::fromStdString(e.what()))); + } catch (const std::exception &e) { + LOG(("Native Notification Error: %1").arg( + QString::fromStdString(e.what()))); } crl::on_main([=] { callback(false); }); @@ -315,45 +319,6 @@ void GetInhibitionSupported(Fn callback) { crl::on_main([=] { callback(false); }); } -bool Inhibited() { - if (!Supported() - || !CurrentCapabilities.contains(qsl("inhibitions")) - || !InhibitionSupported) { - return false; - } - - try { - const auto connection = Gio::DBus::Connection::get_sync( - Gio::DBus::BusType::BUS_TYPE_SESSION); - - // a hack for snap's activation restriction - DBus::StartServiceByName( - connection, - std::string(kService)); - - auto reply = connection->call_sync( - std::string(kObjectPath), - std::string(kPropertiesInterface), - "Get", - MakeGlibVariant(std::tuple{ - Glib::ustring(std::string(kInterface)), - Glib::ustring("Inhibited"), - }), - std::string(kService)); - - return GlibVariantCast( - GlibVariantCast(reply.get_child(0))); - } catch (const Glib::Error &e) { - LOG(("Native Notification Error: %1").arg( - QString::fromStdString(e.what()))); - } catch (const std::exception &e) { - LOG(("Native Notification Error: %1").arg( - QString::fromStdString(e.what()))); - } - - return false; -} - bool IsQualifiedDaemon() { // A list of capabilities that offer feature parity // with custom notifications @@ -373,7 +338,7 @@ bool IsQualifiedDaemon() { return ranges::all_of(NeededCapabilities, [&](const auto &capability) { return CurrentCapabilities.contains(capability); - }) && InhibitionSupported; + }); } ServerInformation CurrentServerInformationValue() { @@ -820,7 +785,7 @@ void Create(Window::Notifications::System *system) { } }; - const auto counter = std::make_shared(3); + const auto counter = std::make_shared(2); const auto oneReady = [=] { if (!--*counter) { managerSetter(); @@ -833,7 +798,6 @@ void Create(Window::Notifications::System *system) { if (!ServiceRegistered) { CurrentServerInformation = std::nullopt; CurrentCapabilities = QStringList{}; - InhibitionSupported = false; managerSetter(); return; } @@ -847,11 +811,6 @@ void Create(Window::Notifications::System *system) { CurrentCapabilities = result; oneReady(); }); - - GetInhibitionSupported([=](bool result) { - InhibitionSupported = result; - oneReady(); - }); }; // There are some asserts that manager is not nullptr, @@ -884,6 +843,10 @@ public: void clearFromSession(not_null session); void clearNotification(NotificationId id); + bool inhibited() { + return _inhibited; + } + ~Private(); private: @@ -895,6 +858,10 @@ private: Window::Notifications::CachedUserpics _cachedUserpics; + Glib::RefPtr _dbusConnection; + bool _inhibited = false; + uint _inhibitedSignalId = 0; + }; Manager::Private::Private(not_null manager, Type type) @@ -925,6 +892,49 @@ Manager::Private::Private(not_null manager, Type type) LOG(("Notification daemon capabilities: %1") .arg(capabilities.join(", "))); } + + try { + _dbusConnection = Gio::DBus::Connection::get_sync( + Gio::DBus::BusType::BUS_TYPE_SESSION); + } catch (const Glib::Error &e) { + LOG(("Native Notification Error: %1").arg( + QString::fromStdString(e.what()))); + return; + } + + GetInhibited([=](bool result) { + _inhibited = result; + }); + + _inhibitedSignalId = _dbusConnection->signal_subscribe( + [=]( + const Glib::RefPtr &connection, + const Glib::ustring &sender_name, + const Glib::ustring &object_path, + const Glib::ustring &interface_name, + const Glib::ustring &signal_name, + Glib::VariantContainerBase parameters) { + try { + const auto interface = GlibVariantCast( + parameters.get_child(0)); + + if (interface != std::string(kInterface)) { + return; + } + + _inhibited = GlibVariantCast( + GlibVariantCast< + std::map + >(parameters.get_child(1)).at("Inhibited")); + } catch (const std::exception &e) { + LOG(("Native Notification Error: %1").arg( + QString::fromStdString(e.what()))); + } + }, + std::string(kService), + std::string(kPropertiesInterface), + "PropertiesChanged", + std::string(kObjectPath)); } void Manager::Private::showNotification( @@ -1074,6 +1084,12 @@ void Manager::Private::clearNotification(NotificationId id) { Manager::Private::~Private() { clearAll(); + + if (_dbusConnection) { + if (_inhibitedSignalId != 0) { + _dbusConnection->signal_unsubscribe(_inhibitedSignalId); + } + } } Manager::Manager(not_null system) @@ -1122,7 +1138,7 @@ void Manager::doClearFromSession(not_null session) { } bool Manager::doSkipAudio() const { - return Inhibited(); + return _private->inhibited(); } bool Manager::doSkipToast() const { @@ -1130,7 +1146,7 @@ bool Manager::doSkipToast() const { } bool Manager::doSkipFlashBounce() const { - return Inhibited(); + return _private->inhibited(); } } // namespace Notifications