diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 931cdafd81..4dc5cec132 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -43,7 +43,7 @@ constexpr auto kImageDataType = "(iiibii@ay)"_cs; constexpr auto kNotifyArgsType = "(susssasa{sv}i)"_cs; bool ServiceRegistered = false; -bool InhibitedNotSupported = false; +bool InhibitionSupported = false; std::vector CurrentServerInformation; QStringList CurrentCapabilities; @@ -118,10 +118,42 @@ QStringList GetCapabilities() { return {}; } +bool GetInhibitionSupported() { + auto message = QDBusMessage::createMethodCall( + kService.utf16(), + kObjectPath.utf16(), + kPropertiesInterface.utf16(), + qsl("Get")); + + message.setArguments({ + qsl("org.freedesktop.Notifications"), + qsl("Inhibited") + }); + + // We may be launched earlier than notification daemon + while (true) { + const QDBusError error = QDBusConnection::sessionBus().call(message); + + if (!error.isValid()) { + return true; + } else if (error.type() == QDBusError::InvalidArgs) { + break; + } + + LOG(("Native notification error: %1").arg(error.message())); + + if (error.type() != QDBusError::NoReply) { + break; + } + } + + return false; +} + bool Inhibited() { if (!Supported() || !CurrentCapabilities.contains(qsl("inhibitions")) - || InhibitedNotSupported) { + || !InhibitionSupported) { return false; } @@ -139,26 +171,36 @@ bool Inhibited() { const QDBusReply reply = QDBusConnection::sessionBus().call( message); - static const auto NotSupportedErrors = { - QDBusError::ServiceUnknown, - QDBusError::InvalidArgs, - }; - if (reply.isValid()) { return reply.value().toBool(); - } else if (ranges::contains(NotSupportedErrors, reply.error().type())) { - InhibitedNotSupported = true; - } else { - if (reply.error().type() == QDBusError::AccessDenied) { - InhibitedNotSupported = true; - } - - LOG(("Native notification error: %1").arg(reply.error().message())); } + LOG(("Native notification error: %1").arg(reply.error().message())); return false; } +bool IsQualifiedDaemon() { + // A list of capabilities that offer feature parity + // with custom notifications + static const auto NeededCapabilities = { + // To show message content + qsl("body"), + // To make the sender name bold + qsl("body-markup"), + // To have buttons on notifications + qsl("actions"), + // To have quick reply + qsl("inline-reply"), + // To not to play sound with Don't Disturb activated + // (no, using sound capability is not a way) + qsl("inhibitions"), + }; + + return ranges::all_of(NeededCapabilities, [&](const auto &capability) { + return CurrentCapabilities.contains(capability); + }) && InhibitionSupported; +} + QVersionNumber ParseSpecificationVersion( const std::vector &serverInformation) { if (serverInformation.size() >= 4) { @@ -605,21 +647,28 @@ bool Supported() { return ServiceRegistered; } +bool Enforced() { + // Wayland doesn't support positioning + // and custom notifications don't work here + return IsQualifiedDaemon() || IsWayland(); +} + std::unique_ptr Create( Window::Notifications::System *system) { ServiceRegistered = GetServiceRegistered(); - InhibitedNotSupported = false; if (Supported()) { CurrentServerInformation = GetServerInformation(); CurrentCapabilities = GetCapabilities(); + InhibitionSupported = GetInhibitionSupported(); } else { CurrentServerInformation = {}; CurrentCapabilities = QStringList{}; + InhibitionSupported = false; } if ((Core::App().settings().nativeNotifications() && Supported()) - || IsWayland()) { + || Enforced()) { return std::make_unique(system); } diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux_dummy.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux_dummy.cpp index 44ef96fa12..cc39a3a7b3 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux_dummy.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux_dummy.cpp @@ -27,9 +27,15 @@ bool Supported() { return false; } +bool Enforced() { + // Wayland doesn't support positioning + // and custom notifications don't work here + return IsWayland(); +} + std::unique_ptr Create( Window::Notifications::System *system) { - if (IsWayland()) { + if (Enforced()) { return std::make_unique(system); } diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm index 827954675c..88d0860663 100644 --- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm +++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm @@ -162,6 +162,10 @@ bool Supported() { return Platform::IsMac10_8OrGreater(); } +bool Enforced() { + return Supported(); +} + std::unique_ptr Create(Window::Notifications::System *system) { if (Supported()) { return std::make_unique(system); diff --git a/Telegram/SourceFiles/platform/platform_notifications_manager.h b/Telegram/SourceFiles/platform/platform_notifications_manager.h index 4afeadf97c..cf8201ec7b 100644 --- a/Telegram/SourceFiles/platform/platform_notifications_manager.h +++ b/Telegram/SourceFiles/platform/platform_notifications_manager.h @@ -17,6 +17,7 @@ namespace Notifications { [[nodiscard]] bool SkipFlashBounce(); [[nodiscard]] bool Supported(); +[[nodiscard]] bool Enforced(); [[nodiscard]] std::unique_ptr Create( Window::Notifications::System *system); diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp index 5fd6c591f8..ff631e9547 100644 --- a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp +++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp @@ -325,6 +325,10 @@ bool Supported() { return false; } +bool Enforced() { + return false; +} + std::unique_ptr Create(Window::Notifications::System *system) { #ifndef __MINGW32__ if (Core::App().settings().nativeNotifications() && Supported()) { diff --git a/Telegram/SourceFiles/settings/settings_notifications.cpp b/Telegram/SourceFiles/settings/settings_notifications.cpp index 19ce0db2b2..95bb969587 100644 --- a/Telegram/SourceFiles/settings/settings_notifications.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications.cpp @@ -676,14 +676,13 @@ void SetupNotificationsContent( }, joined->lifetime()); const auto nativeText = [&] { - if (!Platform::Notifications::Supported()) { + if (!Platform::Notifications::Supported() + || Platform::Notifications::Enforced()) { return QString(); } else if (Platform::IsWindows()) { return tr::lng_settings_use_windows(tr::now); - } else if (Platform::IsLinux() && !Platform::IsWayland()) { - return tr::lng_settings_use_native_notifications(tr::now); } - return QString(); + return tr::lng_settings_use_native_notifications(tr::now); }(); const auto native = [&]() -> Ui::Checkbox* { if (nativeText.isEmpty()) { @@ -697,8 +696,7 @@ void SetupNotificationsContent( return addCheckbox(nativeText, settings.nativeNotifications()); }(); - const auto advancedSlide = !Platform::IsMac10_8OrGreater() - && !Platform::IsWayland() + const auto advancedSlide = !Platform::Notifications::Enforced() ? container->add( object_ptr>( container,