summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/dbustray
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@digia.com>2014-11-28 09:20:19 +0100
committerShawn Rutledge <shawn.rutledge@digia.com>2015-01-22 12:50:51 +0100
commit38abd653774aa0b3c5cdfd9a8b78619605230726 (patch)
tree00dba009a99dfc5c4e85d3f73dd94da1f2120e69 /src/platformsupport/dbustray
parent3c37066062d61a430b8e7f970cccf6effab5a3ef (diff)
QSystemTrayIcon uses D-Bus StatusNotifier on Linux when possible
Implementing org.kde.StatusNotifier DBus interface http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ as well as org.canonical.dbusmenu for the limited purpose of showing the tray icon's context menu. If a desktop environment (such as KDE or Unity) has a StatusNotifierWatcher listening, then tray icon information is sent to be displayed by the tray implementation instead of being rendered directly in an XEmbed window. This is necessary because some modern tray implementations no longer provide XEmbed "hosting". [ChangeLog][QPA][Xcb] QSystemTrayIcon uses StatusNotifier D-Bus protocol when the desktop environment supports it Task-number: QTBUG-31762 Done-with: Marco Martin <mart@kde.org> Change-Id: I3b1f744d621eefc7e9c61d1469460ebfcc77fc54 Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com> Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
Diffstat (limited to 'src/platformsupport/dbustray')
-rw-r--r--src/platformsupport/dbustray/dbustray.pri13
-rw-r--r--src/platformsupport/dbustray/qdbustrayicon.cpp260
-rw-r--r--src/platformsupport/dbustray/qdbustrayicon_p.h160
-rw-r--r--src/platformsupport/dbustray/qdbustraytypes.cpp37
-rw-r--r--src/platformsupport/dbustray/qdbustraytypes_p.h13
-rw-r--r--src/platformsupport/dbustray/qstatusnotifieritemadaptor.cpp174
-rw-r--r--src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h185
7 files changed, 831 insertions, 11 deletions
diff --git a/src/platformsupport/dbustray/dbustray.pri b/src/platformsupport/dbustray/dbustray.pri
new file mode 100644
index 0000000000..ca1ff8e434
--- /dev/null
+++ b/src/platformsupport/dbustray/dbustray.pri
@@ -0,0 +1,13 @@
+QT_FOR_PRIVATE += dbus
+
+INCLUDEPATH += $$PWD $$PWD/../../gui/kernel
+
+HEADERS += \
+ $$PWD/qdbustrayicon_p.h \
+ $$PWD/qdbustraytypes_p.h \
+ $$PWD/qstatusnotifieritemadaptor_p.h \
+
+SOURCES += \
+ $$PWD/qdbustrayicon.cpp \
+ $$PWD/qdbustraytypes.cpp \
+ $$PWD/qstatusnotifieritemadaptor.cpp \
diff --git a/src/platformsupport/dbustray/qdbustrayicon.cpp b/src/platformsupport/dbustray/qdbustrayicon.cpp
new file mode 100644
index 0000000000..1c21da849c
--- /dev/null
+++ b/src/platformsupport/dbustray/qdbustrayicon.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include "qdbustrayicon_p.h"
+#include "qdbusmenuconnection_p.h"
+#include "qstatusnotifieritemadaptor_p.h"
+#include "qdbusmenuadaptor_p.h"
+#include "dbusmenu/qdbusplatformmenu_p.h"
+
+#include <qplatformmenu.h>
+#include <qstring.h>
+#include <qdebug.h>
+#include <qrect.h>
+#include <qloggingcategory.h>
+#include <qplatformintegration.h>
+#include <qplatformservices.h>
+#include <private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcTray, "qt.qpa.tray")
+
+static const QString KDEItemFormat = QStringLiteral("org.kde.StatusNotifierItem-%1-%2");
+static const QString TempFileTemplate = QDir::tempPath() + QStringLiteral("/qt-trayicon-XXXXXX.png");
+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_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)
+{
+ 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;
+ dBusConnection()->registerTrayIcon(this);
+}
+
+void QDBusTrayIcon::cleanup()
+{
+ qCDebug(qLcTray) << "unregistering" << m_instanceId;
+ dBusConnection()->unregisterTrayIcon(this);
+ delete m_dbusConnection;
+ m_dbusConnection = Q_NULLPTR;
+}
+
+void QDBusTrayIcon::activate(int x, int y)
+{
+ qCDebug(qLcTray) << x << y;
+ setStatus(QStringLiteral("Active"));
+}
+
+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 Unity, 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 necessary = (QGuiApplicationPrivate::platformIntegration()->services()->desktopEnvironment().split(':').contains("UNITY"));
+ if (!necessary)
+ return Q_NULLPTR;
+ QTemporaryFile *ret = new QTemporaryFile(TempFileTemplate, this);
+ QSize tempSize;
+ Q_FOREACH (const QSize &size, icon.availableSizes())
+ if (size.width() > tempSize.width())
+ tempSize = size;
+ ret->open();
+ icon.pixmap(tempSize).save(ret);
+ ret->close();
+ return ret;
+}
+
+QDBusMenuConnection * QDBusTrayIcon::dBusConnection()
+{
+ if (!m_dbusConnection)
+ m_dbusConnection = new QDBusMenuConnection(this);
+ 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
+{
+ qCDebug(qLcTray);
+ if (!m_menu)
+ const_cast<QDBusTrayIcon *>(this)->m_menu = new QDBusPlatformMenu();
+ return m_menu;
+}
+
+void QDBusTrayIcon::updateMenu(QPlatformMenu * menu)
+{
+ qCDebug(qLcTray) << 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();
+}
+
+void QDBusTrayIcon::contextMenu(int x, int y)
+{
+ qCDebug(qLcTray) << x << y;
+}
+
+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;
+ 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");
+ 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();
+}
+
+bool QDBusTrayIcon::isSystemTrayAvailable() const
+{
+ QDBusMenuConnection * conn = const_cast<QDBusTrayIcon *>(this)->dBusConnection();
+
+ // If the KDE watcher service is registered, we must be on a desktop
+ // where a StatusNotifier-conforming system tray exists.
+ qCDebug(qLcTray) << conn->isWatcherRegistered();
+ return conn->isWatcherRegistered();
+}
+
+QT_END_NAMESPACE
+#endif //QT_NO_SYSTEMTRAYICON
+
diff --git a/src/platformsupport/dbustray/qdbustrayicon_p.h b/src/platformsupport/dbustray/qdbustrayicon_p.h
new file mode 100644
index 0000000000..1b5f262ef1
--- /dev/null
+++ b/src/platformsupport/dbustray/qdbustrayicon_p.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $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.
+//
+
+#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 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; }
+
+public Q_SLOTS:
+ void activate(int x, int y);
+ void contextMenu(int x, int y);
+
+signals:
+ void categoryChanged();
+ void statusChanged(QString arg);
+ void tooltipChanged();
+ void iconChanged();
+ void attention();
+ void menuChanged();
+
+private Q_SLOTS:
+ void attentionTimerExpired();
+
+private:
+ void setStatus(const QString &status);
+ QTemporaryFile *tempIcon(const QIcon &icon);
+
+private:
+ QDBusMenuConnection* m_dbusConnection;
+ QStatusNotifierItemAdaptor *m_adaptor;
+ QDBusMenuAdaptor *m_menuAdaptor;
+ QDBusPlatformMenu *m_menu;
+ 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;
+};
+
+QT_END_NAMESPACE
+#endif // QT_NO_SYSTEMTRAYICON
+
+#endif // QDBUSTRAYICON_H
diff --git a/src/platformsupport/dbustray/qdbustraytypes.cpp b/src/platformsupport/dbustray/qdbustraytypes.cpp
index 0ca6669508..5100f8ee2c 100644
--- a/src/platformsupport/dbustray/qdbustraytypes.cpp
+++ b/src/platformsupport/dbustray/qdbustraytypes.cpp
@@ -32,20 +32,47 @@
**
****************************************************************************/
+#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 <qpa/qplatformmenu.h>
+#include "qdbusplatformmenu_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static const int IconSizeLimit = 32;
+static const int IconNormalSmallSize = 22;
QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
{
QXdgDBusImageVector ret;
- foreach (QSize size, icon.availableSizes()) {
+ QList<QSize> sizes = icon.availableSizes();
+
+ // Omit any size larger than 32 px, to save D-Bus bandwidth;
+ // and ensure that 22px or smaller exists, because it's a common size.
+ bool hasSmallIcon = false;
+ QList<QSize> toRemove;
+ Q_FOREACH (const QSize &size, sizes) {
+ if (size.width() <= IconNormalSmallSize)
+ hasSmallIcon = true;
+ else if (size.width() > IconSizeLimit)
+ toRemove << size;
+ }
+ Q_FOREACH (const QSize &size, toRemove)
+ sizes.removeOne(size);
+ if (!hasSmallIcon)
+ sizes.append(QSize(IconNormalSmallSize, IconNormalSmallSize));
+
+ foreach (QSize size, sizes) {
QXdgDBusImageStruct kim;
kim.width = size.width();
kim.height = size.height();
@@ -155,9 +182,5 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusToolTipSt
return argument;
}
-void registerDBusTrayTypes()
-{
- qDBusRegisterMetaType<QXdgDBusImageStruct>();
- qDBusRegisterMetaType<QXdgDBusImageVector>();
- qDBusRegisterMetaType<QXdgDBusToolTipStruct>();
-}
+QT_END_NAMESPACE
+#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/platformsupport/dbustray/qdbustraytypes_p.h b/src/platformsupport/dbustray/qdbustraytypes_p.h
index 5b275e0d33..2e1421eccd 100644
--- a/src/platformsupport/dbustray/qdbustraytypes_p.h
+++ b/src/platformsupport/dbustray/qdbustraytypes_p.h
@@ -35,6 +35,8 @@
#ifndef QDBUSTRAYTYPES_P_H
#define QDBUSTRAYTYPES_P_H
+#ifndef QT_NO_SYSTEMTRAYICON
+
#include <QObject>
#include <QString>
#include <QDBusArgument>
@@ -42,6 +44,8 @@
#include <QDBusObjectPath>
#include <QPixmap>
+QT_BEGIN_NAMESPACE
+
// Custom message type to send icons across D-Bus
struct QXdgDBusImageStruct
{
@@ -66,16 +70,17 @@ struct QXdgDBusToolTipStruct
const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusImageStruct &icon);
const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusImageStruct &icon);
-Q_DECLARE_METATYPE(QXdgDBusImageStruct)
-
const QDBusArgument &operator<<(QDBusArgument &argument, const QXdgDBusImageVector &iconVector);
const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusImageVector &iconVector);
-Q_DECLARE_METATYPE(QXdgDBusImageVector)
-
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/dbustray/qstatusnotifieritemadaptor.cpp b/src/platformsupport/dbustray/qstatusnotifieritemadaptor.cpp
new file mode 100644
index 0000000000..8afcaa70d5
--- /dev/null
+++ b/src/platformsupport/dbustray/qstatusnotifieritemadaptor.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $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().
+*/
+
+#ifndef QT_NO_SYSTEMTRAYICON
+
+#include "qstatusnotifieritemadaptor_p.h"
+#include "qdbustrayicon_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcMenu)
+
+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)
+{
+ m_trayIcon->activate(x, y);
+}
+
+void QStatusNotifierItemAdaptor::ContextMenu(int x, int y)
+{
+ m_trayIcon->contextMenu(x, y);
+}
+
+void QStatusNotifierItemAdaptor::Scroll(int, const QString &)
+{
+ // unsupported
+}
+
+void QStatusNotifierItemAdaptor::SecondaryActivate(int, int)
+{
+ // unsupported
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h b/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h
new file mode 100644
index 0000000000..fe5da100b2
--- /dev/null
+++ b/src/platformsupport/dbustray/qstatusnotifieritemadaptor_p.h
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $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
+
+#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=\"(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=\"(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=\"(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=\"(s(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