1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtGui/qtgui-config.h>
5
6#include <QDBusMessage>
7#include <QDBusInterface>
8#include <QDBusServiceWatcher>
9#include <QDBusConnectionInterface>
10#include <QDebug>
11#include <QCoreApplication>
12
13#ifndef QT_NO_SYSTEMTRAYICON
14#include <private/qdbustrayicon_p.h>
15#endif
16#include <private/qdbusmenuconnection_p.h>
17#include <private/qdbusmenuadaptor_p.h>
18#include <private/qdbusplatformmenu_p.h>
19
20QT_BEGIN_NAMESPACE
21
22using namespace Qt::StringLiterals;
23
24Q_DECLARE_LOGGING_CATEGORY(qLcMenu)
25
26const QString StatusNotifierWatcherService = "org.kde.StatusNotifierWatcher"_L1;
27const QString StatusNotifierWatcherPath = "/StatusNotifierWatcher"_L1;
28const QString StatusNotifierItemPath = "/StatusNotifierItem"_L1;
29const QString MenuBarPath = "/MenuBar"_L1;
30
31/*!
32 \class QDBusMenuConnection
33 \internal
34 A D-Bus connection which is used for both menu and tray icon services.
35 Connects to the session bus and registers with the respective watcher services.
36*/
37QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &serviceName)
38 : QObject(parent)
39 , m_serviceName(serviceName)
40 , m_connection(serviceName.isNull() ? QDBusConnection::sessionBus()
41 : QDBusConnection::connectToBus(type: QDBusConnection::SessionBus, name: serviceName))
42 , m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this))
43 , m_watcherRegistered(false)
44{
45#ifndef QT_NO_SYSTEMTRAYICON
46 // Start monitoring if any known tray-related services are registered.
47 if (m_connection.interface()->isServiceRegistered(serviceName: StatusNotifierWatcherService))
48 m_watcherRegistered = true;
49 else
50 qCDebug(qLcMenu) << "failed to find service" << StatusNotifierWatcherService;
51#endif
52}
53
54QDBusMenuConnection::~QDBusMenuConnection()
55{
56 if (!m_serviceName.isEmpty() && m_connection.isConnected())
57 QDBusConnection::disconnectFromBus(name: m_serviceName);
58}
59
60void QDBusMenuConnection::dbusError(const QDBusError &error)
61{
62 qWarning() << "QDBusTrayIcon encountered a D-Bus error:" << error;
63}
64
65#ifndef QT_NO_SYSTEMTRAYICON
66bool QDBusMenuConnection::registerTrayIconMenu(QDBusTrayIcon *item)
67{
68 bool success = connection().registerObject(path: MenuBarPath, object: item->menu());
69 if (!success) // success == false is normal, because the object may be already registered
70 qCDebug(qLcMenu) << "failed to register" << item->instanceId() << MenuBarPath;
71 return success;
72}
73
74void QDBusMenuConnection::unregisterTrayIconMenu(QDBusTrayIcon *item)
75{
76 if (item->menu())
77 connection().unregisterObject(path: MenuBarPath);
78}
79
80bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
81{
82 bool success = connection().registerObject(path: StatusNotifierItemPath, object: item);
83 if (!success) {
84 unregisterTrayIcon(item);
85 qWarning() << "failed to register" << item->instanceId() << StatusNotifierItemPath;
86 return false;
87 }
88
89 if (item->menu())
90 registerTrayIconMenu(item);
91
92 return registerTrayIconWithWatcher(item);
93}
94
95bool QDBusMenuConnection::registerTrayIconWithWatcher(QDBusTrayIcon *item)
96{
97 Q_UNUSED(item);
98 QDBusMessage registerMethod = QDBusMessage::createMethodCall(
99 destination: StatusNotifierWatcherService, path: StatusNotifierWatcherPath, interface: StatusNotifierWatcherService,
100 method: "RegisterStatusNotifierItem"_L1);
101 registerMethod.setArguments(QVariantList() << m_connection.baseService());
102 return m_connection.callWithCallback(message: registerMethod, receiver: this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError)));
103}
104
105void QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
106{
107 unregisterTrayIconMenu(item);
108 connection().unregisterObject(path: StatusNotifierItemPath);
109}
110#endif // QT_NO_SYSTEMTRAYICON
111
112QT_END_NAMESPACE
113
114#include "moc_qdbusmenuconnection_p.cpp"
115

source code of qtbase/src/gui/platform/unix/dbusmenu/qdbusmenuconnection.cpp