Subscribe to StatusNotifierHostRegistered signal

This commit is contained in:
Ilya Fedin 2020-10-04 13:33:24 +04:00 committed by John Preston
parent 6f89598a7b
commit 093fcc3821
4 changed files with 113 additions and 43 deletions

View File

@ -39,6 +39,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtDBus/QDBusReply>
#include <QtDBus/QDBusError>
#include <QtDBus/QDBusMetaType>
extern "C" {
#undef signals
#include <gio/gio.h>
#define signals public
} // extern "C"
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
#include <glib.h>
@ -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<int, QImage> 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<Window::Controller*> 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;

View File

@ -16,7 +16,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QTemporaryFile>
#include <QtDBus/QDBusObjectPath>
#include <dbusmenuexporter.h>
#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<QTemporaryFile> _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
};

View File

@ -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) {

View File

@ -42,7 +42,6 @@ QString GetIconName();
inline void IgnoreApplicationActivationRightNow() {
}
void SetTrayIconSupported(bool supported);
void InstallMainDesktopFile();
} // namespace Platform