summaryrefslogtreecommitdiffstats
path: root/src/widgets/util
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2013-06-28 11:51:29 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-07-30 15:08:31 +0200
commitd8090022f66cc6cff6af5ed2ae702212fd172ff7 (patch)
tree9942fb8e23293c49c62590fe714b8b8d6f961304 /src/widgets/util
parent983e921c541f6eaacb9abcddb8ec079ec5129cf1 (diff)
Move the X11 system tray code from widgets into XCB-plugin.
- Add system tray tracker class to XCB plugin and provide functionality via invokable slots of the native interface. - Remove XLib-dependency of widgets/utils. - Reintroduce tracking of tray window destruction and recreation, which was removed in the XLib-code when porting it from Qt 4 to Qt 5. This paves the way for implementing the tray icon completely in terms of QPlatformSystemTrayIcon at some point later. Change-Id: Ia04268b0e2919c05874a3e9548930535332897c7 Reviewed-by: Alberto Mardegan <mardy@users.sourceforge.net> Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Diffstat (limited to 'src/widgets/util')
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp150
-rw-r--r--src/widgets/util/util.pri1
2 files changed, 54 insertions, 97 deletions
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index 5204b85a9a..347e5701c0 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -57,84 +57,19 @@
#include <qpa/qplatformnativeinterface.h>
#include <qdebug.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xos.h>
-#include <X11/Xatom.h>
-
#ifndef QT_NO_SYSTEMTRAYICON
QT_BEGIN_NAMESPACE
-enum {
- SYSTEM_TRAY_REQUEST_DOCK = 0,
- SYSTEM_TRAY_BEGIN_MESSAGE = 1,
- SYSTEM_TRAY_CANCEL_MESSAGE =2
-};
-
-// ### fixme (15.3.2012): The following issues need to be resolved:
-// - Tracking of the actual tray window for DestroyNotify and re-creation
-// of the icons on the new window should it change (see Qt 4.X).
-
-// Global context for the X11 system tray containing a display for the primary
-// screen and a selection atom from which the tray window can be determined.
-class QX11SystemTrayContext
-{
-public:
- QX11SystemTrayContext();
- ~QX11SystemTrayContext();
-
- bool isValid() const { return m_systemTraySelection != 0; }
-
- inline Display *display() const { return m_display; }
- inline int screenNumber() const { return m_screenNumber; }
- Window locateSystemTray() const;
-
-private:
- Display *m_display;
- int m_screenNumber;
- Atom m_systemTraySelection;
-};
-
-QX11SystemTrayContext::QX11SystemTrayContext() : m_display(0), m_screenNumber(0), m_systemTraySelection(0)
-{
- QScreen *screen = QGuiApplication::primaryScreen();
- if (!screen) {
- qWarning("%s: No screen.", Q_FUNC_INFO);
- return;
- }
- void *displayV = QGuiApplication::platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("display"), screen);
- if (!displayV) {
- qWarning("%s: Unable to obtain X11 display of primary screen.", Q_FUNC_INFO);
- return;
- }
-
- m_display = static_cast<Display *>(displayV);
-
- const QByteArray netSysTray = "_NET_SYSTEM_TRAY_S" + QByteArray::number(m_screenNumber);
- m_systemTraySelection = XInternAtom(m_display, netSysTray.constData(), False);
- if (!m_systemTraySelection) {
- qWarning("%s: Unable to retrieve atom '%s'.", Q_FUNC_INFO, netSysTray.constData());
- return;
- }
-}
-
-Window QX11SystemTrayContext::locateSystemTray() const
+static inline unsigned long locateSystemTray()
{
- if (isValid())
- return XGetSelectionOwner(m_display, m_systemTraySelection);
- return 0;
+ return (unsigned long)QGuiApplication::platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("traywindow"), QGuiApplication::primaryScreen());
}
-QX11SystemTrayContext::~QX11SystemTrayContext()
-{
-}
-
-Q_GLOBAL_STATIC(QX11SystemTrayContext, qX11SystemTrayContext)
-
// System tray widget. Could be replaced by a QWindow with
// a backing store if it did not need tooltip handling.
class QSystemTrayIconSys : public QWidget
{
+ Q_OBJECT
public:
explicit QSystemTrayIconSys(QSystemTrayIcon *q);
@@ -149,7 +84,12 @@ protected:
virtual bool event(QEvent *);
virtual void paintEvent(QPaintEvent *);
+private slots:
+ void systemTrayWindowChanged(QScreen *screen);
+
private:
+ bool addToTray();
+
QSystemTrayIcon *q;
};
@@ -159,47 +99,59 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
{
setObjectName(QStringLiteral("QSystemTrayIconSys"));
setToolTip(q->toolTip());
- QX11SystemTrayContext *context = qX11SystemTrayContext();
- Q_ASSERT(context->isValid());
setAttribute(Qt::WA_AlwaysShowToolTips, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_QuitOnClose, false);
const QSize size(22, 22); // Gnome, standard size
setGeometry(QRect(QPoint(0, 0), size));
setMinimumSize(size);
+ addToTray();
+}
+
+bool QSystemTrayIconSys::addToTray()
+{
+ if (!locateSystemTray())
+ return false;
+
createWinId();
setMouseTracking(true);
- Display *display = context->display();
-
- // Request to be a tray window according to GNOME, NET WM Specification
- static Atom netwm_tray_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False);
- long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, static_cast<long>(winId()), 0, 0 };
- XEvent ev;
- memset(&ev, 0, sizeof(ev));
- ev.xclient.type = ClientMessage;
- ev.xclient.window = context->locateSystemTray();
- ev.xclient.message_type = netwm_tray_atom;
- ev.xclient.format = 32;
- memcpy((char *)&ev.xclient.data, (const char *) l, sizeof(l));
- XSendEvent(display, ev.xclient.window, False, 0, &ev);
+ bool requestResult = false;
+ if (!QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(),
+ "requestSystemTrayWindowDock", Qt::DirectConnection,
+ Q_RETURN_ARG(bool, requestResult),
+ Q_ARG(const QWindow *, windowHandle()))
+ || !requestResult) {
+ qWarning("requestSystemTrayWindowDock failed.");
+ return false;
+ }
show();
+ return true;
}
-QRect QSystemTrayIconSys::globalGeometry() const
+void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
{
- QX11SystemTrayContext *context = qX11SystemTrayContext();
- ::Window dummy;
- int x, y, rootX, rootY;
- unsigned int width, height, border, depth;
- // Use X11 API since we are parented on the tray, about which the QWindow does not know.
- XGetGeometry(context->display(), winId(), &dummy, &x, &y, &width, &height, &border, &depth);
- XTranslateCoordinates(context->display(), winId(),
- XRootWindow(context->display(), context->screenNumber()),
- x, y, &rootX, &rootY, &dummy);
- return QRect(QPoint(rootX, rootY), QSize(width, height));
+ if (locateSystemTray()) {
+ addToTray();
+ } else {
+ QBalloonTip::hideBalloon();
+ hide(); // still no luck
+ destroy();
+ }
}
+QRect QSystemTrayIconSys::globalGeometry() const
+{
+ QRect result;
+ if (!QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(),
+ "systemTrayWindowGlobalGeometry", Qt::DirectConnection,
+ Q_RETURN_ARG(QRect, result),
+ Q_ARG(const QWindow *, windowHandle()))
+ || !result.isValid()) {
+ qWarning("systemTrayWindowGlobalGeometry failed.");
+ }
+ return result;
+}
void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)
{
@@ -268,8 +220,11 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
Q_Q(QSystemTrayIcon);
- if (!sys && qX11SystemTrayContext()->isValid())
+ if (!sys && locateSystemTray()) {
sys = new QSystemTrayIconSys(q);
+ QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
+ sys, SLOT(systemTrayWindowChanged(QScreen*)));
+ }
}
QRect QSystemTrayIconPrivate::geometry_sys() const
@@ -313,7 +268,7 @@ bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
{
const QString platform = QGuiApplication::platformName();
if (platform.compare(QStringLiteral("xcb"), Qt::CaseInsensitive) == 0)
- return qX11SystemTrayContext()->locateSystemTray() != None;
+ return locateSystemTray();
return false;
}
@@ -334,4 +289,7 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QStri
}
QT_END_NAMESPACE
+
+#include "qsystemtrayicon_x11.moc"
+
#endif //QT_NO_SYSTEMTRAYICON
diff --git a/src/widgets/util/util.pri b/src/widgets/util/util.pri
index 598a3082c0..072c736f71 100644
--- a/src/widgets/util/util.pri
+++ b/src/widgets/util/util.pri
@@ -31,7 +31,6 @@ win32:!wince* {
SOURCES += util/qsystemtrayicon_win.cpp
} else:contains(QT_CONFIG, xcb) {
SOURCES += util/qsystemtrayicon_x11.cpp
- CONFIG += x11
} else {
SOURCES += util/qsystemtrayicon_qpa.cpp
}