summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/themes/genericunix
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2016-09-29 16:49:12 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2016-10-07 07:21:14 +0000
commit13e7c603d51f22763d47e98a4e37468e46deac98 (patch)
tree7f0c12830d42176cb91431f8ad189487844da600 /src/platformsupport/themes/genericunix
parent85023e1d7254e69a997247899ec23ca12f58b054 (diff)
move dbusmenu and dbustray under themes/genericunix
that's the only place where they are used, and this clarifies the structure. Change-Id: I874beb7f049b34cc73079609b8baabcc1bd3cd39 Reviewed-by: Jake Petroules <jake.petroules@qt.io>
Diffstat (limited to 'src/platformsupport/themes/genericunix')
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/dbusmenu.pri19
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor.cpp163
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor_p.h182
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar.cpp177
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar_p.h92
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp136
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h95
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy.cpp64
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h127
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp301
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes_p.h155
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp307
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h207
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/dbustray.pri15
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp305
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustrayicon_p.h169
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp212
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustraytypes_p.h108
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp186
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor_p.h204
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy.cpp53
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h152
-rw-r--r--src/platformsupport/themes/genericunix/genericunix.pri5
23 files changed, 3434 insertions, 0 deletions
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/dbusmenu.pri b/src/platformsupport/themes/genericunix/dbusmenu/dbusmenu.pri
new file mode 100644
index 0000000000..662ebfdae6
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/dbusmenu.pri
@@ -0,0 +1,19 @@
+QT_FOR_PRIVATE += dbus
+
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qdbusmenuadaptor_p.h \
+ $$PWD/qdbusmenutypes_p.h \
+ $$PWD/qdbusmenuconnection_p.h \
+ $$PWD/qdbusmenubar_p.h \
+ $$PWD/qdbusmenuregistrarproxy_p.h \
+ $$PWD/qdbusplatformmenu_p.h \
+
+SOURCES += \
+ $$PWD/qdbusmenuadaptor.cpp \
+ $$PWD/qdbusmenutypes.cpp \
+ $$PWD/qdbusmenuconnection.cpp \
+ $$PWD/qdbusmenubar.cpp \
+ $$PWD/qdbusmenuregistrarproxy.cpp \
+ $$PWD/qdbusplatformmenu.cpp \
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor.cpp
new file mode 100644
index 0000000000..354b9c3a2e
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ This file was originally created by qdbusxml2cpp version 0.8
+ Command line was:
+ qdbusxml2cpp -a dbusmenu ../../3rdparty/dbus-ifaces/dbus-menu.xml
+
+ However it is maintained manually.
+*/
+
+#include "qdbusmenuadaptor_p.h"
+#include "qdbusplatformmenu_p.h"
+#include <QtCore/QMetaObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+QDBusMenuAdaptor::QDBusMenuAdaptor(QDBusPlatformMenu *topLevelMenu)
+ : QDBusAbstractAdaptor(topLevelMenu)
+ , m_topLevelMenu(topLevelMenu)
+{
+ setAutoRelaySignals(true);
+}
+
+QDBusMenuAdaptor::~QDBusMenuAdaptor()
+{
+}
+
+QString QDBusMenuAdaptor::status() const
+{
+ qCDebug(qLcMenu);
+ return QLatin1String("normal");
+}
+
+QString QDBusMenuAdaptor::textDirection() const
+{
+ return QLocale().textDirection() == Qt::RightToLeft ? QLatin1String("rtl") : QLatin1String("ltr");
+}
+
+uint QDBusMenuAdaptor::version() const
+{
+ return 4;
+}
+
+bool QDBusMenuAdaptor::AboutToShow(int id)
+{
+ qCDebug(qLcMenu) << id;
+ if (id == 0) {
+ emit m_topLevelMenu->aboutToShow();
+ } else {
+ QDBusPlatformMenuItem *item = QDBusPlatformMenuItem::byId(id);
+ if (item) {
+ const QDBusPlatformMenu *menu = static_cast<const QDBusPlatformMenu *>(item->menu());
+ if (menu)
+ emit const_cast<QDBusPlatformMenu *>(menu)->aboutToShow();
+ }
+ }
+ return false; // updateNeeded (we don't know that, so false)
+}
+
+QList<int> QDBusMenuAdaptor::AboutToShowGroup(const QList<int> &ids, QList<int> &idErrors)
+{
+ qCDebug(qLcMenu) << ids;
+ Q_UNUSED(idErrors)
+ idErrors.clear();
+ for (int id : ids)
+ AboutToShow(id);
+ return QList<int>(); // updatesNeeded
+}
+
+void QDBusMenuAdaptor::Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp)
+{
+ Q_UNUSED(data)
+ Q_UNUSED(timestamp)
+ QDBusPlatformMenuItem *item = QDBusPlatformMenuItem::byId(id);
+ qCDebug(qLcMenu) << id << (item ? item->text() : QLatin1String("")) << eventId;
+ if (item && eventId == QLatin1String("clicked"))
+ item->trigger();
+ if (item && eventId == QLatin1String("hovered"))
+ emit item->hovered();
+ if (eventId == QLatin1String("closed")) {
+ // There is no explicit AboutToHide method, so map closed event to aboutToHide method
+ const QDBusPlatformMenu *menu = Q_NULLPTR;
+ if (item)
+ menu = static_cast<const QDBusPlatformMenu *>(item->menu());
+ else if (id == 0)
+ menu = m_topLevelMenu;
+ if (menu)
+ emit const_cast<QDBusPlatformMenu *>(menu)->aboutToHide();
+ }
+}
+
+QList<int> QDBusMenuAdaptor::EventGroup(const QDBusMenuEventList &events)
+{
+ for (const QDBusMenuEvent &ev : events)
+ Event(ev.m_id, ev.m_eventId, ev.m_data, ev.m_timestamp);
+ return QList<int>(); // idErrors
+}
+
+QDBusMenuItemList QDBusMenuAdaptor::GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames)
+{
+ qCDebug(qLcMenu) << ids << propertyNames << "=>" << QDBusMenuItem::items(ids, propertyNames);
+ return QDBusMenuItem::items(ids, propertyNames);
+}
+
+uint QDBusMenuAdaptor::GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, QDBusMenuLayoutItem &layout)
+{
+ uint ret = layout.populate(parentId, recursionDepth, propertyNames, m_topLevelMenu);
+ qCDebug(qLcMenu) << parentId << "depth" << recursionDepth << propertyNames << layout.m_id << layout.m_properties << "revision" << ret << layout;
+ return ret;
+}
+
+QDBusVariant QDBusMenuAdaptor::GetProperty(int id, const QString &name)
+{
+ qCDebug(qLcMenu) << id << name;
+ // handle method call com.canonical.dbusmenu.GetProperty
+ QDBusVariant value;
+ return value;
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor_p.h
new file mode 100644
index 0000000000..6612f019a7
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuadaptor_p.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtDBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ This file was originally created by qdbusxml2cpp version 0.8
+ Command line was:
+ qdbusxml2cpp -a dbusmenu ../../3rdparty/dbus-ifaces/dbus-menu.xml
+
+ However it is maintained manually.
+
+ It is also not part of the public API. This header file may change from
+ version to version without notice, or even be removed.
+*/
+
+#ifndef DBUSMENUADAPTOR_H
+#define DBUSMENUADAPTOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+#include "qdbusmenutypes_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Adaptor class for interface com.canonical.dbusmenu
+ */
+class QDBusMenuAdaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.canonical.dbusmenu")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"com.canonical.dbusmenu\">\n"
+" <property access=\"read\" type=\"u\" name=\"Version\">\n"
+" </property>\n"
+" <property access=\"read\" type=\"s\" name=\"TextDirection\">\n"
+" </property>\n"
+" <property access=\"read\" type=\"s\" name=\"Status\">\n"
+" </property>\n"
+" <property access=\"read\" type=\"as\" name=\"IconThemePath\">\n"
+" </property>\n"
+" <method name=\"GetLayout\">\n"
+" <annotation value=\"QDBusMenuLayoutItem\" name=\"org.qtproject.QtDBus.QtTypeName.Out1\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"parentId\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"recursionDepth\"/>\n"
+" <arg direction=\"in\" type=\"as\" name=\"propertyNames\"/>\n"
+" <arg direction=\"out\" type=\"u\" name=\"revision\"/>\n"
+" <arg direction=\"out\" type=\"(ia{sv}av)\" name=\"layout\"/>\n"
+" </method>\n"
+" <method name=\"GetGroupProperties\">\n"
+" <annotation value=\"QList&lt;int&gt;\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
+" <annotation value=\"QDBusMenuItemList\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
+" <arg direction=\"in\" type=\"ai\" name=\"ids\"/>\n"
+" <arg direction=\"in\" type=\"as\" name=\"propertyNames\"/>\n"
+" <arg direction=\"out\" type=\"a(ia{sv})\" name=\"properties\"/>\n"
+" </method>\n"
+" <method name=\"GetProperty\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"id\"/>\n"
+" <arg direction=\"in\" type=\"s\" name=\"name\"/>\n"
+" <arg direction=\"out\" type=\"v\" name=\"value\"/>\n"
+" </method>\n"
+" <method name=\"Event\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"id\"/>\n"
+" <arg direction=\"in\" type=\"s\" name=\"eventId\"/>\n"
+" <arg direction=\"in\" type=\"v\" name=\"data\"/>\n"
+" <arg direction=\"in\" type=\"u\" name=\"timestamp\"/>\n"
+" </method>\n"
+" <method name=\"EventGroup\">\n"
+" <annotation value=\"QList&lt;QDBusMenuEvent&gt;\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
+" <annotation value=\"QList&lt;int&gt;\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
+" <arg direction=\"in\" type=\"a(isvu)\" name=\"events\"/>\n"
+" <arg direction=\"out\" type=\"ai\" name=\"idErrors\"/>\n"
+" </method>\n"
+" <method name=\"AboutToShow\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"id\"/>\n"
+" <arg direction=\"out\" type=\"b\" name=\"needUpdate\"/>\n"
+" </method>\n"
+" <method name=\"AboutToShowGroup\">\n"
+" <annotation value=\"QList&lt;int&gt;\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
+" <annotation value=\"QList&lt;int&gt;\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
+" <annotation value=\"QList&lt;int&gt;\" name=\"org.qtproject.QtDBus.QtTypeName.Out1\"/>\n"
+" <arg direction=\"in\" type=\"ai\" name=\"ids\"/>\n"
+" <arg direction=\"out\" type=\"ai\" name=\"updatesNeeded\"/>\n"
+" <arg direction=\"out\" type=\"ai\" name=\"idErrors\"/>\n"
+" </method>\n"
+" <signal name=\"ItemsPropertiesUpdated\">\n"
+" <annotation value=\"QDBusMenuItemList\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
+" <annotation value=\"QDBusMenuItemKeysList\" name=\"org.qtproject.QtDBus.QtTypeName.In1\"/>\n"
+" <arg direction=\"out\" type=\"a(ia{sv})\" name=\"updatedProps\"/>\n"
+" <arg direction=\"out\" type=\"a(ias)\" name=\"removedProps\"/>\n"
+" </signal>\n"
+" <signal name=\"LayoutUpdated\">\n"
+" <arg direction=\"out\" type=\"u\" name=\"revision\"/>\n"
+" <arg direction=\"out\" type=\"i\" name=\"parent\"/>\n"
+" </signal>\n"
+" <signal name=\"ItemActivationRequested\">\n"
+" <arg direction=\"out\" type=\"i\" name=\"id\"/>\n"
+" <arg direction=\"out\" type=\"u\" name=\"timestamp\"/>\n"
+" </signal>\n"
+" </interface>\n"
+ "")
+public:
+ QDBusMenuAdaptor(QDBusPlatformMenu *topLevelMenu);
+ virtual ~QDBusMenuAdaptor();
+
+public: // PROPERTIES
+ Q_PROPERTY(QString Status READ status)
+ QString status() const;
+
+ Q_PROPERTY(QString TextDirection READ textDirection)
+ QString textDirection() const;
+
+ Q_PROPERTY(uint Version READ version)
+ uint version() const;
+
+public Q_SLOTS: // METHODS
+ bool AboutToShow(int id);
+ QList<int> AboutToShowGroup(const QList<int> &ids, QList<int> &idErrors);
+ void Event(int id, const QString &eventId, const QDBusVariant &data, uint timestamp);
+ QList<int> EventGroup(const QDBusMenuEventList &events);
+ QDBusMenuItemList GetGroupProperties(const QList<int> &ids, const QStringList &propertyNames);
+ uint GetLayout(int parentId, int recursionDepth, const QStringList &propertyNames, QDBusMenuLayoutItem &layout);
+ QDBusVariant GetProperty(int id, const QString &name);
+
+Q_SIGNALS: // SIGNALS
+ void ItemActivationRequested(int id, uint timestamp);
+ void ItemsPropertiesUpdated(const QDBusMenuItemList &updatedProps, const QDBusMenuItemKeysList &removedProps);
+ void LayoutUpdated(uint revision, int parent);
+
+private:
+ QDBusPlatformMenu *m_topLevelMenu;
+};
+
+QT_END_NAMESPACE
+
+#endif // DBUSMENUADAPTOR_H
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar.cpp
new file mode 100644
index 0000000000..76d658f51a
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdbusmenubar_p.h"
+#include "qdbusmenuregistrarproxy_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/* note: do not change these to QStringLiteral;
+ we are unloaded before QtDBus is done using the strings.
+ */
+#define REGISTRAR_SERVICE QLatin1String("com.canonical.AppMenu.Registrar")
+#define REGISTRAR_PATH QLatin1String("/com/canonical/AppMenu/Registrar")
+
+QDBusMenuBar::QDBusMenuBar()
+ : QPlatformMenuBar()
+ , m_menu(new QDBusPlatformMenu())
+ , m_menuAdaptor(new QDBusMenuAdaptor(m_menu))
+ , m_windowId(0)
+{
+ QDBusMenuItem::registerDBusTypes();
+ connect(m_menu, &QDBusPlatformMenu::propertiesUpdated,
+ m_menuAdaptor, &QDBusMenuAdaptor::ItemsPropertiesUpdated);
+ connect(m_menu, &QDBusPlatformMenu::updated,
+ m_menuAdaptor, &QDBusMenuAdaptor::LayoutUpdated);
+}
+
+QDBusMenuBar::~QDBusMenuBar()
+{
+ unregisterMenuBar();
+ delete m_menuAdaptor;
+ delete m_menu;
+ qDeleteAll(m_menuItems);
+}
+
+QDBusPlatformMenuItem *QDBusMenuBar::menuItemForMenu(QPlatformMenu *menu)
+{
+ if (!menu)
+ return nullptr;
+ quintptr tag = menu->tag();
+ const auto it = m_menuItems.constFind(tag);
+ if (it != m_menuItems.cend()) {
+ return *it;
+ } else {
+ QDBusPlatformMenuItem *item = new QDBusPlatformMenuItem;
+ updateMenuItem(item, menu);
+ m_menuItems.insert(tag, item);
+ return item;
+ }
+}
+
+void QDBusMenuBar::updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu)
+{
+ const QDBusPlatformMenu *ourMenu = qobject_cast<const QDBusPlatformMenu *>(menu);
+ item->setText(ourMenu->text());
+ item->setIcon(ourMenu->icon());
+ item->setEnabled(ourMenu->isEnabled());
+ item->setVisible(ourMenu->isVisible());
+ item->setMenu(menu);
+}
+
+void QDBusMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *before)
+{
+ QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu);
+ QDBusPlatformMenuItem *beforeItem = menuItemForMenu(before);
+ m_menu->insertMenuItem(menuItem, beforeItem);
+ m_menu->emitUpdated();
+}
+
+void QDBusMenuBar::removeMenu(QPlatformMenu *menu)
+{
+ QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu);
+ m_menu->removeMenuItem(menuItem);
+ m_menu->emitUpdated();
+}
+
+void QDBusMenuBar::syncMenu(QPlatformMenu *menu)
+{
+ QDBusPlatformMenuItem *menuItem = menuItemForMenu(menu);
+ updateMenuItem(menuItem, menu);
+}
+
+void QDBusMenuBar::handleReparent(QWindow *newParentWindow)
+{
+ if (newParentWindow && newParentWindow->winId() != m_windowId) {
+ unregisterMenuBar();
+ m_windowId = newParentWindow->winId();
+ registerMenuBar();
+ }
+}
+
+QPlatformMenu *QDBusMenuBar::menuForTag(quintptr tag) const
+{
+ QDBusPlatformMenuItem *menuItem = m_menuItems.value(tag);
+ if (menuItem)
+ return const_cast<QPlatformMenu *>(menuItem->menu());
+ return nullptr;
+}
+
+QPlatformMenu *QDBusMenuBar::createMenu() const
+{
+ return new QDBusPlatformMenu;
+}
+
+void QDBusMenuBar::registerMenuBar()
+{
+ static uint menuBarId = 0;
+
+ QDBusConnection connection = QDBusConnection::sessionBus();
+ m_objectPath = QStringLiteral("/MenuBar/%1").arg(++menuBarId);
+ if (!connection.registerObject(m_objectPath, m_menu))
+ return;
+
+ QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this);
+ QDBusPendingReply<> r = registrar.RegisterWindow(m_windowId, QDBusObjectPath(m_objectPath));
+ r.waitForFinished();
+ if (r.isError()) {
+ qWarning("Failed to register window menu, reason: %s (\"%s\")",
+ qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message()));
+ connection.unregisterObject(m_objectPath);
+ }
+}
+
+void QDBusMenuBar::unregisterMenuBar()
+{
+ QDBusConnection connection = QDBusConnection::sessionBus();
+
+ if (m_windowId) {
+ QDBusMenuRegistrarInterface registrar(REGISTRAR_SERVICE, REGISTRAR_PATH, connection, this);
+ QDBusPendingReply<> r = registrar.UnregisterWindow(m_windowId);
+ r.waitForFinished();
+ if (r.isError())
+ qWarning("Failed to unregister window menu, reason: %s (\"%s\")",
+ qUtf8Printable(r.error().name()), qUtf8Printable(r.error().message()));
+ }
+
+ if (!m_objectPath.isEmpty())
+ connection.unregisterObject(m_objectPath);
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar_p.h
new file mode 100644
index 0000000000..8266a395f5
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenubar_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSMENUBAR_P_H
+#define QDBUSMENUBAR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qdbusplatformmenu_p.h>
+#include <private/qdbusmenuadaptor_p.h>
+#include <QtCore/QHash>
+#include <QtCore/QString>
+#include <QtGui/QWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QDBusMenuBar : public QPlatformMenuBar
+{
+ Q_OBJECT
+
+public:
+ QDBusMenuBar();
+ virtual ~QDBusMenuBar();
+
+ void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) Q_DECL_OVERRIDE;
+ void removeMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
+ void syncMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
+ void handleReparent(QWindow *newParentWindow) Q_DECL_OVERRIDE;
+ QPlatformMenu *menuForTag(quintptr tag) const Q_DECL_OVERRIDE;
+ QPlatformMenu *createMenu() const Q_DECL_OVERRIDE;
+
+private:
+ QDBusPlatformMenu *m_menu;
+ QDBusMenuAdaptor *m_menuAdaptor;
+ QHash<quintptr, QDBusPlatformMenuItem *> m_menuItems;
+ uint m_windowId;
+ QString m_objectPath;
+
+ QDBusPlatformMenuItem *menuItemForMenu(QPlatformMenu *menu);
+ static void updateMenuItem(QDBusPlatformMenuItem *item, QPlatformMenu *menu);
+ void registerMenuBar();
+ void unregisterMenuBar();
+};
+
+QT_END_NAMESPACE
+
+#endif // QDBUSMENUBAR_P_H
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
new file mode 100644
index 0000000000..361146dc23
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_SYSTEMTRAYICON
+#include "qdbustrayicon_p.h"
+#endif
+#include "qdbusmenuconnection_p.h"
+#include "qdbusmenuadaptor_p.h"
+#include "qdbusplatformmenu_p.h"
+
+#include <QtDBus/QDBusMessage>
+#include <QtDBus/QDBusServiceWatcher>
+#include <QtDBus/QDBusConnectionInterface>
+#include <qdebug.h>
+#include <qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcMenu)
+
+const QString StatusNotifierWatcherService = QLatin1String("org.kde.StatusNotifierWatcher");
+const QString StatusNotifierWatcherPath = QLatin1String("/StatusNotifierWatcher");
+const QString StatusNotifierItemPath = QLatin1String("/StatusNotifierItem");
+const QString MenuBarPath = QLatin1String("/MenuBar");
+
+/*!
+ \class QDBusMenuConnection
+ \internal
+ A D-Bus connection which is used for both menu and tray icon services.
+ Connects to the session bus and registers with the respective watcher services.
+*/
+QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &serviceName)
+ : QObject(parent)
+ , m_connection(serviceName.isNull() ? QDBusConnection::sessionBus()
+ : QDBusConnection::connectToBus(QDBusConnection::SessionBus, serviceName))
+ , m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this))
+ , m_statusNotifierHostRegistered(false)
+{
+#ifndef QT_NO_SYSTEMTRAYICON
+ QDBusInterface systrayHost(StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService, m_connection);
+ if (systrayHost.isValid() && systrayHost.property("IsStatusNotifierHostRegistered").toBool())
+ m_statusNotifierHostRegistered = true;
+ else
+ qCDebug(qLcMenu) << "StatusNotifierHost is not registered";
+#endif
+}
+
+void QDBusMenuConnection::dbusError(const QDBusError &error)
+{
+ qWarning() << "QDBusTrayIcon encountered a D-Bus error:" << error;
+}
+
+#ifndef QT_NO_SYSTEMTRAYICON
+bool QDBusMenuConnection::registerTrayIconMenu(QDBusTrayIcon *item)
+{
+ bool success = connection().registerObject(MenuBarPath, item->menu());
+ if (!success) // success == false is normal, because the object may be already registered
+ qCDebug(qLcMenu) << "failed to register" << item->instanceId() << MenuBarPath;
+ return success;
+}
+
+bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
+{
+ bool success = connection().registerService(item->instanceId());
+ if (!success) {
+ qWarning() << "failed to register service" << item->instanceId();
+ return false;
+ }
+
+ success = connection().registerObject(StatusNotifierItemPath, item);
+ if (!success) {
+ unregisterTrayIcon(item);
+ qWarning() << "failed to register" << item->instanceId() << StatusNotifierItemPath;
+ return false;
+ }
+
+ if (item->menu())
+ registerTrayIconMenu(item);
+
+ QDBusMessage registerMethod = QDBusMessage::createMethodCall(
+ StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService,
+ QLatin1String("RegisterStatusNotifierItem"));
+ registerMethod.setArguments(QVariantList() << item->instanceId());
+ success = m_connection.callWithCallback(registerMethod, this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError)));
+
+ return success;
+}
+
+bool QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
+{
+ connection().unregisterObject(MenuBarPath);
+ connection().unregisterObject(StatusNotifierItemPath);
+ bool success = connection().unregisterService(item->instanceId());
+ if (!success)
+ qWarning() << "failed to unregister service" << item->instanceId();
+ return success;
+}
+#endif // QT_NO_SYSTEMTRAYICON
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
new file mode 100644
index 0000000000..84eb2a6f3a
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DBUSCONNECTION_H
+#define DBUSCONNECTION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QDBusServiceWatcher;
+#ifndef QT_NO_SYSTEMTRAYICON
+class QDBusTrayIcon;
+#endif // QT_NO_SYSTEMTRAYICON
+
+class QDBusMenuConnection : public QObject
+{
+ Q_OBJECT
+
+public:
+ QDBusMenuConnection(QObject *parent = 0, const QString &serviceName = QString());
+ QDBusConnection connection() const { return m_connection; }
+ bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
+#ifndef QT_NO_SYSTEMTRAYICON
+ bool registerTrayIconMenu(QDBusTrayIcon *item);
+ bool registerTrayIcon(QDBusTrayIcon *item);
+ bool unregisterTrayIcon(QDBusTrayIcon *item);
+#endif // QT_NO_SYSTEMTRAYICON
+
+Q_SIGNALS:
+#ifndef QT_NO_SYSTEMTRAYICON
+ void trayIconRegistered();
+#endif // QT_NO_SYSTEMTRAYICON
+
+private Q_SLOTS:
+ void dbusError(const QDBusError &error);
+
+private:
+ QDBusConnection m_connection;
+ QDBusServiceWatcher *m_dbusWatcher;
+ bool m_statusNotifierHostRegistered;
+};
+
+QT_END_NAMESPACE
+
+#endif // DBUSCONNECTION_H
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy.cpp
new file mode 100644
index 0000000000..c59b5a675e
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * This file was originally created by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p qdbusmenuregistrarproxy ../../3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml
+ *
+ * However it is maintained manually.
+ */
+
+#include "qdbusmenuregistrarproxy_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Implementation of interface class QDBusMenuRegistrarInterface
+ */
+
+QDBusMenuRegistrarInterface::QDBusMenuRegistrarInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+QDBusMenuRegistrarInterface::~QDBusMenuRegistrarInterface()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h
new file mode 100644
index 0000000000..c92de0a140
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * This file was originally created by qdbusxml2cpp version 0.8
+ * Command line was: qdbusxml2cpp -p qdbusmenuregistrarproxy ../../3rdparty/dbus-ifaces/com.canonical.AppMenu.Registrar.xml
+ *
+ * However it is maintained manually.
+ */
+
+#ifndef QDBUSMENUREGISTRARPROXY_P_H
+#define QDBUSMENUREGISTRARPROXY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtDBus/QDBusAbstractInterface>
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusReply>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Proxy class for interface com.canonical.AppMenu.Registrar
+ */
+class QDBusMenuRegistrarInterface : public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ {
+ return "com.canonical.AppMenu.Registrar";
+ }
+
+public:
+ explicit QDBusMenuRegistrarInterface(const QString &service,
+ const QString &path,
+ const QDBusConnection &connection,
+ QObject *parent = nullptr);
+
+ ~QDBusMenuRegistrarInterface();
+
+public Q_SLOTS: // METHODS
+ QDBusPendingReply<QString, QDBusObjectPath> GetMenuForWindow(uint windowId)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(windowId);
+ return asyncCallWithArgumentList(QStringLiteral("GetMenuForWindow"), argumentList);
+ }
+ QDBusReply<QString> GetMenuForWindow(uint windowId, QDBusObjectPath &menuObjectPath)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(windowId);
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("GetMenuForWindow"), argumentList);
+ QList<QVariant> arguments = reply.arguments();
+ if (reply.type() == QDBusMessage::ReplyMessage && arguments.count() == 2)
+ menuObjectPath = qdbus_cast<QDBusObjectPath>(arguments.at(1));
+ return reply;
+ }
+
+ QDBusPendingReply<> RegisterWindow(uint windowId, const QDBusObjectPath &menuObjectPath)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(windowId) << QVariant::fromValue(menuObjectPath);
+ return asyncCallWithArgumentList(QStringLiteral("RegisterWindow"), argumentList);
+ }
+
+ QDBusPendingReply<> UnregisterWindow(uint windowId)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(windowId);
+ return asyncCallWithArgumentList(QStringLiteral("UnregisterWindow"), argumentList);
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QDBUSMENUREGISTRARPROXY_P_H
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp
new file mode 100644
index 0000000000..82a13d2fa0
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes.cpp
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdbusmenutypes_p.h"
+
+#include <QDBusConnection>
+#include <QDBusMetaType>
+#include <QImage>
+#include <QIcon>
+#include <QImage>
+#include <QPixmap>
+#include <QDebug>
+#include <QtEndian>
+#include <QBuffer>
+#include <private/qkeysequence_p.h>
+#include <qpa/qplatformmenu.h>
+#include "qdbusplatformmenu_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItem &item)
+{
+ arg.beginStructure();
+ arg << item.m_id << item.m_properties;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuItem &item)
+{
+ arg.beginStructure();
+ arg >> item.m_id >> item.m_properties;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItemKeys &keys)
+{
+ arg.beginStructure();
+ arg << keys.id << keys.properties;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuItemKeys &keys)
+{
+ arg.beginStructure();
+ arg >> keys.id >> keys.properties;
+ arg.endStructure();
+ return arg;
+}
+
+uint QDBusMenuLayoutItem::populate(int id, int depth, const QStringList &propertyNames, const QDBusPlatformMenu *topLevelMenu)
+{
+ qCDebug(qLcMenu) << id << "depth" << depth << propertyNames;
+ m_id = id;
+ if (id == 0) {
+ m_properties.insert(QLatin1String("children-display"), QLatin1String("submenu"));
+ if (topLevelMenu)
+ populate(topLevelMenu, depth, propertyNames);
+ return 1; // revision
+ }
+
+ QDBusPlatformMenuItem *item = QDBusPlatformMenuItem::byId(id);
+ if (item) {
+ const QDBusPlatformMenu *menu = static_cast<const QDBusPlatformMenu *>(item->menu());
+
+ if (menu) {
+ if (depth != 0)
+ populate(menu, depth, propertyNames);
+ return menu->revision();
+ }
+ }
+
+ return 1; // revision
+}
+
+void QDBusMenuLayoutItem::populate(const QDBusPlatformMenu *menu, int depth, const QStringList &propertyNames)
+{
+ const auto items = menu->items();
+ for (QDBusPlatformMenuItem *item : items) {
+ QDBusMenuLayoutItem child;
+ child.populate(item, depth - 1, propertyNames);
+ m_children << child;
+ }
+}
+
+void QDBusMenuLayoutItem::populate(const QDBusPlatformMenuItem *item, int depth, const QStringList &propertyNames)
+{
+ m_id = item->dbusID();
+ QDBusMenuItem proxy(item);
+ m_properties = proxy.m_properties;
+
+ const QDBusPlatformMenu *menu = static_cast<const QDBusPlatformMenu *>(item->menu());
+ if (depth != 0 && menu)
+ populate(menu, depth, propertyNames);
+}
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuLayoutItem &item)
+{
+ arg.beginStructure();
+ arg << item.m_id << item.m_properties;
+ arg.beginArray(qMetaTypeId<QDBusVariant>());
+ for (const QDBusMenuLayoutItem &child : item.m_children)
+ arg << QDBusVariant(QVariant::fromValue<QDBusMenuLayoutItem>(child));
+ arg.endArray();
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuLayoutItem &item)
+{
+ arg.beginStructure();
+ arg >> item.m_id >> item.m_properties;
+ arg.beginArray();
+ while (!arg.atEnd()) {
+ QDBusVariant dbusVariant;
+ arg >> dbusVariant;
+ QDBusArgument childArgument = dbusVariant.variant().value<QDBusArgument>();
+
+ QDBusMenuLayoutItem child;
+ childArgument >> child;
+ item.m_children.append(child);
+ }
+ arg.endArray();
+ arg.endStructure();
+ return arg;
+}
+
+void QDBusMenuItem::registerDBusTypes()
+{
+ qDBusRegisterMetaType<QDBusMenuItem>();
+ qDBusRegisterMetaType<QDBusMenuItemList>();
+ qDBusRegisterMetaType<QDBusMenuItemKeys>();
+ qDBusRegisterMetaType<QDBusMenuItemKeysList>();
+ qDBusRegisterMetaType<QDBusMenuLayoutItem>();
+ qDBusRegisterMetaType<QDBusMenuLayoutItemList>();
+ qDBusRegisterMetaType<QDBusMenuEvent>();
+ qDBusRegisterMetaType<QDBusMenuEventList>();
+ qDBusRegisterMetaType<QDBusMenuShortcut>();
+}
+
+QDBusMenuItem::QDBusMenuItem(const QDBusPlatformMenuItem *item)
+ : m_id(item->dbusID())
+{
+ if (item->isSeparator()) {
+ m_properties.insert(QLatin1String("type"), QLatin1String("separator"));
+ } else {
+ m_properties.insert(QLatin1String("label"), convertMnemonic(item->text()));
+ if (item->menu())
+ m_properties.insert(QLatin1String("children-display"), QLatin1String("submenu"));
+ m_properties.insert(QLatin1String("enabled"), item->isEnabled());
+ if (item->isCheckable()) {
+ QString toggleType = item->hasExclusiveGroup() ? QLatin1String("radio") : QLatin1String("checkmark");
+ m_properties.insert(QLatin1String("toggle-type"), toggleType);
+ m_properties.insert(QLatin1String("toggle-state"), item->isChecked() ? 1 : 0);
+ }
+#ifndef QT_NO_SHORTCUT
+ const QKeySequence &scut = item->shortcut();
+ if (!scut.isEmpty()) {
+ QDBusMenuShortcut shortcut = convertKeySequence(scut);
+ m_properties.insert(QLatin1String("shortcut"), QVariant::fromValue(shortcut));
+ }
+#endif
+ const QIcon &icon = item->icon();
+ if (!icon.name().isEmpty()) {
+ m_properties.insert(QLatin1String("icon-name"), icon.name());
+ } else if (!icon.isNull()) {
+ QBuffer buf;
+ icon.pixmap(16).save(&buf, "PNG");
+ m_properties.insert(QLatin1String("icon-data"), buf.data());
+ }
+ }
+ m_properties.insert(QLatin1String("visible"), item->isVisible());
+}
+
+QDBusMenuItemList QDBusMenuItem::items(const QList<int> &ids, const QStringList &propertyNames)
+{
+ Q_UNUSED(propertyNames)
+ QDBusMenuItemList ret;
+ const QList<const QDBusPlatformMenuItem *> items = QDBusPlatformMenuItem::byIds(ids);
+ ret.reserve(items.size());
+ for (const QDBusPlatformMenuItem *item : items)
+ ret << QDBusMenuItem(item);
+ return ret;
+}
+
+QString QDBusMenuItem::convertMnemonic(const QString &label)
+{
+ // convert only the first occurrence of ampersand which is not at the end
+ // dbusmenu uses underscore instead of ampersand
+ int idx = label.indexOf(QLatin1Char('&'));
+ if (idx < 0 || idx == label.length() - 1)
+ return label;
+ QString ret(label);
+ ret[idx] = QLatin1Char('_');
+ return ret;
+}
+
+#ifndef QT_NO_SHORTCUT
+QDBusMenuShortcut QDBusMenuItem::convertKeySequence(const QKeySequence &sequence)
+{
+ QDBusMenuShortcut shortcut;
+ for (int i = 0; i < sequence.count(); ++i) {
+ QStringList tokens;
+ int key = sequence[i];
+ if (key & Qt::MetaModifier)
+ tokens << QStringLiteral("Super");
+ if (key & Qt::ControlModifier)
+ tokens << QStringLiteral("Control");
+ if (key & Qt::AltModifier)
+ tokens << QStringLiteral("Alt");
+ if (key & Qt::ShiftModifier)
+ tokens << QStringLiteral("Shift");
+ if (key & Qt::KeypadModifier)
+ tokens << QStringLiteral("Num");
+
+ QString keyName = QKeySequencePrivate::keyName(key, QKeySequence::PortableText);
+ if (keyName == QLatin1String("+"))
+ tokens << QStringLiteral("plus");
+ else if (keyName == QLatin1String("-"))
+ tokens << QStringLiteral("minus");
+ else
+ tokens << keyName;
+ shortcut << tokens;
+ }
+ return shortcut;
+}
+#endif
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuEvent &ev)
+{
+ arg.beginStructure();
+ arg << ev.m_id << ev.m_eventId << ev.m_data << ev.m_timestamp;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuEvent &ev)
+{
+ arg.beginStructure();
+ arg >> ev.m_id >> ev.m_eventId >> ev.m_data >> ev.m_timestamp;
+ arg.endStructure();
+ return arg;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QDBusMenuItem &item)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "QDBusMenuItem(id=" << item.m_id << ", properties=" << item.m_properties << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, const QDBusMenuLayoutItem &item)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "QDBusMenuLayoutItem(id=" << item.m_id << ", properties=" << item.m_properties << ", " << item.m_children.count() << " children)";
+ return d;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes_p.h
new file mode 100644
index 0000000000..fd6727d3be
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenutypes_p.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSMENUTYPES_H
+#define QDBUSMENUTYPES_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QObject>
+#include <QString>
+#include <QDBusArgument>
+#include <QDBusConnection>
+#include <QDBusObjectPath>
+#include <QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+class QDBusPlatformMenu;
+class QDBusPlatformMenuItem;
+class QDBusMenuItem;
+typedef QVector<QDBusMenuItem> QDBusMenuItemList;
+typedef QVector<QStringList> QDBusMenuShortcut;
+
+class QDBusMenuItem
+{
+public:
+ QDBusMenuItem() { }
+ QDBusMenuItem(const QDBusPlatformMenuItem *item);
+
+ static QDBusMenuItemList items(const QList<int> &ids, const QStringList &propertyNames);
+ static QString convertMnemonic(const QString &label);
+#ifndef QT_NO_SHORTCUT
+ static QDBusMenuShortcut convertKeySequence(const QKeySequence &sequence);
+#endif
+ static void registerDBusTypes();
+
+ int m_id;
+ QVariantMap m_properties;
+};
+Q_DECLARE_TYPEINFO(QDBusMenuItem, Q_MOVABLE_TYPE);
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItem &item);
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuItem &item);
+
+class QDBusMenuItemKeys
+{
+public:
+
+ int id;
+ QStringList properties;
+};
+Q_DECLARE_TYPEINFO(QDBusMenuItemKeys, Q_MOVABLE_TYPE);
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItemKeys &keys);
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuItemKeys &keys);
+
+typedef QVector<QDBusMenuItemKeys> QDBusMenuItemKeysList;
+
+class QDBusMenuLayoutItem
+{
+public:
+ uint populate(int id, int depth, const QStringList &propertyNames, const QDBusPlatformMenu *topLevelMenu);
+ void populate(const QDBusPlatformMenu *menu, int depth, const QStringList &propertyNames);
+ void populate(const QDBusPlatformMenuItem *item, int depth, const QStringList &propertyNames);
+
+ int m_id;
+ QVariantMap m_properties;
+ QVector<QDBusMenuLayoutItem> m_children;
+};
+Q_DECLARE_TYPEINFO(QDBusMenuLayoutItem, Q_MOVABLE_TYPE);
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuLayoutItem &);
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuLayoutItem &item);
+
+typedef QVector<QDBusMenuLayoutItem> QDBusMenuLayoutItemList;
+
+class QDBusMenuEvent
+{
+public:
+ int m_id;
+ QString m_eventId;
+ QDBusVariant m_data;
+ uint m_timestamp;
+};
+Q_DECLARE_TYPEINFO(QDBusMenuEvent, Q_MOVABLE_TYPE); // QDBusVariant is movable, even though it cannot
+ // be marked as such until Qt 6.
+
+const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuEvent &ev);
+const QDBusArgument &operator>>(const QDBusArgument &arg, QDBusMenuEvent &ev);
+
+typedef QVector<QDBusMenuEvent> QDBusMenuEventList;
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QDBusMenuItem &item);
+QDebug operator<<(QDebug d, const QDBusMenuLayoutItem &item);
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDBusMenuItem)
+Q_DECLARE_METATYPE(QDBusMenuItemList)
+Q_DECLARE_METATYPE(QDBusMenuItemKeys)
+Q_DECLARE_METATYPE(QDBusMenuItemKeysList)
+Q_DECLARE_METATYPE(QDBusMenuLayoutItem)
+Q_DECLARE_METATYPE(QDBusMenuLayoutItemList)
+Q_DECLARE_METATYPE(QDBusMenuEvent)
+Q_DECLARE_METATYPE(QDBusMenuEventList)
+Q_DECLARE_METATYPE(QDBusMenuShortcut)
+
+#endif
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp
new file mode 100644
index 0000000000..15440a03cd
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp
@@ -0,0 +1,307 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdbusplatformmenu_p.h"
+
+#include <QDebug>
+#include <QWindow>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcMenu, "qt.qpa.menu")
+
+static int nextDBusID = 1;
+QHash<int, QDBusPlatformMenuItem *> menuItemsByID;
+
+QDBusPlatformMenuItem::QDBusPlatformMenuItem(quintptr tag)
+ : m_tag(tag ? tag : reinterpret_cast<quintptr>(this)) // QMenu will overwrite this later
+ , m_subMenu(Q_NULLPTR)
+ , m_role(NoRole)
+ , m_isEnabled(true)
+ , m_isVisible(true)
+ , m_isSeparator(false)
+ , m_isCheckable(false)
+ , m_isChecked(false)
+ , m_dbusID(nextDBusID++)
+ , m_hasExclusiveGroup(false)
+{
+ menuItemsByID.insert(m_dbusID, this);
+}
+
+QDBusPlatformMenuItem::~QDBusPlatformMenuItem()
+{
+ menuItemsByID.remove(m_dbusID);
+ if (m_subMenu)
+ static_cast<QDBusPlatformMenu *>(m_subMenu)->setContainingMenuItem(Q_NULLPTR);
+}
+
+void QDBusPlatformMenuItem::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+void QDBusPlatformMenuItem::setText(const QString &text)
+{
+ qCDebug(qLcMenu) << m_dbusID << text;
+ m_text = text;
+}
+
+void QDBusPlatformMenuItem::setIcon(const QIcon &icon)
+{
+ m_icon = icon;
+}
+
+/*!
+ Set a submenu under this menu item.
+*/
+void QDBusPlatformMenuItem::setMenu(QPlatformMenu *menu)
+{
+ if (m_subMenu)
+ static_cast<QDBusPlatformMenu *>(m_subMenu)->setContainingMenuItem(Q_NULLPTR);
+ m_subMenu = menu;
+ if (menu)
+ static_cast<QDBusPlatformMenu *>(menu)->setContainingMenuItem(this);
+}
+
+void QDBusPlatformMenuItem::setEnabled(bool enabled)
+{
+ m_isEnabled = enabled;
+}
+
+void QDBusPlatformMenuItem::setVisible(bool isVisible)
+{
+ m_isVisible = isVisible;
+}
+
+void QDBusPlatformMenuItem::setIsSeparator(bool isSeparator)
+{
+ m_isSeparator = isSeparator;
+}
+
+void QDBusPlatformMenuItem::setRole(QPlatformMenuItem::MenuRole role)
+{
+ m_role = role;
+}
+
+void QDBusPlatformMenuItem::setCheckable(bool checkable)
+{
+ m_isCheckable = checkable;
+}
+
+void QDBusPlatformMenuItem::setChecked(bool isChecked)
+{
+ m_isChecked = isChecked;
+}
+
+void QDBusPlatformMenuItem::setHasExclusiveGroup(bool hasExclusiveGroup)
+{
+ m_hasExclusiveGroup = hasExclusiveGroup;
+}
+
+#ifndef QT_NO_SHORTCUT
+void QDBusPlatformMenuItem::setShortcut(const QKeySequence &shortcut)
+{
+ m_shortcut = shortcut;
+}
+#endif
+
+void QDBusPlatformMenuItem::trigger()
+{
+ emit activated();
+}
+
+QDBusPlatformMenuItem *QDBusPlatformMenuItem::byId(int id)
+{
+ // We need to check contains because otherwise QHash would insert
+ // a default-constructed nullptr value into menuItemsByID
+ if (menuItemsByID.contains(id))
+ return menuItemsByID[id];
+ return Q_NULLPTR;
+}
+
+QList<const QDBusPlatformMenuItem *> QDBusPlatformMenuItem::byIds(const QList<int> &ids)
+{
+ QList<const QDBusPlatformMenuItem *> ret;
+ for (int id : ids) {
+ if (menuItemsByID.contains(id))
+ ret << menuItemsByID[id];
+ }
+ return ret;
+}
+
+
+QDBusPlatformMenu::QDBusPlatformMenu(quintptr tag)
+ : m_tag(tag ? tag : reinterpret_cast<quintptr>(this))
+ , m_isEnabled(true)
+ , m_isVisible(true)
+ , m_isSeparator(false)
+ , m_revision(1)
+ , m_containingMenuItem(Q_NULLPTR)
+{
+}
+
+QDBusPlatformMenu::~QDBusPlatformMenu()
+{
+ if (m_containingMenuItem)
+ m_containingMenuItem->setMenu(Q_NULLPTR);
+}
+
+void QDBusPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
+{
+ QDBusPlatformMenuItem *item = static_cast<QDBusPlatformMenuItem *>(menuItem);
+ QDBusPlatformMenuItem *beforeItem = static_cast<QDBusPlatformMenuItem *>(before);
+ int idx = m_items.indexOf(beforeItem);
+ qCDebug(qLcMenu) << item->dbusID() << item->text();
+ if (idx < 0)
+ m_items.append(item);
+ else
+ m_items.insert(idx, item);
+ m_itemsByTag.insert(item->tag(), item);
+ if (item->menu())
+ syncSubMenu(static_cast<const QDBusPlatformMenu *>(item->menu()));
+ emitUpdated();
+}
+
+void QDBusPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem)
+{
+ QDBusPlatformMenuItem *item = static_cast<QDBusPlatformMenuItem *>(menuItem);
+ m_items.removeAll(item);
+ m_itemsByTag.remove(menuItem->tag());
+ if (item->menu()) {
+ // disconnect from the signals we connected to in syncSubMenu()
+ const QDBusPlatformMenu *menu = static_cast<const QDBusPlatformMenu *>(item->menu());
+ disconnect(menu, &QDBusPlatformMenu::propertiesUpdated,
+ this, &QDBusPlatformMenu::propertiesUpdated);
+ disconnect(menu, &QDBusPlatformMenu::updated,
+ this, &QDBusPlatformMenu::updated);
+ }
+ emitUpdated();
+}
+
+void QDBusPlatformMenu::syncSubMenu(const QDBusPlatformMenu *menu)
+{
+ // The adaptor is only connected to the propertiesUpdated signal of the top-level
+ // menu, so the submenus should transfer their signals to their parents.
+ connect(menu, &QDBusPlatformMenu::propertiesUpdated,
+ this, &QDBusPlatformMenu::propertiesUpdated, Qt::UniqueConnection);
+ connect(menu, &QDBusPlatformMenu::updated,
+ this, &QDBusPlatformMenu::updated, Qt::UniqueConnection);
+}
+
+void QDBusPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem)
+{
+ QDBusPlatformMenuItem *item = static_cast<QDBusPlatformMenuItem *>(menuItem);
+ // if a submenu was added to this item, we need to connect to its signals
+ if (item->menu())
+ syncSubMenu(static_cast<const QDBusPlatformMenu *>(item->menu()));
+ // TODO keep around copies of the QDBusMenuLayoutItems so they can be updated?
+ // or eliminate them by putting dbus streaming operators in this class instead?
+ // or somehow tell the dbusmenu client that something has changed, so it will ask for properties again
+ QDBusMenuItemList updated;
+ QDBusMenuItemKeysList removed;
+ updated << QDBusMenuItem(item);
+ qCDebug(qLcMenu) << updated;
+ emit propertiesUpdated(updated, removed);
+}
+
+void QDBusPlatformMenu::emitUpdated()
+{
+ if (m_containingMenuItem)
+ emit updated(++m_revision, m_containingMenuItem->dbusID());
+ else
+ emit updated(++m_revision, 0);
+}
+
+void QDBusPlatformMenu::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+void QDBusPlatformMenu::setText(const QString &text)
+{
+ m_text = text;
+}
+
+void QDBusPlatformMenu::setIcon(const QIcon &icon)
+{
+ m_icon = icon;
+}
+
+void QDBusPlatformMenu::setEnabled(bool enabled)
+{
+ m_isEnabled = enabled;
+}
+
+void QDBusPlatformMenu::setVisible(bool isVisible)
+{
+ m_isVisible = isVisible;
+}
+
+void QDBusPlatformMenu::setContainingMenuItem(QDBusPlatformMenuItem *item)
+{
+ m_containingMenuItem = item;
+}
+
+QPlatformMenuItem *QDBusPlatformMenu::menuItemAt(int position) const
+{
+ return m_items.value(position);
+}
+
+QPlatformMenuItem *QDBusPlatformMenu::menuItemForTag(quintptr tag) const
+{
+ return m_itemsByTag[tag];
+}
+
+const QList<QDBusPlatformMenuItem *> QDBusPlatformMenu::items() const
+{
+ return m_items;
+}
+
+QPlatformMenuItem *QDBusPlatformMenu::createMenuItem() const
+{
+ QDBusPlatformMenuItem *ret = new QDBusPlatformMenuItem();
+ return ret;
+}
+
+QPlatformMenu *QDBusPlatformMenu::createSubMenu() const
+{
+ return new QDBusPlatformMenu;
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h
new file mode 100644
index 0000000000..38c27e8051
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSPLATFORMMENU_H
+#define QDBUSPLATFORMMENU_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the DBus menu support and is not meant to be used
+// in applications. Usage of this API may make your code
+// source and binary incompatible with future versions of Qt.
+//
+
+#include <qpa/qplatformmenu.h>
+#include <QLoggingCategory>
+#include "qdbusmenutypes_p.h"
+
+QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(qLcMenu)
+
+class QDBusPlatformMenu;
+
+class QDBusPlatformMenuItem : public QPlatformMenuItem
+{
+ Q_OBJECT
+
+public:
+ QDBusPlatformMenuItem(quintptr tag = 0LL);
+ ~QDBusPlatformMenuItem();
+
+ quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
+ void setTag(quintptr tag) Q_DECL_OVERRIDE;
+
+ const QString text() const { return m_text; }
+ void setText(const QString &text) Q_DECL_OVERRIDE;
+ QIcon icon() const { return m_icon; }
+ void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
+ const QPlatformMenu *menu() const { return m_subMenu; }
+ void setMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
+ bool isEnabled() const { return m_isEnabled; }
+ void setEnabled(bool enabled) Q_DECL_OVERRIDE;
+ bool isVisible() const { return m_isVisible; }
+ void setVisible(bool isVisible) Q_DECL_OVERRIDE;
+ bool isSeparator() const { return m_isSeparator; }
+ void setIsSeparator(bool isSeparator) Q_DECL_OVERRIDE;
+ void setFont(const QFont &font) Q_DECL_OVERRIDE { Q_UNUSED(font); }
+ void setRole(MenuRole role) Q_DECL_OVERRIDE;
+ bool isCheckable() const { return m_isCheckable; }
+ void setCheckable(bool checkable) Q_DECL_OVERRIDE;
+ bool isChecked() const { return m_isChecked; }
+ void setChecked(bool isChecked) Q_DECL_OVERRIDE;
+ bool hasExclusiveGroup() const { return m_hasExclusiveGroup; }
+ void setHasExclusiveGroup(bool hasExclusiveGroup) Q_DECL_OVERRIDE;
+#ifndef QT_NO_SHORTCUT
+ QKeySequence shortcut() const { return m_shortcut; }
+ void setShortcut(const QKeySequence& shortcut) Q_DECL_OVERRIDE;
+#endif
+ void setIconSize(int size) Q_DECL_OVERRIDE { Q_UNUSED(size); }
+ void setNativeContents(WId item) Q_DECL_OVERRIDE { Q_UNUSED(item); }
+
+ int dbusID() const { return m_dbusID; }
+
+ void trigger();
+
+ bool operator==(const QDBusPlatformMenuItem& other) { return m_tag == other.m_tag; }
+
+ static QDBusPlatformMenuItem *byId(int id);
+ static QList<const QDBusPlatformMenuItem *> byIds(const QList<int> &ids);
+
+private:
+ quintptr m_tag;
+ QString m_text;
+ QIcon m_icon;
+ QPlatformMenu *m_subMenu;
+ MenuRole m_role : 4;
+ bool m_isEnabled : 1;
+ bool m_isVisible : 1;
+ bool m_isSeparator : 1;
+ bool m_isCheckable : 1;
+ bool m_isChecked : 1;
+ int m_dbusID : 16;
+ bool m_hasExclusiveGroup : 1;
+ int m_reserved : 6;
+ QKeySequence m_shortcut;
+};
+
+class QDBusPlatformMenu : public QPlatformMenu
+{
+ Q_OBJECT
+
+public:
+ QDBusPlatformMenu(quintptr tag = 0LL);
+ ~QDBusPlatformMenu();
+ void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
+ void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
+ void syncSubMenu(const QDBusPlatformMenu *menu);
+ void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
+ void syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE { Q_UNUSED(enable); }
+
+ quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
+ void setTag(quintptr tag) Q_DECL_OVERRIDE;
+
+ const QString text() const { return m_text; }
+ void setText(const QString &text) Q_DECL_OVERRIDE;
+ QIcon icon() const { return m_icon; }
+ void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
+ bool isEnabled() const Q_DECL_OVERRIDE { return m_isEnabled; }
+ void setEnabled(bool enabled) Q_DECL_OVERRIDE;
+ bool isVisible() const { return m_isVisible; }
+ void setVisible(bool visible) Q_DECL_OVERRIDE;
+ void setMinimumWidth(int width) Q_DECL_OVERRIDE { Q_UNUSED(width); }
+ void setFont(const QFont &font) Q_DECL_OVERRIDE { Q_UNUSED(font); }
+ void setMenuType(MenuType type) Q_DECL_OVERRIDE { Q_UNUSED(type); }
+ void setContainingMenuItem(QDBusPlatformMenuItem *item);
+
+ void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) Q_DECL_OVERRIDE
+ {
+ Q_UNUSED(parentWindow);
+ Q_UNUSED(targetRect);
+ Q_UNUSED(item);
+ setVisible(true);
+ }
+
+ void dismiss() Q_DECL_OVERRIDE { } // Closes this and all its related menu popups
+
+ QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE;
+ const QList<QDBusPlatformMenuItem *> items() const;
+
+ QPlatformMenuItem *createMenuItem() const Q_DECL_OVERRIDE;
+ QPlatformMenu *createSubMenu() const Q_DECL_OVERRIDE;
+
+ bool operator==(const QDBusPlatformMenu& other) { return m_tag == other.m_tag; }
+
+ uint revision() const { return m_revision; }
+
+ void emitUpdated();
+
+signals:
+ void updated(uint revision, int dbusId);
+ void propertiesUpdated(QDBusMenuItemList updatedProps, QDBusMenuItemKeysList removedProps);
+
+private:
+ quintptr m_tag;
+ QString m_text;
+ QIcon m_icon;
+ bool m_isEnabled;
+ bool m_isVisible;
+ bool m_isSeparator;
+ uint m_revision;
+ QHash<quintptr, QDBusPlatformMenuItem *> m_itemsByTag;
+ QList<QDBusPlatformMenuItem *> m_items;
+ QDBusPlatformMenuItem *m_containingMenuItem;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/platformsupport/themes/genericunix/dbustray/dbustray.pri b/src/platformsupport/themes/genericunix/dbustray/dbustray.pri
new file mode 100644
index 0000000000..f703e24ba9
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/dbustray.pri
@@ -0,0 +1,15 @@
+QT_FOR_PRIVATE += dbus
+
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qdbustrayicon_p.h \
+ $$PWD/qdbustraytypes_p.h \
+ $$PWD/qstatusnotifieritemadaptor_p.h \
+ $$PWD/qxdgnotificationproxy_p.h \
+
+SOURCES += \
+ $$PWD/qdbustrayicon.cpp \
+ $$PWD/qdbustraytypes.cpp \
+ $$PWD/qstatusnotifieritemadaptor.cpp \
+ $$PWD/qxdgnotificationproxy.cpp \
diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp b/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
new file mode 100644
index 0000000000..95e9651e9a
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdbustrayicon_p.h"
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include "qdbusmenuconnection_p.h"
+#include "qstatusnotifieritemadaptor_p.h"
+#include "qdbusmenuadaptor_p.h"
+#include "qdbusplatformmenu_p.h"
+#include "qxdgnotificationproxy_p.h"
+
+#include <qpa/qplatformmenu.h>
+#include <qstring.h>
+#include <qdebug.h>
+#include <qrect.h>
+#include <qloggingcategory.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformservices.h>
+#include <qdbusconnectioninterface.h>
+#include <private/qlockfile_p.h>
+#include <private/qguiapplication_p.h>
+
+// Defined in Windows headers which get included by qlockfile_p.h
+#undef interface
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcTray, "qt.qpa.tray")
+
+static const QString KDEItemFormat = QStringLiteral("org.kde.StatusNotifierItem-%1-%2");
+static const QString KDEWatcherService = QStringLiteral("org.kde.StatusNotifierWatcher");
+static const QString TempFileTemplate = QDir::tempPath() + QLatin1String("/qt-trayicon-XXXXXX.png");
+static const QString XdgNotificationService = QStringLiteral("org.freedesktop.Notifications");
+static const QString XdgNotificationPath = QStringLiteral("/org/freedesktop/Notifications");
+static const QString DefaultAction = QStringLiteral("default");
+static int instanceCount = 0;
+
+/*!
+ \class QDBusTrayIcon
+ \internal
+*/
+
+QDBusTrayIcon::QDBusTrayIcon()
+ : m_dbusConnection(Q_NULLPTR)
+ , m_adaptor(new QStatusNotifierItemAdaptor(this))
+ , m_menuAdaptor(Q_NULLPTR)
+ , m_menu(Q_NULLPTR)
+ , m_notifier(Q_NULLPTR)
+ , m_instanceId(KDEItemFormat.arg(QCoreApplication::applicationPid()).arg(++instanceCount))
+ , m_category(QStringLiteral("ApplicationStatus"))
+ , m_defaultStatus(QStringLiteral("Active")) // be visible all the time. QSystemTrayIcon has no API to control this.
+ , m_status(m_defaultStatus)
+ , m_tempIcon(Q_NULLPTR)
+ , m_tempAttentionIcon(Q_NULLPTR)
+ , m_registered(false)
+{
+ qCDebug(qLcTray);
+ if (instanceCount == 1) {
+ QDBusMenuItem::registerDBusTypes();
+ qDBusRegisterMetaType<QXdgDBusImageStruct>();
+ qDBusRegisterMetaType<QXdgDBusImageVector>();
+ qDBusRegisterMetaType<QXdgDBusToolTipStruct>();
+ }
+ connect(this, SIGNAL(statusChanged(QString)), m_adaptor, SIGNAL(NewStatus(QString)));
+ connect(this, SIGNAL(tooltipChanged()), m_adaptor, SIGNAL(NewToolTip()));
+ connect(this, SIGNAL(iconChanged()), m_adaptor, SIGNAL(NewIcon()));
+ connect(this, SIGNAL(attention()), m_adaptor, SIGNAL(NewAttentionIcon()));
+ connect(this, SIGNAL(attention()), m_adaptor, SIGNAL(NewTitle()));
+ connect(&m_attentionTimer, SIGNAL(timeout()), this, SLOT(attentionTimerExpired()));
+ m_attentionTimer.setSingleShot(true);
+}
+
+QDBusTrayIcon::~QDBusTrayIcon()
+{
+}
+
+void QDBusTrayIcon::init()
+{
+ qCDebug(qLcTray) << "registering" << m_instanceId;
+ m_registered = dBusConnection()->registerTrayIcon(this);
+}
+
+void QDBusTrayIcon::cleanup()
+{
+ qCDebug(qLcTray) << "unregistering" << m_instanceId;
+ if (m_registered)
+ dBusConnection()->unregisterTrayIcon(this);
+ delete m_dbusConnection;
+ m_dbusConnection = Q_NULLPTR;
+ delete m_notifier;
+ m_notifier = Q_NULLPTR;
+ m_registered = false;
+}
+
+void QDBusTrayIcon::attentionTimerExpired()
+{
+ m_messageTitle = QString();
+ m_message = QString();
+ m_attentionIcon = QIcon();
+ emit attention();
+ emit tooltipChanged();
+ setStatus(m_defaultStatus);
+}
+
+void QDBusTrayIcon::setStatus(const QString &status)
+{
+ qCDebug(qLcTray) << status;
+ if (m_status == status)
+ return;
+ m_status = status;
+ emit statusChanged(m_status);
+}
+
+QTemporaryFile *QDBusTrayIcon::tempIcon(const QIcon &icon)
+{
+ // Hack for indicator-application, which doesn't handle icons sent across D-Bus:
+ // save the icon to a temp file and set the icon name to that filename.
+ static bool necessity_checked = false;
+ static bool necessary = false;
+ if (!necessity_checked) {
+ QDBusConnection session = QDBusConnection::sessionBus();
+ uint pid = session.interface()->servicePid(KDEWatcherService).value();
+ QString processName = QLockFilePrivate::processNameByPid(pid);
+ necessary = processName.endsWith(QLatin1String("indicator-application-service"));
+ necessity_checked = true;
+ }
+ if (!necessary)
+ return Q_NULLPTR;
+ qreal dpr = qGuiApp->devicePixelRatio();
+ QTemporaryFile *ret = new QTemporaryFile(TempFileTemplate, this);
+ ret->open();
+ icon.pixmap(QSize(22 * dpr, 22 * dpr)).save(ret);
+ ret->close();
+ return ret;
+}
+
+QDBusMenuConnection * QDBusTrayIcon::dBusConnection()
+{
+ if (!m_dbusConnection) {
+ m_dbusConnection = new QDBusMenuConnection(this, m_instanceId);
+ m_notifier = new QXdgNotificationInterface(XdgNotificationService,
+ XdgNotificationPath, m_dbusConnection->connection(), this);
+ connect(m_notifier, SIGNAL(NotificationClosed(uint,uint)), this, SLOT(notificationClosed(uint,uint)));
+ connect(m_notifier, SIGNAL(ActionInvoked(uint,QString)), this, SLOT(actionInvoked(uint,QString)));
+ }
+ return m_dbusConnection;
+}
+
+void QDBusTrayIcon::updateIcon(const QIcon &icon)
+{
+ m_iconName = icon.name();
+ m_icon = icon;
+ if (m_iconName.isEmpty()) {
+ if (m_tempIcon)
+ delete m_tempIcon;
+ m_tempIcon = tempIcon(icon);
+ if (m_tempIcon)
+ m_iconName = m_tempIcon->fileName();
+ }
+ qCDebug(qLcTray) << m_iconName << icon.availableSizes();
+ emit iconChanged();
+}
+
+void QDBusTrayIcon::updateToolTip(const QString &tooltip)
+{
+ qCDebug(qLcTray) << tooltip;
+ m_tooltip = tooltip;
+ emit tooltipChanged();
+}
+
+QPlatformMenu *QDBusTrayIcon::createMenu() const
+{
+ return new QDBusPlatformMenu();
+}
+
+void QDBusTrayIcon::updateMenu(QPlatformMenu * menu)
+{
+ qCDebug(qLcTray) << menu;
+ bool needsRegistering = !m_menu;
+ if (!m_menu)
+ m_menu = qobject_cast<QDBusPlatformMenu *>(menu);
+ if (!m_menuAdaptor) {
+ m_menuAdaptor = new QDBusMenuAdaptor(m_menu);
+ // TODO connect(m_menu, , m_menuAdaptor, SIGNAL(ItemActivationRequested(int,uint)));
+ connect(m_menu, SIGNAL(propertiesUpdated(QDBusMenuItemList,QDBusMenuItemKeysList)),
+ m_menuAdaptor, SIGNAL(ItemsPropertiesUpdated(QDBusMenuItemList,QDBusMenuItemKeysList)));
+ connect(m_menu, SIGNAL(updated(uint,int)),
+ m_menuAdaptor, SIGNAL(LayoutUpdated(uint,int)));
+ }
+ m_menu->emitUpdated();
+ if (needsRegistering)
+ dBusConnection()->registerTrayIconMenu(this);
+}
+
+void QDBusTrayIcon::showMessage(const QString &title, const QString &msg, const QIcon &icon,
+ QPlatformSystemTrayIcon::MessageIcon iconType, int msecs)
+{
+ m_messageTitle = title;
+ m_message = msg;
+ m_attentionIcon = icon;
+ QStringList notificationActions;
+ switch (iconType) {
+ case Information:
+ m_attentionIconName = QStringLiteral("dialog-information");
+ break;
+ case Warning:
+ m_attentionIconName = QStringLiteral("dialog-warning");
+ break;
+ case Critical:
+ m_attentionIconName = QStringLiteral("dialog-error");
+ // If there are actions, the desktop notification may appear as a message dialog
+ // with button(s), which will interrupt the user and require a response.
+ // That is an optional feature in implementations of org.freedesktop.Notifications
+ notificationActions << DefaultAction << tr("OK");
+ break;
+ default:
+ m_attentionIconName.clear();
+ break;
+ }
+ if (m_attentionIconName.isEmpty()) {
+ if (m_tempAttentionIcon)
+ delete m_tempAttentionIcon;
+ m_tempAttentionIcon = tempIcon(icon);
+ if (m_tempAttentionIcon)
+ m_attentionIconName = m_tempAttentionIcon->fileName();
+ }
+ qCDebug(qLcTray) << title << msg <<
+ QPlatformSystemTrayIcon::metaObject()->enumerator(
+ QPlatformSystemTrayIcon::staticMetaObject.indexOfEnumerator("MessageIcon")).valueToKey(iconType)
+ << m_attentionIconName << msecs;
+ setStatus(QStringLiteral("NeedsAttention"));
+ m_attentionTimer.start(msecs);
+ emit tooltipChanged();
+ emit attention();
+
+ // Desktop notification
+ QVariantMap hints;
+ // urgency levels according to https://developer.gnome.org/notification-spec/#urgency-levels
+ // 0 low, 1 normal, 2 critical
+ int urgency = static_cast<int>(iconType) - 1;
+ if (urgency < 0) // no icon
+ urgency = 0;
+ hints.insert(QLatin1String("urgency"), QVariant(urgency));
+ m_notifier->notify(QCoreApplication::applicationName(), 0,
+ m_attentionIconName, title, msg, notificationActions, hints, msecs);
+}
+
+void QDBusTrayIcon::actionInvoked(uint id, const QString &action)
+{
+ qCDebug(qLcTray) << id << action;
+ emit messageClicked();
+}
+
+void QDBusTrayIcon::notificationClosed(uint id, uint reason)
+{
+ qCDebug(qLcTray) << id << reason;
+}
+
+bool QDBusTrayIcon::isSystemTrayAvailable() const
+{
+ QDBusMenuConnection * conn = const_cast<QDBusTrayIcon *>(this)->dBusConnection();
+ qCDebug(qLcTray) << conn->isStatusNotifierHostRegistered();
+ return conn->isStatusNotifierHostRegistered();
+}
+
+QT_END_NAMESPACE
+#endif //QT_NO_SYSTEMTRAYICON
diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon_p.h b/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon_p.h
new file mode 100644
index 0000000000..a383ef86fc
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qdbustrayicon_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QDBUSTRAYICON_H
+#define QDBUSTRAYICON_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include <QIcon>
+#include <QTemporaryFile>
+#include <QTimer>
+#include "QtGui/qpa/qplatformsystemtrayicon.h"
+#include "private/qdbusmenuconnection_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QStatusNotifierItemAdaptor;
+class QDBusMenuAdaptor;
+class QDBusPlatformMenu;
+class QXdgNotificationInterface;
+
+class QDBusTrayIcon: public QPlatformSystemTrayIcon
+{
+ Q_OBJECT
+ Q_PROPERTY(QString category READ category NOTIFY categoryChanged)
+ Q_PROPERTY(QString status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QString tooltip READ tooltip NOTIFY tooltipChanged)
+ Q_PROPERTY(QString iconName READ iconName NOTIFY iconChanged)
+ Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
+ Q_PROPERTY(bool isRequestingAttention READ isRequestingAttention NOTIFY attention)
+ Q_PROPERTY(QString attentionTitle READ attentionTitle NOTIFY attention)
+ Q_PROPERTY(QString attentionMessage READ attentionMessage NOTIFY attention)
+ Q_PROPERTY(QString attentionIconName READ attentionIconName NOTIFY attention)
+ Q_PROPERTY(QIcon attentionIcon READ attentionIcon NOTIFY attention)
+ Q_PROPERTY(QDBusPlatformMenu *menu READ menu NOTIFY menuChanged)
+
+public:
+ QDBusTrayIcon();
+
+ virtual ~QDBusTrayIcon();
+
+ QDBusMenuConnection * dBusConnection();
+
+ void init() Q_DECL_OVERRIDE;
+ void cleanup() Q_DECL_OVERRIDE;
+ void updateIcon(const QIcon &icon) Q_DECL_OVERRIDE;
+ void updateToolTip(const QString &tooltip) Q_DECL_OVERRIDE;
+ void updateMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
+ QPlatformMenu *createMenu() const Q_DECL_OVERRIDE;
+ void showMessage(const QString &title, const QString &msg,
+ const QIcon &icon, MessageIcon iconType, int msecs) Q_DECL_OVERRIDE;
+
+ bool isSystemTrayAvailable() const Q_DECL_OVERRIDE;
+ bool supportsMessages() const Q_DECL_OVERRIDE { return true; }
+ QRect geometry() const Q_DECL_OVERRIDE { return QRect(); }
+
+ QString category() const { return m_category; }
+ QString status() const { return m_status; }
+ QString tooltip() const { return m_tooltip; }
+
+ QString iconName() const { return m_iconName; }
+ const QIcon & icon() const { return m_icon; }
+
+ bool isRequestingAttention() const { return m_attentionTimer.isActive(); }
+ QString attentionTitle() const { return m_messageTitle; }
+ QString attentionMessage() const { return m_message; }
+ QString attentionIconName() const { return m_attentionIconName; }
+ const QIcon & attentionIcon() const { return m_attentionIcon; }
+
+ QString instanceId() const { return m_instanceId; }
+
+ QDBusPlatformMenu *menu() { return m_menu; }
+
+signals:
+ void categoryChanged();
+ void statusChanged(QString arg);
+ void tooltipChanged();
+ void iconChanged();
+ void attention();
+ void menuChanged();
+
+private Q_SLOTS:
+ void attentionTimerExpired();
+ void actionInvoked(uint id, const QString &action);
+ void notificationClosed(uint id, uint reason);
+
+private:
+ void setStatus(const QString &status);
+ QTemporaryFile *tempIcon(const QIcon &icon);
+
+private:
+ QDBusMenuConnection* m_dbusConnection;
+ QStatusNotifierItemAdaptor *m_adaptor;
+ QDBusMenuAdaptor *m_menuAdaptor;
+ QDBusPlatformMenu *m_menu;
+ QXdgNotificationInterface *m_notifier;
+ QString m_instanceId;
+ QString m_category;
+ QString m_defaultStatus;
+ QString m_status;
+ QString m_tooltip;
+ QString m_messageTitle;
+ QString m_message;
+ QIcon m_icon;
+ QTemporaryFile *m_tempIcon;
+ QString m_iconName;
+ QIcon m_attentionIcon;
+ QTemporaryFile *m_tempAttentionIcon;
+ QString m_attentionIconName;
+ QTimer m_attentionTimer;
+ bool m_isRequestingAttention;
+ bool m_hasMenu;
+ bool m_registered;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMTRAYICON
+#endif // QDBUSTRAYICON_H
diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp
new file mode 100644
index 0000000000..fc0fa00655
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Marco Martin <notmart@gmail.com>
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include "qdbustraytypes_p.h"
+
+#include <QDBusConnection>
+#include <QDBusMetaType>
+#include <QImage>
+#include <QIcon>
+#include <QImage>
+#include <QPixmap>
+#include <QDebug>
+#include <QtEndian>
+#include <QPainter>
+#include <QGuiApplication>
+#include <qpa/qplatformmenu.h>
+#include "qdbusplatformmenu_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static const int IconSizeLimit = 64;
+static const int IconNormalSmallSize = 22;
+static const int IconNormalMediumSize = 64;
+
+QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
+{
+ QXdgDBusImageVector ret;
+ QList<QSize> sizes = icon.availableSizes();
+
+ // Omit any size larger than 64 px, to save D-Bus bandwidth;
+ // ensure that 22px or smaller exists, because it's a common size;
+ // and ensure that something between 22px and 64px exists, for better scaling to other sizes.
+ bool hasSmallIcon = false;
+ bool hasMediumIcon = false;
+ qreal dpr = qGuiApp->devicePixelRatio();
+ QList<QSize> toRemove;
+ Q_FOREACH (const QSize &size, sizes) {
+ int maxSize = qMax(size.width(), size.height());
+ if (maxSize <= IconNormalSmallSize * dpr)
+ hasSmallIcon = true;
+ else if (maxSize <= IconNormalMediumSize * dpr)
+ hasMediumIcon = true;
+ else if (maxSize > IconSizeLimit * dpr)
+ toRemove << size;
+ }
+ Q_FOREACH (const QSize &size, toRemove)
+ sizes.removeOne(size);
+ if (!hasSmallIcon)
+ sizes.append(QSize(IconNormalSmallSize * dpr, IconNormalSmallSize * dpr));
+ if (!hasMediumIcon)
+ sizes.append(QSize(IconNormalMediumSize * dpr, IconNormalMediumSize * dpr));
+
+ ret.reserve(sizes.size());
+ foreach (QSize size, sizes) {
+ // Protocol specifies ARGB32 format in network byte order
+ QImage im = icon.pixmap(size).toImage().convertToFormat(QImage::Format_ARGB32);
+ // letterbox if necessary to make it square
+ if (im.height() != im.width()) {
+ int maxSize = qMax(im.width(), im.height());
+ QImage padded(maxSize, maxSize, QImage::Format_ARGB32);
+ padded.fill(Qt::transparent);
+ QPainter painter(&padded);
+ painter.drawImage((maxSize - im.width()) / 2, (maxSize - im.height()) / 2, im);
+ im = padded;
+ }
+ // copy and endian-convert
+ QXdgDBusImageStruct kim(im.width(), im.height());
+ const uchar *end = im.constBits() + im.byteCount();
+ uchar *dest = reinterpret_cast<uchar *>(kim.data.data());
+ for (const uchar *src = im.constBits(); src < end; src += 4, dest += 4)
+ qToUnaligned(qToBigEndian<quint32>(qFromUnaligned<quint32>(src)), dest);
+
+ ret << kim;
+ }
+ return ret;
+}
+
+// Marshall the ImageStruct data into a D-Bus argument
+const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusImageStruct &icon)
+{
+ argument.beginStructure();
+ argument << icon.width;
+ argument << icon.height;
+ argument << icon.data;
+ argument.endStructure();
+ return argument;
+}
+
+// Retrieve the ImageStruct data from the D-Bus argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusImageStruct &icon)
+{
+ qint32 width;
+ qint32 height;
+ QByteArray data;
+
+ argument.beginStructure();
+ argument >> width;
+ argument >> height;
+ argument >> data;
+ argument.endStructure();
+
+ icon.width = width;
+ icon.height = height;
+ icon.data = data;
+
+ return argument;
+}
+
+// Marshall the ImageVector data into a D-Bus argument
+const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusImageVector &iconVector)
+{
+ argument.beginArray(qMetaTypeId<QXdgDBusImageStruct>());
+ for (int i = 0; i < iconVector.size(); ++i) {
+ argument << iconVector[i];
+ }
+ argument.endArray();
+ return argument;
+}
+
+// Retrieve the ImageVector data from the D-Bus argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusImageVector &iconVector)
+{
+ argument.beginArray();
+ iconVector.clear();
+
+ while (!argument.atEnd()) {
+ QXdgDBusImageStruct element;
+ argument >> element;
+ iconVector.append(element);
+ }
+
+ argument.endArray();
+
+ return argument;
+}
+
+// Marshall the ToolTipStruct data into a D-Bus argument
+const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusToolTipStruct &toolTip)
+{
+ argument.beginStructure();
+ argument << toolTip.icon;
+ argument << toolTip.image;
+ argument << toolTip.title;
+ argument << toolTip.subTitle;
+ argument.endStructure();
+ return argument;
+}
+
+// Retrieve the ToolTipStruct data from the D-Bus argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusToolTipStruct &toolTip)
+{
+ QString icon;
+ QXdgDBusImageVector image;
+ QString title;
+ QString subTitle;
+
+ argument.beginStructure();
+ argument >> icon;
+ argument >> image;
+ argument >> title;
+ argument >> subTitle;
+ argument.endStructure();
+
+ toolTip.icon = icon;
+ toolTip.image = image;
+ toolTip.title = title;
+ toolTip.subTitle = subTitle;
+
+ return argument;
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes_p.h b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes_p.h
new file mode 100644
index 0000000000..1bdc855c3c
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Marco Martin <notmart@gmail.com>
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSTRAYTYPES_P_H
+#define QDBUSTRAYTYPES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include <QObject>
+#include <QString>
+#include <QDBusArgument>
+#include <QDBusConnection>
+#include <QDBusObjectPath>
+#include <QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+// Custom message type to send icons across D-Bus
+struct QXdgDBusImageStruct
+{
+ QXdgDBusImageStruct() { }
+ QXdgDBusImageStruct(int w, int h)
+ : width(w), height(h), data(width * height * 4, 0) { }
+ int width;
+ int height;
+ QByteArray data;
+};
+Q_DECLARE_TYPEINFO(QXdgDBusImageStruct, Q_MOVABLE_TYPE);
+
+typedef QVector<QXdgDBusImageStruct> QXdgDBusImageVector;
+
+QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon);
+
+// Custom message type to send tooltips across D-Bus
+struct QXdgDBusToolTipStruct
+{
+ QString icon;
+ QXdgDBusImageVector image;
+ QString title;
+ QString subTitle;
+};
+Q_DECLARE_TYPEINFO(QXdgDBusToolTipStruct, Q_MOVABLE_TYPE);
+
+const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusImageStruct &icon);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusImageStruct &icon);
+
+const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusImageVector &iconVector);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusImageVector &iconVector);
+
+const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusToolTipStruct &toolTip);
+const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusToolTipStruct &toolTip);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QXdgDBusImageStruct)
+Q_DECLARE_METATYPE(QXdgDBusImageVector)
+Q_DECLARE_METATYPE(QXdgDBusToolTipStruct)
+
+#endif // QT_NO_SYSTEMTRAYICON
+#endif // QDBUSTRAYTYPES_P_H
diff --git a/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp b/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp
new file mode 100644
index 0000000000..d3c5454f01
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ This file was originally created by qdbusxml2cpp version 0.8
+ Command line was:
+ qdbusxml2cpp -a statusnotifieritem ../../3rdparty/dbus-ifaces/org.kde.StatusNotifierItem.xml
+
+ However it is maintained manually, because this adapter needs to do
+ significant interface adaptation, and can do it more efficiently using the
+ QDBusTrayIcon API directly rather than via QObject::property() and
+ QMetaObject::invokeMethod().
+*/
+
+#include "qstatusnotifieritemadaptor_p.h"
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include "qdbustrayicon_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcMenu)
+Q_DECLARE_LOGGING_CATEGORY(qLcTray)
+
+QStatusNotifierItemAdaptor::QStatusNotifierItemAdaptor(QDBusTrayIcon *parent)
+ : QDBusAbstractAdaptor(parent), m_trayIcon(parent)
+{
+ setAutoRelaySignals(true);
+}
+
+QStatusNotifierItemAdaptor::~QStatusNotifierItemAdaptor()
+{
+}
+
+QString QStatusNotifierItemAdaptor::attentionIconName() const
+{
+ return m_trayIcon->attentionIconName();
+}
+
+QXdgDBusImageVector QStatusNotifierItemAdaptor::attentionIconPixmap() const
+{
+ return iconToQXdgDBusImageVector(m_trayIcon->attentionIcon());
+}
+
+QString QStatusNotifierItemAdaptor::attentionMovieName() const
+{
+ return QString();
+}
+
+QString QStatusNotifierItemAdaptor::category() const
+{
+ return m_trayIcon->category();
+}
+
+QString QStatusNotifierItemAdaptor::iconName() const
+{
+ return m_trayIcon->iconName();
+}
+
+QXdgDBusImageVector QStatusNotifierItemAdaptor::iconPixmap() const
+{
+ return iconToQXdgDBusImageVector(m_trayIcon->icon());
+}
+
+QString QStatusNotifierItemAdaptor::id() const
+{
+ // from the API docs: "a name that should be unique for this application and
+ // consistent between sessions, such as the application name itself"
+ return QCoreApplication::applicationName();
+}
+
+bool QStatusNotifierItemAdaptor::itemIsMenu() const
+{
+ // From KDE docs: if this is true, the item only supports the context menu,
+ // so the visualization should prefer sending ContextMenu() instead of Activate().
+ // But QSystemTrayIcon doesn't have such a setting: it will emit activated()
+ // and the application is free to use it or ignore it; we don't know whether it will.
+ return false;
+}
+
+QDBusObjectPath QStatusNotifierItemAdaptor::menu() const
+{
+ return QDBusObjectPath(m_trayIcon->menu() ? "/MenuBar" : "/NO_DBUSMENU");
+}
+
+QString QStatusNotifierItemAdaptor::overlayIconName() const
+{
+ return QString();
+}
+
+QXdgDBusImageVector QStatusNotifierItemAdaptor::overlayIconPixmap() const
+{
+ QXdgDBusImageVector ret; // empty vector
+ return ret;
+}
+
+QString QStatusNotifierItemAdaptor::status() const
+{
+ return m_trayIcon->status();
+}
+
+QString QStatusNotifierItemAdaptor::title() const
+{
+ // Shown e.g. when the icon is hidden, in the popup showing all hidden items.
+ // Since QSystemTrayIcon doesn't have this property, the application name
+ // is the best information we have available.
+ return QCoreApplication::applicationName();
+}
+
+QXdgDBusToolTipStruct QStatusNotifierItemAdaptor::toolTip() const
+{
+ QXdgDBusToolTipStruct ret;
+ if (m_trayIcon->isRequestingAttention()) {
+ ret.title = m_trayIcon->attentionTitle();
+ ret.subTitle = m_trayIcon->attentionMessage();
+ ret.icon = m_trayIcon->attentionIconName();
+ } else {
+ ret.title = m_trayIcon->tooltip();
+ }
+ return ret;
+}
+
+void QStatusNotifierItemAdaptor::Activate(int x, int y)
+{
+ qCDebug(qLcTray) << x << y;
+ emit m_trayIcon->activated(QPlatformSystemTrayIcon::Trigger);
+}
+
+void QStatusNotifierItemAdaptor::ContextMenu(int x, int y)
+{
+ qCDebug(qLcTray) << x << y;
+ emit m_trayIcon->activated(QPlatformSystemTrayIcon::Context);
+}
+
+void QStatusNotifierItemAdaptor::Scroll(int w, const QString &s)
+{
+ qCDebug(qLcTray) << w << s;
+ // unsupported
+}
+
+void QStatusNotifierItemAdaptor::SecondaryActivate(int x, int y)
+{
+ qCDebug(qLcTray) << x << y;
+ emit m_trayIcon->activated(QPlatformSystemTrayIcon::MiddleClick);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor_p.h b/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor_p.h
new file mode 100644
index 0000000000..776e1b23ef
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qstatusnotifieritemadaptor_p.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ This file was originally created by qdbusxml2cpp version 0.8
+ Command line was:
+ qdbusxml2cpp -a statusnotifieritem ../../3rdparty/dbus-ifaces/org.kde.StatusNotifierItem.xml
+
+ However it is maintained manually.
+
+ It is also not part of the public API. This header file may change from
+ version to version without notice, or even be removed.
+*/
+
+#ifndef QSTATUSNOTIFIERITEMADAPTER_P_H
+#define QSTATUSNOTIFIERITEMADAPTER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+
+#include "qdbustraytypes_p.h"
+
+QT_BEGIN_NAMESPACE
+class QDBusTrayIcon;
+
+/*
+ Adaptor class for interface org.kde.StatusNotifierItem
+ see http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/
+ (also http://www.notmart.org/misc/statusnotifieritem/)
+*/
+class QStatusNotifierItemAdaptor: public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "org.kde.StatusNotifierItem")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"org.kde.StatusNotifierItem\">\n"
+" <property access=\"read\" type=\"s\" name=\"Category\"/>\n"
+" <property access=\"read\" type=\"s\" name=\"Id\"/>\n"
+" <property access=\"read\" type=\"s\" name=\"Title\"/>\n"
+" <property access=\"read\" type=\"s\" name=\"Status\"/>\n"
+" <property access=\"read\" type=\"i\" name=\"WindowId\"/>\n"
+" <property access=\"read\" type=\"s\" name=\"IconThemePath\"/>\n"
+" <property access=\"read\" type=\"o\" name=\"Menu\"/>\n"
+" <property access=\"read\" type=\"b\" name=\"ItemIsMenu\"/>\n"
+" <property access=\"read\" type=\"s\" name=\"IconName\"/>\n"
+" <property access=\"read\" type=\"a(iiay)\" name=\"IconPixmap\">\n"
+" <annotation value=\"QXdgDBusImageVector\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
+" </property>\n"
+" <property access=\"read\" type=\"s\" name=\"OverlayIconName\"/>\n"
+" <property access=\"read\" type=\"a(iiay)\" name=\"OverlayIconPixmap\">\n"
+" <annotation value=\"QXdgDBusImageVector\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
+" </property>\n"
+" <property access=\"read\" type=\"s\" name=\"AttentionIconName\"/>\n"
+" <property access=\"read\" type=\"a(iiay)\" name=\"AttentionIconPixmap\">\n"
+" <annotation value=\"QXdgDBusImageVector\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
+" </property>\n"
+" <property access=\"read\" type=\"s\" name=\"AttentionMovieName\"/>\n"
+" <property access=\"read\" type=\"(sa(iiay)ss)\" name=\"ToolTip\">\n"
+" <annotation value=\"QXdgDBusToolTipStruct\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
+" </property>\n"
+" <method name=\"ContextMenu\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
+" </method>\n"
+" <method name=\"Activate\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
+" </method>\n"
+" <method name=\"SecondaryActivate\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
+" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
+" </method>\n"
+" <method name=\"Scroll\">\n"
+" <arg direction=\"in\" type=\"i\" name=\"delta\"/>\n"
+" <arg direction=\"in\" type=\"s\" name=\"orientation\"/>\n"
+" </method>\n"
+" <signal name=\"NewTitle\"/>\n"
+" <signal name=\"NewIcon\"/>\n"
+" <signal name=\"NewAttentionIcon\"/>\n"
+" <signal name=\"NewOverlayIcon\"/>\n"
+" <signal name=\"NewToolTip\"/>\n"
+" <signal name=\"NewStatus\">\n"
+" <arg type=\"s\" name=\"status\"/>\n"
+" </signal>\n"
+" </interface>\n"
+ "")
+public:
+ QStatusNotifierItemAdaptor(QDBusTrayIcon *parent);
+ virtual ~QStatusNotifierItemAdaptor();
+
+public: // PROPERTIES
+ Q_PROPERTY(QString AttentionIconName READ attentionIconName)
+ QString attentionIconName() const;
+
+ Q_PROPERTY(QXdgDBusImageVector AttentionIconPixmap READ attentionIconPixmap)
+ QXdgDBusImageVector attentionIconPixmap() const;
+
+ Q_PROPERTY(QString AttentionMovieName READ attentionMovieName)
+ QString attentionMovieName() const;
+
+ Q_PROPERTY(QString Category READ category)
+ QString category() const;
+
+ Q_PROPERTY(QString IconName READ iconName)
+ QString iconName() const;
+
+ Q_PROPERTY(QXdgDBusImageVector IconPixmap READ iconPixmap)
+ QXdgDBusImageVector iconPixmap() const;
+
+ Q_PROPERTY(QString Id READ id)
+ QString id() const;
+
+ Q_PROPERTY(bool ItemIsMenu READ itemIsMenu)
+ bool itemIsMenu() const;
+
+ Q_PROPERTY(QDBusObjectPath Menu READ menu)
+ QDBusObjectPath menu() const;
+
+ Q_PROPERTY(QString OverlayIconName READ overlayIconName)
+ QString overlayIconName() const;
+
+ Q_PROPERTY(QXdgDBusImageVector OverlayIconPixmap READ overlayIconPixmap)
+ QXdgDBusImageVector overlayIconPixmap() const;
+
+ Q_PROPERTY(QString Status READ status)
+ QString status() const;
+
+ Q_PROPERTY(QString Title READ title)
+ QString title() const;
+
+ Q_PROPERTY(QXdgDBusToolTipStruct ToolTip READ toolTip)
+ QXdgDBusToolTipStruct toolTip() const;
+
+public Q_SLOTS: // METHODS
+ void Activate(int x, int y);
+ void ContextMenu(int x, int y);
+ void Scroll(int delta, const QString &orientation);
+ void SecondaryActivate(int x, int y);
+Q_SIGNALS: // SIGNALS
+ void NewAttentionIcon();
+ void NewIcon();
+ void NewOverlayIcon();
+ void NewStatus(const QString &status);
+ void NewTitle();
+ void NewToolTip();
+
+private:
+ QDBusTrayIcon *m_trayIcon;
+};
+
+QT_END_NAMESPACE
+#endif // QT_NO_SYSTEMTRAYICON
+#endif // QSTATUSNOTIFIERITEMADAPTER_P_H
diff --git a/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy.cpp b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy.cpp
new file mode 100644
index 0000000000..ef2aa799c8
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxdgnotificationproxy_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QXdgNotificationInterface::QXdgNotificationInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
+ : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
+{
+}
+
+QXdgNotificationInterface::~QXdgNotificationInterface()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
new file mode 100644
index 0000000000..03899723ab
--- /dev/null
+++ b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ This file was originally created by qdbusxml2cpp version 0.8
+ Command line was:
+ qdbusxml2cpp -p qxdgnotificationproxy ../../3rdparty/dbus-ifaces/org.freedesktop.Notifications.xml
+
+ However it is maintained manually.
+
+ It is also not part of the public API. This header file may change from
+ version to version without notice, or even be removed.
+*/
+
+#ifndef QXDGNOTIFICATIONPROXY_P_H
+#define QXDGNOTIFICATIONPROXY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+#include <QtDBus/QtDBus>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcTray)
+
+/*
+ * Proxy class for interface org.freedesktop.Notifications
+ */
+class QXdgNotificationInterface: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ static inline const char *staticInterfaceName()
+ { return "org.freedesktop.Notifications"; }
+
+public:
+ QXdgNotificationInterface(const QString &service, const QString &path,
+ const QDBusConnection &connection, QObject *parent = 0);
+
+ ~QXdgNotificationInterface();
+
+public Q_SLOTS: // METHODS
+ inline QDBusPendingReply<> closeNotification(uint id)
+ {
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(id);
+ return asyncCallWithArgumentList(QStringLiteral("CloseNotification"), argumentList);
+ }
+
+ inline QDBusPendingReply<QStringList> getCapabilities()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QStringLiteral("GetCapabilities"), argumentList);
+ }
+
+ inline QDBusPendingReply<QString, QString, QString, QString> getServerInformation()
+ {
+ QList<QVariant> argumentList;
+ return asyncCallWithArgumentList(QStringLiteral("GetServerInformation"), argumentList);
+ }
+ inline QDBusReply<QString> getServerInformation(QString &vendor, QString &version, QString &specVersion)
+ {
+ QList<QVariant> argumentList;
+ QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("GetServerInformation"), argumentList);
+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 4) {
+ vendor = qdbus_cast<QString>(reply.arguments().at(1));
+ version = qdbus_cast<QString>(reply.arguments().at(2));
+ specVersion = qdbus_cast<QString>(reply.arguments().at(3));
+ }
+ return reply;
+ }
+
+ // see https://developer.gnome.org/notification-spec/#basic-design
+ inline QDBusPendingReply<uint> notify(const QString &appName, uint replacesId, const QString &appIcon,
+ const QString &summary, const QString &body, const QStringList &actions,
+ const QVariantMap &hints, int timeout)
+ {
+ qCDebug(qLcTray) << appName << replacesId << appIcon << summary << body << actions << hints << timeout;
+ QList<QVariant> argumentList;
+ argumentList << QVariant::fromValue(appName) << QVariant::fromValue(replacesId) <<
+ QVariant::fromValue(appIcon) << QVariant::fromValue(summary) <<
+ QVariant::fromValue(body) << QVariant::fromValue(actions) <<
+ QVariant::fromValue(hints) << QVariant::fromValue(timeout);
+ return asyncCallWithArgumentList(QStringLiteral("Notify"), argumentList);
+ }
+
+Q_SIGNALS:
+ void ActionInvoked(uint id, const QString &action_key);
+ void NotificationClosed(uint id, uint reason);
+};
+
+namespace org {
+ namespace freedesktop {
+ typedef ::QXdgNotificationInterface Notifications;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/platformsupport/themes/genericunix/genericunix.pri b/src/platformsupport/themes/genericunix/genericunix.pri
index eed48257d0..27019b4aa2 100644
--- a/src/platformsupport/themes/genericunix/genericunix.pri
+++ b/src/platformsupport/themes/genericunix/genericunix.pri
@@ -1,2 +1,7 @@
HEADERS += $$PWD/qgenericunixthemes_p.h
SOURCES += $$PWD/qgenericunixthemes.cpp
+
+qtConfig(dbus) {
+ include(dbusmenu/dbusmenu.pri)
+ include(dbustray/dbustray.pri)
+}