From 093fcc3821338cbaa69f2f48a44c024e5a1c7986 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sun, 4 Oct 2020 13:33:24 +0400 Subject: [PATCH] Subscribe to StatusNotifierHostRegistered signal --- .../platform/linux/main_window_linux.cpp | 121 +++++++++++++----- .../platform/linux/main_window_linux.h | 24 +++- .../platform/linux/specific_linux.cpp | 10 +- .../platform/linux/specific_linux.h | 1 - 4 files changed, 113 insertions(+), 43 deletions(-) diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index 593d4b6531..1c3171c571 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -39,6 +39,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include + +extern "C" { +#undef signals +#include +#define signals public +} // extern "C" #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION #include @@ -51,10 +57,13 @@ constexpr auto kForcePanelIcon = "TDESKTOP_FORCE_PANEL_ICON"_cs; constexpr auto kPanelTrayIconName = "telegram-panel"_cs; constexpr auto kMutePanelTrayIconName = "telegram-mute-panel"_cs; constexpr auto kAttentionPanelTrayIconName = "telegram-attention-panel"_cs; -constexpr auto kSNIWatcherService = "org.kde.StatusNotifierWatcher"_cs; constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs; constexpr auto kTrayIconFilename = "tdesktop-trayicon-XXXXXX.png"_cs; +constexpr auto kSNIWatcherService = "org.kde.StatusNotifierWatcher"_cs; +constexpr auto kSNIWatcherObjectPath = "/StatusNotifierWatcher"_cs; +constexpr auto kSNIWatcherInterface = kSNIWatcherService; + constexpr auto kAppMenuService = "com.canonical.AppMenu.Registrar"_cs; constexpr auto kAppMenuObjectPath = "/com/canonical/AppMenu/Registrar"_cs; constexpr auto kAppMenuInterface = kAppMenuService; @@ -65,9 +74,6 @@ base::flat_map TrayIconImageBack; QIcon TrayIcon; QString TrayIconThemeName, TrayIconName; -bool SNIAvailable = false; -bool AppMenuSupported = false; - QString GetPanelIconName(int counter, bool muted) { return (counter > 0) ? (muted @@ -222,7 +228,13 @@ QIcon TrayIconGen(int counter, bool muted) { iconImage.height() - layer.height() - 1, layer); } else { - App::wnd()->placeSmallCounter(iconImage, 16, counter, bg, QPoint(), fg); + App::wnd()->placeSmallCounter( + iconImage, + 16, + counter, + bg, + QPoint(), + fg); } } @@ -312,7 +324,7 @@ bool IsSNIAvailable() { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION auto message = QDBusMessage::createMethodCall( kSNIWatcherService.utf16(), - qsl("/StatusNotifierWatcher"), + kSNIWatcherObjectPath.utf16(), kPropertiesInterface.utf16(), qsl("Get")); @@ -416,15 +428,26 @@ MainWindow::MainWindow(not_null controller) } void MainWindow::initHook() { - SNIAvailable = IsSNIAvailable(); - - const auto trayAvailable = SNIAvailable - || QSystemTrayIcon::isSystemTrayAvailable(); - - LOG(("System tray available: %1").arg(Logs::b(trayAvailable))); - Platform::SetTrayIconSupported(trayAvailable); + _sniAvailable = IsSNIAvailable(); + LOG(("System tray available: %1").arg(Logs::b(trayAvailable()))); #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION + _sniDBusProxy = g_dbus_proxy_new_for_bus_sync( + G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + nullptr, + kSNIWatcherService.utf8(), + kSNIWatcherObjectPath.utf8(), + kSNIWatcherInterface.utf8(), + nullptr, + nullptr); + + g_signal_connect( + _sniDBusProxy, + "g-signal", + G_CALLBACK(sniSignalEmitted), + this); + auto sniWatcher = new QDBusServiceWatcher( kSNIWatcherService.utf16(), QDBusConnection::sessionBus(), @@ -442,7 +465,7 @@ void MainWindow::initHook() { handleSNIOwnerChanged(service, oldOwner, newOwner); }); - AppMenuSupported = IsAppMenuSupported(); + _appMenuSupported = IsAppMenuSupported(); auto appMenuWatcher = new QDBusServiceWatcher( kAppMenuService.utf16(), @@ -461,7 +484,7 @@ void MainWindow::initHook() { handleAppMenuOwnerChanged(service, oldOwner, newOwner); }); - if (AppMenuSupported) { + if (_appMenuSupported) { LOG(("Using D-Bus global menu.")); } else { LOG(("Not using D-Bus global menu.")); @@ -484,7 +507,7 @@ void MainWindow::initHook() { bool MainWindow::hasTrayIcon() const { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION - return trayIcon || (SNIAvailable && _sniTrayIcon); + return trayIcon || (_sniAvailable && _sniTrayIcon); #else return trayIcon; #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION @@ -564,22 +587,50 @@ void MainWindow::attachToSNITrayIcon() { updateTrayMenu(); } -void MainWindow::handleSNIOwnerChanged( - const QString &service, - const QString &oldOwner, - const QString &newOwner) { - SNIAvailable = !newOwner.isEmpty(); +void MainWindow::sniSignalEmitted( + GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + MainWindow *window) { + if(signal_name == qstr("StatusNotifierHostRegistered")) { + window->handleSNIHostRegistered(); + } +} - const auto trayAvailable = SNIAvailable - || QSystemTrayIcon::isSystemTrayAvailable(); +void MainWindow::handleSNIHostRegistered() { + if (_sniAvailable) { + return; + } - Platform::SetTrayIconSupported(trayAvailable); + _sniAvailable = true; if (Global::WorkMode().value() == dbiwmWindowOnly) { return; } - if (oldOwner.isEmpty() && !newOwner.isEmpty()) { + LOG(("Switching to SNI tray icon...")); + + if (trayIcon) { + trayIcon->setContextMenu(0); + trayIcon->deleteLater(); + } + trayIcon = nullptr; + + psSetupTrayIcon(); +} + +void MainWindow::handleSNIOwnerChanged( + const QString &service, + const QString &oldOwner, + const QString &newOwner) { + _sniAvailable = IsSNIAvailable(); + + if (Global::WorkMode().value() == dbiwmWindowOnly) { + return; + } + + if (oldOwner.isEmpty() && !newOwner.isEmpty() && _sniAvailable) { LOG(("Switching to SNI tray icon...")); } else if (!oldOwner.isEmpty() && newOwner.isEmpty()) { LOG(("Switching to Qt tray icon...")); @@ -593,7 +644,7 @@ void MainWindow::handleSNIOwnerChanged( } trayIcon = nullptr; - if (trayAvailable) { + if (trayAvailable()) { psSetupTrayIcon(); } else { LOG(("System tray is not available.")); @@ -605,14 +656,14 @@ void MainWindow::handleAppMenuOwnerChanged( const QString &oldOwner, const QString &newOwner) { if (oldOwner.isEmpty() && !newOwner.isEmpty()) { - AppMenuSupported = true; + _appMenuSupported = true; LOG(("Using D-Bus global menu.")); } else if (!oldOwner.isEmpty() && newOwner.isEmpty()) { - AppMenuSupported = false; + _appMenuSupported = false; LOG(("Not using D-Bus global menu.")); } - if (AppMenuSupported && !_mainMenuPath.path().isEmpty()) { + if (_appMenuSupported && !_mainMenuPath.path().isEmpty()) { RegisterAppMenu(winId(), _mainMenuPath); } else { UnregisterAppMenu(winId()); @@ -624,7 +675,7 @@ void MainWindow::psSetupTrayIcon() { const auto counter = Core::App().unreadBadge(); const auto muted = Core::App().unreadBadgeMuted(); - if (SNIAvailable) { + if (_sniAvailable) { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION LOG(("Using SNI tray icon.")); if (!_sniTrayIcon) { @@ -654,7 +705,7 @@ void MainWindow::psSetupTrayIcon() { } void MainWindow::workmodeUpdated(DBIWorkMode mode) { - if (!Platform::TrayIconSupported()) { + if (!trayAvailable()) { return; } else if (mode == dbiwmWindowOnly) { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION @@ -953,7 +1004,7 @@ void MainWindow::createGlobalMenu() { _mainMenuPath.path(), psMainMenu); - if (AppMenuSupported) { + if (_appMenuSupported) { RegisterAppMenu(winId(), _mainMenuPath); } @@ -1074,7 +1125,7 @@ void MainWindow::updateGlobalMenuHook() { } void MainWindow::handleVisibleChangedHook(bool visible) { - if (AppMenuSupported && !_mainMenuPath.path().isEmpty()) { + if (_appMenuSupported && !_mainMenuPath.path().isEmpty()) { if (visible) { RegisterAppMenu(winId(), _mainMenuPath); } else { @@ -1089,12 +1140,14 @@ MainWindow::~MainWindow() { #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION delete _sniTrayIcon; - if (AppMenuSupported) { + if (_appMenuSupported) { UnregisterAppMenu(winId()); } delete _mainMenuExporter; delete psMainMenu; + + g_object_unref(_sniDBusProxy); #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION delete _trayIconMenuXEmbed; diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 143c472346..a390893265 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -16,7 +16,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include -#endif + +typedef char gchar; +typedef struct _GVariant GVariant; +typedef struct _GDBusProxy GDBusProxy; +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION namespace Platform { @@ -33,6 +37,14 @@ public: void psShowTrayMenu(); + bool trayAvailable() { + return _sniAvailable || QSystemTrayIcon::isSystemTrayAvailable(); + } + +#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION + void handleSNIHostRegistered(); +#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION + static void LibsLoaded(); ~MainWindow(); @@ -64,6 +76,7 @@ protected: style::color color) = 0; private: + bool _sniAvailable = false; Ui::PopupMenu *_trayIconMenuXEmbed = nullptr; void updateIconCounters(); @@ -71,8 +84,10 @@ private: #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION StatusNotifierItem *_sniTrayIcon = nullptr; + GDBusProxy *_sniDBusProxy = nullptr; std::unique_ptr _trayIconFile = nullptr; + bool _appMenuSupported = false; DBusMenuExporter *_mainMenuExporter = nullptr; QDBusObjectPath _mainMenuPath; @@ -124,6 +139,13 @@ private: void psLinuxStrikeOut(); void psLinuxMonospace(); void psLinuxClearFormat(); + + static void sniSignalEmitted( + GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + MainWindow *window); #endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION }; diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp index 85347bf554..7f28ad56a0 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp @@ -85,8 +85,6 @@ constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs; QStringList PlatformThemes; -bool IsTrayIconSupported = false; - #ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION void PortalAutostart(bool autostart, bool silent = false) { if (cExeName().isEmpty()) { @@ -1066,11 +1064,9 @@ bool AutostartSupported() { } bool TrayIconSupported() { - return IsTrayIconSupported; -} - -void SetTrayIconSupported(bool supported) { - IsTrayIconSupported = supported; + return App::wnd() + ? App::wnd()->trayAvailable() + : false; } bool StartSystemMove(QWindow *window) { diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index e34cb9b35f..1b4cdc0d50 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -42,7 +42,6 @@ QString GetIconName(); inline void IgnoreApplicationActivationRightNow() { } -void SetTrayIconSupported(bool supported); void InstallMainDesktopFile(); } // namespace Platform