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
24const QString StatusNotifierWatcherService = "org.kde.StatusNotifierWatcher"_L1;
25const QString StatusNotifierWatcherPath = "/StatusNotifierWatcher"_L1;
26const QString StatusNotifierItemPath = "/StatusNotifierItem"_L1;
27const QString MenuBarPath = "/MenuBar"_L1;
28
29/*!
30 \class QDBusMenuConnection
31 \internal
32 A D-Bus connection which is used for both menu and tray icon services.
33 Connects to the session bus and registers with the respective watcher services.
34*/
35QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &serviceName)
36 : QObject(parent)
37 , m_serviceName(serviceName)
38 , m_connection(serviceName.isNull() ? QDBusConnection::sessionBus()
39 : QDBusConnection::connectToBus(type: QDBusConnection::SessionBus, name: serviceName))
40 , m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this))
41 , m_watcherRegistered(false)
42{
43#ifndef QT_NO_SYSTEMTRAYICON
44 // Start monitoring if any known tray-related services are registered.
45 if (m_connection.interface()->isServiceRegistered(serviceName: StatusNotifierWatcherService))
46 m_watcherRegistered = true;
47 else
48 qCDebug(qLcMenu) << "failed to find service" << StatusNotifierWatcherService;
49#endif
50}
51
52QDBusMenuConnection::~QDBusMenuConnection()
53{
54 if (!m_serviceName.isEmpty() && m_connection.isConnected())
55 QDBusConnection::disconnectFromBus(name: m_serviceName);
56}
57
58void QDBusMenuConnection::dbusError(const QDBusError &error)
59{
60 qWarning() << "QDBusTrayIcon encountered a D-Bus error:" << error;
61}
62
63#ifndef QT_NO_SYSTEMTRAYICON
64bool QDBusMenuConnection::registerTrayIconMenu(QDBusTrayIcon *item)
65{
66 bool success = connection().registerObject(path: MenuBarPath, object: item->menu());
67 if (!success) // success == false is normal, because the object may be already registered
68 qCDebug(qLcMenu) << "failed to register" << item->instanceId() << MenuBarPath;
69 return success;
70}
71
72void QDBusMenuConnection::unregisterTrayIconMenu(QDBusTrayIcon *item)
73{
74 if (item->menu())
75 connection().unregisterObject(path: MenuBarPath);
76}
77
78bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
79{
80 bool success = connection().registerObject(path: StatusNotifierItemPath, object: item);
81 if (!success) {
82 unregisterTrayIcon(item);
83 qWarning() << "failed to register" << item->instanceId() << StatusNotifierItemPath;
84 return false;
85 }
86
87 if (item->menu())
88 registerTrayIconMenu(item);
89
90 return registerTrayIconWithWatcher(item);
91}
92
93bool QDBusMenuConnection::registerTrayIconWithWatcher(QDBusTrayIcon *item)
94{
95 Q_UNUSED(item);
96 QDBusMessage registerMethod = QDBusMessage::createMethodCall(
97 destination: StatusNotifierWatcherService, path: StatusNotifierWatcherPath, interface: StatusNotifierWatcherService,
98 method: "RegisterStatusNotifierItem"_L1);
99 registerMethod.setArguments(QVariantList() << m_connection.baseService());
100 return m_connection.callWithCallback(message: registerMethod, receiver: this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError)));
101}
102
103void QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
104{
105 unregisterTrayIconMenu(item);
106 connection().unregisterObject(path: StatusNotifierItemPath);
107}
108#endif // QT_NO_SYSTEMTRAYICON
109
110QT_END_NAMESPACE
111
112#include "moc_qdbusmenuconnection_p.cpp"
113

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