updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / qt-systemtrayicon / kubuntu_14_systemtrayicon.diff
blob56510578a39fa4e9b8f2f92998b7f434d444e583
1 System tray icon plugin system for SNI
2 diff --git a/examples/desktop/systray/window.cpp b/examples/desktop/systray/window.cpp
3 index 4091358..50c4ca6 100644
4 --- a/examples/desktop/systray/window.cpp
5 +++ b/examples/desktop/systray/window.cpp
6 @@ -158,15 +158,23 @@ void Window::createIconGroupBox()
7 iconComboBox->addItem(QIcon(":/images/bad.svg"), tr("Bad"));
8 iconComboBox->addItem(QIcon(":/images/heart.svg"), tr("Heart"));
9 iconComboBox->addItem(QIcon(":/images/trash.svg"), tr("Trash"));
10 + iconComboBox->addItem(QIcon::fromTheme("system-file-manager"), tr("File Manager"));
12 showIconCheckBox = new QCheckBox(tr("Show icon"));
13 showIconCheckBox->setChecked(true);
15 +#if defined(Q_WS_X11)
16 + jitToolTipCheckBox = new QCheckBox(tr("Just In Time Tooltip"));
17 +#endif
19 QHBoxLayout *iconLayout = new QHBoxLayout;
20 iconLayout->addWidget(iconLabel);
21 iconLayout->addWidget(iconComboBox);
22 iconLayout->addStretch();
23 iconLayout->addWidget(showIconCheckBox);
24 +#if defined(Q_WS_X11)
25 + iconLayout->addWidget(jitToolTipCheckBox);
26 +#endif
27 iconGroupBox->setLayout(iconLayout);
30 @@ -254,5 +262,37 @@ void Window::createTrayIcon()
31 trayIconMenu->addAction(quitAction);
33 trayIcon = new QSystemTrayIcon(this);
34 + QByteArray category = qgetenv("SNI_CATEGORY");
35 + if (!category.isEmpty()) {
36 + trayIcon->setProperty("_qt_sni_category", QString::fromLocal8Bit(category));
37 + }
38 trayIcon->setContextMenu(trayIconMenu);
40 +#if defined(Q_WS_X11)
41 + trayIcon->installEventFilter(this);
42 +#endif
45 +#if defined(Q_WS_X11)
46 +bool Window::eventFilter(QObject *, QEvent *event)
48 + switch(event->type()) {
49 + case QEvent::ToolTip:
50 + if (jitToolTipCheckBox->isChecked()) {
51 + QString timeString = QTime::currentTime().toString();
52 + trayIcon->setToolTip(tr("Current Time: %1").arg(timeString));
53 + }
54 + break;
55 + case QEvent::Wheel: {
56 + QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
57 + int delta = wheelEvent->delta() > 0 ? 1 : -1;
58 + int index = (iconComboBox->currentIndex() + delta) % iconComboBox->count();
59 + iconComboBox->setCurrentIndex(index);
60 + break;
61 + }
62 + default:
63 + break;
64 + }
65 + return false;
67 +#endif
68 diff --git a/examples/desktop/systray/window.h b/examples/desktop/systray/window.h
69 index 537a8a2..374a623 100644
70 --- a/examples/desktop/systray/window.h
71 +++ b/examples/desktop/systray/window.h
72 @@ -69,6 +69,9 @@ public:
74 protected:
75 void closeEvent(QCloseEvent *event);
76 +#if defined(Q_WS_X11)
77 + bool eventFilter(QObject *object, QEvent *event);
78 +#endif
80 private slots:
81 void setIcon(int index);
82 @@ -86,6 +89,9 @@ private:
83 QLabel *iconLabel;
84 QComboBox *iconComboBox;
85 QCheckBox *showIconCheckBox;
86 +#if defined(Q_WS_X11)
87 + QCheckBox *jitToolTipCheckBox;
88 +#endif
90 QGroupBox *messageGroupBox;
91 QLabel *typeLabel;
92 diff --git a/src/gui/util/qabstractsystemtrayiconsys.cpp b/src/gui/util/qabstractsystemtrayiconsys.cpp
93 new file mode 100644
94 index 0000000..0c4f7ae
95 --- /dev/null
96 +++ b/src/gui/util/qabstractsystemtrayiconsys.cpp
97 @@ -0,0 +1,65 @@
98 +/****************************************************************************
99 +**
100 +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
101 +** All rights reserved.
102 +** Contact: Nokia Corporation (qt-info@nokia.com)
104 +** This file is part of the QtGui module of the Qt Toolkit.
106 +** $QT_BEGIN_LICENSE:LGPL$
107 +** GNU Lesser General Public License Usage
108 +** This file may be used under the terms of the GNU Lesser General Public
109 +** License version 2.1 as published by the Free Software Foundation and
110 +** appearing in the file LICENSE.LGPL included in the packaging of this
111 +** file. Please review the following information to ensure the GNU Lesser
112 +** General Public License version 2.1 requirements will be met:
113 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
115 +** In addition, as a special exception, Nokia gives you certain additional
116 +** rights. These rights are described in the Nokia Qt LGPL Exception
117 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
119 +** GNU General Public License Usage
120 +** Alternatively, this file may be used under the terms of the GNU General
121 +** Public License version 3.0 as published by the Free Software Foundation
122 +** and appearing in the file LICENSE.GPL included in the packaging of this
123 +** file. Please review the following information to ensure the GNU General
124 +** Public License version 3.0 requirements will be met:
125 +** http://www.gnu.org/copyleft/gpl.html.
127 +** Other Usage
128 +** Alternatively, this file may be used in accordance with the terms and
129 +** conditions contained in a signed written agreement between you and Nokia.
135 +** $QT_END_LICENSE$
137 +****************************************************************************/
138 +#ifndef QT_NO_SYSTEMTRAYICON
140 +#include "qabstractsystemtrayiconsys_p.h"
143 +QSystemTrayIconSysFactoryInterface::QSystemTrayIconSysFactoryInterface()
147 +/////////////////////////////////////////////////
148 +QAbstractSystemTrayIconSys::QAbstractSystemTrayIconSys(QSystemTrayIcon *icon)
149 +: trayIcon(icon)
153 +QAbstractSystemTrayIconSys::~QAbstractSystemTrayIconSys()
157 +void QAbstractSystemTrayIconSys::sendActivated(QSystemTrayIcon::ActivationReason reason)
159 + qtsystray_sendActivated(trayIcon, reason);
162 +#endif
163 diff --git a/src/gui/util/qabstractsystemtrayiconsys_p.h b/src/gui/util/qabstractsystemtrayiconsys_p.h
164 new file mode 100644
165 index 0000000..65ca2f6
166 --- /dev/null
167 +++ b/src/gui/util/qabstractsystemtrayiconsys_p.h
168 @@ -0,0 +1,106 @@
169 +/****************************************************************************
171 +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
172 +** All rights reserved.
173 +** Contact: Nokia Corporation (qt-info@nokia.com)
175 +** This file is part of the QtGui module of the Qt Toolkit.
177 +** $QT_BEGIN_LICENSE:LGPL$
178 +** GNU Lesser General Public License Usage
179 +** This file may be used under the terms of the GNU Lesser General Public
180 +** License version 2.1 as published by the Free Software Foundation and
181 +** appearing in the file LICENSE.LGPL included in the packaging of this
182 +** file. Please review the following information to ensure the GNU Lesser
183 +** General Public License version 2.1 requirements will be met:
184 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
186 +** In addition, as a special exception, Nokia gives you certain additional
187 +** rights. These rights are described in the Nokia Qt LGPL Exception
188 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
190 +** GNU General Public License Usage
191 +** Alternatively, this file may be used under the terms of the GNU General
192 +** Public License version 3.0 as published by the Free Software Foundation
193 +** and appearing in the file LICENSE.GPL included in the packaging of this
194 +** file. Please review the following information to ensure the GNU General
195 +** Public License version 3.0 requirements will be met:
196 +** http://www.gnu.org/copyleft/gpl.html.
198 +** Other Usage
199 +** Alternatively, this file may be used in accordance with the terms and
200 +** conditions contained in a signed written agreement between you and Nokia.
206 +** $QT_END_LICENSE$
208 +****************************************************************************/
210 +#ifndef QABSTRACTSYSTEMTRAYICONSYS_P_H
211 +#define QABSTRACTSYSTEMTRAYICONSYS_P_H
214 +// W A R N I N G
215 +// -------------
217 +// This file is not part of the Qt API. It exists for the convenience
218 +// of a number of Qt sources files. This header file may change from
219 +// version to version without notice, or even be removed.
221 +// We mean it.
224 +#ifndef QT_NO_SYSTEMTRAYICON
226 +#include <qfactoryinterface.h>
227 +#include <qsystemtrayicon.h>
229 +class QAbstractSystemTrayIconSys;
231 +class Q_GUI_EXPORT QSystemTrayIconSysFactoryInterface : public QObject, public QFactoryInterface
233 + Q_OBJECT
234 +public:
235 + QSystemTrayIconSysFactoryInterface();
236 + virtual QAbstractSystemTrayIconSys * create(QSystemTrayIcon *) = 0;
237 + virtual bool isAvailable() const = 0;
239 + // \reimp
240 + virtual QStringList keys() const { return QStringList() << QLatin1String("default"); }
242 +Q_SIGNALS:
243 + void availableChanged(bool);
246 +#define QSystemTrayIconSysFactoryInterface_iid "com.nokia.qt.QSystemTrayIconSysFactoryInterface"
247 +Q_DECLARE_INTERFACE(QSystemTrayIconSysFactoryInterface, QSystemTrayIconSysFactoryInterface_iid)
249 +class QRect;
251 +class Q_GUI_EXPORT QAbstractSystemTrayIconSys
253 +public:
254 + QAbstractSystemTrayIconSys(QSystemTrayIcon *icon);
255 + virtual ~QAbstractSystemTrayIconSys();
257 + virtual QRect geometry() const = 0;
258 + virtual void updateVisibility() = 0;
259 + virtual void updateIcon() = 0;
260 + virtual void updateToolTip() = 0;
261 + virtual void updateMenu() = 0;
262 + virtual void showMessage(const QString &message, const QString &title,
263 + QSystemTrayIcon::MessageIcon icon, int msecs) = 0;
265 + void sendActivated(QSystemTrayIcon::ActivationReason);
267 +protected:
268 + QSystemTrayIcon *trayIcon;
271 +#endif // QT_NO_SYSTEMTRAYICON
273 +#endif // QABSTRACTSYSTEMTRAYICONSYS_P_H
275 diff --git a/src/gui/util/qsystemtrayicon.cpp b/src/gui/util/qsystemtrayicon.cpp
276 index 28d4932..96d68fc 100644
277 --- a/src/gui/util/qsystemtrayicon.cpp
278 +++ b/src/gui/util/qsystemtrayicon.cpp
279 @@ -287,12 +287,6 @@ bool QSystemTrayIcon::isVisible() const
281 bool QSystemTrayIcon::event(QEvent *e)
283 -#if defined(Q_WS_X11)
284 - if (e->type() == QEvent::ToolTip) {
285 - Q_D(QSystemTrayIcon);
286 - return d->sys->deliverToolTipEvent(e);
288 -#endif
289 return QObject::event(e);
292 diff --git a/src/gui/util/qsystemtrayicon_p.h b/src/gui/util/qsystemtrayicon_p.h
293 index 14495ee..2596658 100644
294 --- a/src/gui/util/qsystemtrayicon_p.h
295 +++ b/src/gui/util/qsystemtrayicon_p.h
296 @@ -62,10 +62,17 @@
297 #include "QtGui/qpixmap.h"
298 #include "QtCore/qstring.h"
299 #include "QtCore/qpointer.h"
300 +#if defined(Q_WS_X11)
301 +#include "QtCore/qset.h"
302 +#endif
304 QT_BEGIN_NAMESPACE
306 +#if defined(Q_WS_X11)
307 +class QAbstractSystemTrayIconSys;
308 +#else
309 class QSystemTrayIconSys;
310 +#endif
311 class QToolButton;
312 class QLabel;
314 @@ -75,6 +82,9 @@ class QSystemTrayIconPrivate : public QObjectPrivate
316 public:
317 QSystemTrayIconPrivate() : sys(0), visible(false) { }
318 + #if defined(Q_WS_X11)
319 + ~QSystemTrayIconPrivate();
320 + #endif
322 void install_sys();
323 void remove_sys();
324 @@ -90,7 +100,11 @@ public:
325 QPointer<QMenu> menu;
326 QIcon icon;
327 QString toolTip;
328 + #if defined(Q_WS_X11)
329 + QAbstractSystemTrayIconSys *sys;
330 + #else
331 QSystemTrayIconSys *sys;
332 + #endif
333 bool visible;
336 @@ -123,60 +137,37 @@ private:
339 #if defined(Q_WS_X11)
340 -QT_BEGIN_INCLUDE_NAMESPACE
341 -#include <QtCore/qcoreapplication.h>
342 -#include <X11/Xlib.h>
343 -#include <X11/Xatom.h>
344 -#include <X11/Xutil.h>
345 -QT_END_INCLUDE_NAMESPACE
347 -class QSystemTrayIconSys : public QWidget
348 +class QSystemTrayIconSysFactoryInterface;
350 +/**
351 + * This class acts as a composite QSystemTrayIconSysFactory: It can create
352 + * instances of QAbstractSystemTrayIconSys* using either a plugin or the
353 + * builtin factory and will cause QSystemTrayIconPrivate to recreate their
354 + * 'sys' instances if the plugin availability changes.
355 + */
356 +class QSystemTrayIconSysFactory : public QObject
358 - friend class QSystemTrayIconPrivate;
360 + Q_OBJECT
361 public:
362 - QSystemTrayIconSys(QSystemTrayIcon *q);
363 - ~QSystemTrayIconSys();
364 - enum {
365 - SYSTEM_TRAY_REQUEST_DOCK = 0,
366 - SYSTEM_TRAY_BEGIN_MESSAGE = 1,
367 - SYSTEM_TRAY_CANCEL_MESSAGE =2
368 - };
370 - void addToTray();
371 - void updateIcon();
372 - XVisualInfo* getSysTrayVisualInfo();
374 - // QObject::event is public but QWidget's ::event() re-implementation
375 - // is protected ;(
376 - inline bool deliverToolTipEvent(QEvent *e)
377 - { return QWidget::event(e); }
379 - static Window sysTrayWindow;
380 - static QList<QSystemTrayIconSys *> trayIcons;
381 - static QCoreApplication::EventFilter oldEventFilter;
382 - static bool sysTrayTracker(void *message, long *result);
383 - static Window locateSystemTray();
384 - static Atom sysTraySelection;
385 - static XVisualInfo sysTrayVisual;
386 + QSystemTrayIconSysFactory();
387 + void registerSystemTrayIconPrivate(QSystemTrayIconPrivate *iconPrivate);
388 + void unregisterSystemTrayIconPrivate(QSystemTrayIconPrivate *iconPrivate);
390 -protected:
391 - void paintEvent(QPaintEvent *pe);
392 - void resizeEvent(QResizeEvent *re);
393 - bool x11Event(XEvent *event);
394 - void mousePressEvent(QMouseEvent *event);
395 - void mouseDoubleClickEvent(QMouseEvent *event);
396 -#ifndef QT_NO_WHEELEVENT
397 - void wheelEvent(QWheelEvent *event);
398 -#endif
399 - bool event(QEvent *e);
400 + QAbstractSystemTrayIconSys *create(QSystemTrayIcon *) const;
402 + bool isAvailable() const;
404 +private Q_SLOTS:
405 + void refreshTrayIconPrivates();
407 private:
408 - QPixmap background;
409 - QSystemTrayIcon *q;
410 - Colormap colormap;
411 + QSystemTrayIconSysFactoryInterface *factory() const;
412 + void loadPluginFactory();
414 + QSystemTrayIconSysFactoryInterface *pluginFactory;
415 + QSet<QSystemTrayIconPrivate *> trayIconPrivates;
417 -#endif // Q_WS_X11
418 +#endif
420 QT_END_NAMESPACE
422 diff --git a/src/gui/util/qsystemtrayicon_x11.cpp b/src/gui/util/qsystemtrayicon_x11.cpp
423 index 86c2749..33f672b 100644
424 --- a/src/gui/util/qsystemtrayicon_x11.cpp
425 +++ b/src/gui/util/qsystemtrayicon_x11.cpp
426 @@ -38,311 +38,114 @@
427 ** $QT_END_LICENSE$
429 ****************************************************************************/
430 +#ifndef QT_NO_SYSTEMTRAYICON
432 +#include <private/qfactoryloader_p.h>
434 -#include "private/qt_x11_p.h"
435 -#include "qlabel.h"
436 -#include "qx11info_x11.h"
437 -#include "qpainter.h"
438 -#include "qpixmap.h"
439 -#include "qbitmap.h"
440 -#include "qevent.h"
441 -#include "qapplication.h"
442 -#include "qlist.h"
443 -#include "qmenu.h"
444 -#include "qtimer.h"
445 #include "qsystemtrayicon_p.h"
446 -#include "qpaintengine.h"
447 +#include "qabstractsystemtrayiconsys_p.h"
448 +#include "qcoreapplication.h"
449 +#include "qxembedsystemtrayicon_x11_p.h"
451 -#ifndef QT_NO_SYSTEMTRAYICON
452 QT_BEGIN_NAMESPACE
454 -Window QSystemTrayIconSys::sysTrayWindow = XNone;
455 -QList<QSystemTrayIconSys *> QSystemTrayIconSys::trayIcons;
456 -QCoreApplication::EventFilter QSystemTrayIconSys::oldEventFilter = 0;
457 -Atom QSystemTrayIconSys::sysTraySelection = XNone;
458 -XVisualInfo QSystemTrayIconSys::sysTrayVisual = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
459 +Q_GLOBAL_STATIC(QSystemTrayIconSysFactory, qt_guiSystemTrayIconSysFactory)
461 -// Locate the system tray
462 -Window QSystemTrayIconSys::locateSystemTray()
463 +QSystemTrayIconSysFactory::QSystemTrayIconSysFactory()
464 +: pluginFactory(0)
466 - Display *display = QX11Info::display();
467 - if (sysTraySelection == XNone) {
468 - int screen = QX11Info::appScreen();
469 - QString net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen);
470 - sysTraySelection = XInternAtom(display, net_sys_tray.toLatin1(), False);
473 - return XGetSelectionOwner(QX11Info::display(), sysTraySelection);
476 -XVisualInfo* QSystemTrayIconSys::getSysTrayVisualInfo()
477 +void QSystemTrayIconSysFactory::loadPluginFactory()
479 - Display *display = QX11Info::display();
481 - if (!sysTrayVisual.visual) {
482 - Window win = locateSystemTray();
483 - if (win != XNone) {
484 - Atom actual_type;
485 - int actual_format;
486 - ulong nitems, bytes_remaining;
487 - uchar *data = 0;
488 - int result = XGetWindowProperty(display, win, ATOM(_NET_SYSTEM_TRAY_VISUAL), 0, 1,
489 - False, XA_VISUALID, &actual_type,
490 - &actual_format, &nitems, &bytes_remaining, &data);
491 - VisualID vid = 0;
492 - if (result == Success && data && actual_type == XA_VISUALID && actual_format == 32 &&
493 - nitems == 1 && bytes_remaining == 0)
494 - vid = *(VisualID*)data;
495 - if (data)
496 - XFree(data);
497 - if (vid == 0)
498 - return 0;
500 - uint mask = VisualIDMask;
501 - XVisualInfo *vi, rvi;
502 - int count;
503 - rvi.visualid = vid;
504 - vi = XGetVisualInfo(display, mask, &rvi, &count);
505 - if (vi) {
506 - sysTrayVisual = vi[0];
507 - XFree((char*)vi);
509 - if (sysTrayVisual.depth != 32)
510 - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
512 + if (pluginFactory) {
513 + return;
516 - return sysTrayVisual.visual ? &sysTrayVisual : 0;
519 -bool QSystemTrayIconSys::sysTrayTracker(void *message, long *result)
521 - bool retval = false;
522 - if (QSystemTrayIconSys::oldEventFilter)
523 - retval = QSystemTrayIconSys::oldEventFilter(message, result);
525 - if (trayIcons.isEmpty())
526 - return retval;
528 - Display *display = QX11Info::display();
529 - XEvent *ev = (XEvent *)message;
530 - if (ev->type == DestroyNotify && ev->xany.window == sysTrayWindow) {
531 - sysTrayWindow = locateSystemTray();
532 - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
533 - for (int i = 0; i < trayIcons.count(); i++) {
534 - if (sysTrayWindow == XNone) {
535 - QBalloonTip::hideBalloon();
536 - trayIcons[i]->hide(); // still no luck
537 - trayIcons[i]->destroy();
538 - trayIcons[i]->create();
539 - } else
540 - trayIcons[i]->addToTray(); // add it to the new tray
542 - retval = true;
543 - } else if (ev->type == ClientMessage && sysTrayWindow == XNone) {
544 - static Atom manager_atom = XInternAtom(display, "MANAGER", False);
545 - XClientMessageEvent *cm = (XClientMessageEvent *)message;
546 - if ((cm->message_type == manager_atom) && ((Atom)cm->data.l[1] == sysTraySelection)) {
547 - sysTrayWindow = cm->data.l[2];
548 - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
549 - XSelectInput(display, sysTrayWindow, StructureNotifyMask);
550 - for (int i = 0; i < trayIcons.count(); i++) {
551 - trayIcons[i]->addToTray();
553 - retval = true;
555 - } else if (ev->type == PropertyNotify && ev->xproperty.atom == ATOM(_NET_SYSTEM_TRAY_VISUAL) &&
556 - ev->xproperty.window == sysTrayWindow) {
557 - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
558 - for (int i = 0; i < trayIcons.count(); i++) {
559 - trayIcons[i]->addToTray();
561 +#ifndef QT_NO_LIBRARY
562 + QFactoryLoader loader(QSystemTrayIconSysFactoryInterface_iid, QLatin1String("/systemtrayicon"));
563 + pluginFactory = qobject_cast<QSystemTrayIconSysFactoryInterface *>(loader.instance(QLatin1String("default")));
564 + if (pluginFactory) {
565 + // Set parent to ensure factory destructor is called when application
566 + // is closed
567 + pluginFactory->setParent(QCoreApplication::instance());
568 + connect(pluginFactory, SIGNAL(availableChanged(bool)), SLOT(refreshTrayIconPrivates()));
571 - return retval;
572 +#endif // QT_NO_LIBRARY
575 -QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *q)
576 - : QWidget(0, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint),
577 - q(q), colormap(0)
578 +QSystemTrayIconSysFactoryInterface *QSystemTrayIconSysFactory::factory() const
580 - setAttribute(Qt::WA_AlwaysShowToolTips);
581 - setAttribute(Qt::WA_QuitOnClose, false);
582 - setAttribute(Qt::WA_NoSystemBackground, true);
583 - setAttribute(Qt::WA_PaintOnScreen);
585 - static bool eventFilterAdded = false;
586 - Display *display = QX11Info::display();
587 - if (!eventFilterAdded) {
588 - oldEventFilter = qApp->setEventFilter(sysTrayTracker);
589 - eventFilterAdded = true;
590 - Window root = QX11Info::appRootWindow();
591 - XWindowAttributes attr;
592 - XGetWindowAttributes(display, root, &attr);
593 - if ((attr.your_event_mask & StructureNotifyMask) != StructureNotifyMask) {
594 - (void) QApplication::desktop(); // lame trick to ensure our event mask is not overridden
595 - XSelectInput(display, root, attr.your_event_mask | StructureNotifyMask); // for MANAGER selection
597 + if (!pluginFactory) {
598 + const_cast<QSystemTrayIconSysFactory*>(this)->loadPluginFactory();
600 - if (trayIcons.isEmpty()) {
601 - sysTrayWindow = locateSystemTray();
602 - if (sysTrayWindow != XNone)
603 - XSelectInput(display, sysTrayWindow, StructureNotifyMask); // track tray events
605 - trayIcons.append(this);
606 - setMouseTracking(true);
607 -#ifndef QT_NO_TOOLTIP
608 - setToolTip(q->toolTip());
609 -#endif
610 - if (sysTrayWindow != XNone)
611 - addToTray();
614 -QSystemTrayIconSys::~QSystemTrayIconSys()
616 - trayIcons.removeAt(trayIcons.indexOf(this));
617 - Display *display = QX11Info::display();
618 - if (trayIcons.isEmpty()) {
619 - if (sysTrayWindow == XNone)
620 - return;
621 - if (display)
622 - XSelectInput(display, sysTrayWindow, 0); // stop tracking the tray
623 - sysTrayWindow = XNone;
624 + if (pluginFactory && pluginFactory->isAvailable()) {
625 + return pluginFactory;
627 - if (colormap)
628 - XFreeColormap(display, colormap);
629 + static QXEmbedSystemTrayIconSysFactory def;
630 + return def.isAvailable() ? &def : 0;
633 -void QSystemTrayIconSys::addToTray()
634 +void QSystemTrayIconSysFactory::refreshTrayIconPrivates()
636 - Q_ASSERT(sysTrayWindow != XNone);
637 - Display *display = QX11Info::display();
639 - XVisualInfo *vi = getSysTrayVisualInfo();
640 - if (vi && vi->visual) {
641 - Window root = RootWindow(display, vi->screen);
642 - Window p = root;
643 - if (QWidget *pw = parentWidget())
644 - p = pw->effectiveWinId();
645 - colormap = XCreateColormap(display, root, vi->visual, AllocNone);
646 - XSetWindowAttributes wsa;
647 - wsa.background_pixmap = 0;
648 - wsa.colormap = colormap;
649 - wsa.background_pixel = 0;
650 - wsa.border_pixel = 0;
651 - Window wid = XCreateWindow(display, p, -1, -1, 1, 1,
652 - 0, vi->depth, InputOutput, vi->visual,
653 - CWBackPixmap|CWBackPixel|CWBorderPixel|CWColormap, &wsa);
654 - create(wid);
655 - } else {
656 - XSetWindowBackgroundPixmap(display, winId(), ParentRelative);
657 + Q_FOREACH(QSystemTrayIconPrivate *trayIconPrivate, trayIconPrivates) {
658 + if (trayIconPrivate->sys) {
659 + delete trayIconPrivate->sys;
660 + trayIconPrivate->sys = 0;
661 + trayIconPrivate->install_sys();
665 - // GNOME, NET WM Specification
666 - static Atom netwm_tray_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False);
667 - long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, winId(), 0, 0 };
668 - XEvent ev;
669 - memset(&ev, 0, sizeof(ev));
670 - ev.xclient.type = ClientMessage;
671 - ev.xclient.window = sysTrayWindow;
672 - ev.xclient.message_type = netwm_tray_atom;
673 - ev.xclient.format = 32;
674 - memcpy((char *)&ev.xclient.data, (const char *) l, sizeof(l));
675 - XSendEvent(display, sysTrayWindow, False, 0, &ev);
676 - setMinimumSize(22, 22); // required at least on GNOME
679 -void QSystemTrayIconSys::updateIcon()
680 +void QSystemTrayIconSysFactory::registerSystemTrayIconPrivate(QSystemTrayIconPrivate* trayIconPrivate)
682 - update();
683 + trayIconPrivates.insert(trayIconPrivate);
686 -void QSystemTrayIconSys::resizeEvent(QResizeEvent *re)
687 +void QSystemTrayIconSysFactory::unregisterSystemTrayIconPrivate(QSystemTrayIconPrivate* trayIconPrivate)
689 - QWidget::resizeEvent(re);
690 - updateIcon();
693 -void QSystemTrayIconSys::paintEvent(QPaintEvent*)
695 - QPainter p(this);
696 - if (!getSysTrayVisualInfo()) {
697 - const QRegion oldSystemClip = p.paintEngine()->systemClip();
698 - const QRect clearedRect = oldSystemClip.boundingRect();
699 - XClearArea(QX11Info::display(), winId(), clearedRect.x(), clearedRect.y(),
700 - clearedRect.width(), clearedRect.height(), False);
701 - QPaintEngine *pe = p.paintEngine();
702 - pe->setSystemClip(clearedRect);
703 - q->icon().paint(&p, rect());
704 - pe->setSystemClip(oldSystemClip);
705 - } else {
706 - p.setCompositionMode(QPainter::CompositionMode_Source);
707 - p.fillRect(rect(), Qt::transparent);
708 - p.setCompositionMode(QPainter::CompositionMode_SourceOver);
709 - q->icon().paint(&p, rect());
711 + trayIconPrivates.remove(trayIconPrivate);
714 -void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)
715 +QAbstractSystemTrayIconSys *QSystemTrayIconSysFactory::create(QSystemTrayIcon *trayIcon) const
717 - QPoint globalPos = ev->globalPos();
718 - if (ev->button() == Qt::RightButton && q->contextMenu())
719 - q->contextMenu()->popup(globalPos);
721 - if (QBalloonTip::isBalloonVisible()) {
722 - emit q->messageClicked();
723 - QBalloonTip::hideBalloon();
724 + QSystemTrayIconSysFactoryInterface *f = factory();
725 + if (!f) {
726 + qWarning("No systemtrayicon available");
727 + return 0;
730 - if (ev->button() == Qt::LeftButton)
731 - emit q->activated(QSystemTrayIcon::Trigger);
732 - else if (ev->button() == Qt::RightButton)
733 - emit q->activated(QSystemTrayIcon::Context);
734 - else if (ev->button() == Qt::MidButton)
735 - emit q->activated(QSystemTrayIcon::MiddleClick);
736 + return f->create(trayIcon);
739 -void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev)
740 +bool QSystemTrayIconSysFactory::isAvailable() const
742 - if (ev->button() == Qt::LeftButton)
743 - emit q->activated(QSystemTrayIcon::DoubleClick);
744 + return factory();
747 -#ifndef QT_NO_WHEELEVENT
748 -void QSystemTrayIconSys::wheelEvent(QWheelEvent *e)
749 +////////////////////////////////////////////////
750 +QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
752 - QApplication::sendEvent(q, e);
754 -#endif
756 -bool QSystemTrayIconSys::event(QEvent *e)
758 - if (e->type() == QEvent::ToolTip) {
759 - return QApplication::sendEvent(q, e);
761 - return QWidget::event(e);
762 + qt_guiSystemTrayIconSysFactory()->unregisterSystemTrayIconPrivate(this);
763 + delete sys;
766 -bool QSystemTrayIconSys::x11Event(XEvent *event)
768 - if (event->type == ReparentNotify)
769 - show();
770 - return QWidget::x11Event(event);
773 -////////////////////////////////////////////////////////////////////////////
774 void QSystemTrayIconPrivate::install_sys()
776 Q_Q(QSystemTrayIcon);
777 - if (!sys)
778 - sys = new QSystemTrayIconSys(q);
779 + if (!sys) {
780 + sys = qt_guiSystemTrayIconSysFactory()->create(q);
781 + if (!sys) {
782 + return;
784 + qt_guiSystemTrayIconSysFactory()->registerSystemTrayIconPrivate(this);
786 + sys->updateVisibility();
789 QRect QSystemTrayIconPrivate::geometry_sys() const
791 - if (!sys)
792 - return QRect();
793 - return QRect(sys->mapToGlobal(QPoint(0, 0)), sys->size());
794 + if (!sys || !visible)
795 + return QRect();
796 + return sys->geometry();
799 void QSystemTrayIconPrivate::remove_sys()
800 @@ -350,35 +153,35 @@ void QSystemTrayIconPrivate::remove_sys()
801 if (!sys)
802 return;
803 QBalloonTip::hideBalloon();
804 - sys->hide(); // this should do the trick, but...
805 - delete sys; // wm may resize system tray only for DestroyEvents
806 - sys = 0;
807 + sys->updateVisibility();
810 void QSystemTrayIconPrivate::updateIcon_sys()
812 - if (!sys)
813 + if (!sys || !visible)
814 return;
815 sys->updateIcon();
818 void QSystemTrayIconPrivate::updateMenu_sys()
821 + if (!sys || !visible)
822 + return;
823 + sys->updateMenu();
826 void QSystemTrayIconPrivate::updateToolTip_sys()
828 - if (!sys)
829 + if (!sys || !visible)
830 return;
831 #ifndef QT_NO_TOOLTIP
832 - sys->setToolTip(toolTip);
833 + sys->updateToolTip();
834 #endif
837 bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
839 - return QSystemTrayIconSys::locateSystemTray() != XNone;
840 + return qt_guiSystemTrayIconSysFactory()->isAvailable();
843 bool QSystemTrayIconPrivate::supportsMessages_sys()
844 @@ -389,12 +192,9 @@ bool QSystemTrayIconPrivate::supportsMessages_sys()
845 void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QString &title,
846 QSystemTrayIcon::MessageIcon icon, int msecs)
848 - if (!sys)
849 + if (!sys || !visible)
850 return;
851 - QPoint g = sys->mapToGlobal(QPoint(0, 0));
852 - QBalloonTip::showBalloon(icon, message, title, sys->q,
853 - QPoint(g.x() + sys->width()/2, g.y() + sys->height()/2),
854 - msecs);
855 + sys->showMessage(message, title, icon, msecs);
858 QT_END_NAMESPACE
859 diff --git a/src/gui/util/qxembedsystemtrayicon_x11.cpp b/src/gui/util/qxembedsystemtrayicon_x11.cpp
860 new file mode 100644
861 index 0000000..d39bc68
862 --- /dev/null
863 +++ b/src/gui/util/qxembedsystemtrayicon_x11.cpp
864 @@ -0,0 +1,469 @@
865 +/****************************************************************************
867 +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
868 +** All rights reserved.
869 +** Contact: Nokia Corporation (qt-info@nokia.com)
871 +** This file is part of the QtGui module of the Qt Toolkit.
873 +** $QT_BEGIN_LICENSE:LGPL$
874 +** GNU Lesser General Public License Usage
875 +** This file may be used under the terms of the GNU Lesser General Public
876 +** License version 2.1 as published by the Free Software Foundation and
877 +** appearing in the file LICENSE.LGPL included in the packaging of this
878 +** file. Please review the following information to ensure the GNU Lesser
879 +** General Public License version 2.1 requirements will be met:
880 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
882 +** In addition, as a special exception, Nokia gives you certain additional
883 +** rights. These rights are described in the Nokia Qt LGPL Exception
884 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
886 +** GNU General Public License Usage
887 +** Alternatively, this file may be used under the terms of the GNU General
888 +** Public License version 3.0 as published by the Free Software Foundation
889 +** and appearing in the file LICENSE.GPL included in the packaging of this
890 +** file. Please review the following information to ensure the GNU General
891 +** Public License version 3.0 requirements will be met:
892 +** http://www.gnu.org/copyleft/gpl.html.
894 +** Other Usage
895 +** Alternatively, this file may be used in accordance with the terms and
896 +** conditions contained in a signed written agreement between you and Nokia.
902 +** $QT_END_LICENSE$
904 +****************************************************************************/
905 +#include "qxembedsystemtrayicon_x11_p.h"
907 +#ifndef QT_NO_SYSTEMTRAYICON
909 +#include "private/qt_x11_p.h"
910 +#include "qapplication.h"
911 +#include "qevent.h"
912 +#include "qlist.h"
913 +#include "qmenu.h"
914 +#include "qpainter.h"
915 +#include "qpaintengine.h"
916 +#include "qsystemtrayicon_p.h"
917 +#include "qx11info_x11.h"
919 +QT_BEGIN_INCLUDE_NAMESPACE
920 +#include <QtCore/qcoreapplication.h>
921 +#include <X11/Xlib.h>
922 +#include <X11/Xatom.h>
923 +#include <X11/Xutil.h>
924 +QT_END_INCLUDE_NAMESPACE
926 +QT_BEGIN_NAMESPACE
928 +class QSystemTrayIconWidget : public QWidget
930 +public:
931 + QSystemTrayIconWidget(QSystemTrayIcon *q, QXEmbedSystemTrayIconSys *s);
932 + ~QSystemTrayIconWidget();
934 + static Window locateSystemTray();
936 +protected:
937 + void paintEvent(QPaintEvent *pe);
938 + void resizeEvent(QResizeEvent *re);
939 + bool x11Event(XEvent *event);
940 + void mousePressEvent(QMouseEvent *event);
941 + void mouseDoubleClickEvent(QMouseEvent *event);
942 +#ifndef QT_NO_WHEELEVENT
943 + void wheelEvent(QWheelEvent *event);
944 +#endif
945 + bool event(QEvent *e);
947 +private:
948 + enum {
949 + SYSTEM_TRAY_REQUEST_DOCK = 0,
950 + SYSTEM_TRAY_BEGIN_MESSAGE = 1,
951 + SYSTEM_TRAY_CANCEL_MESSAGE =2
952 + };
954 + void addToTray();
955 + static XVisualInfo* getSysTrayVisualInfo();
957 + static Window sysTrayWindow;
958 + static QList<QSystemTrayIconWidget *> trayIcons;
959 + static QCoreApplication::EventFilter oldEventFilter;
960 + static bool sysTrayTracker(void *message, long *result);
961 + static Atom sysTraySelection;
962 + static XVisualInfo sysTrayVisual;
964 + QSystemTrayIcon *q;
965 + QXEmbedSystemTrayIconSys *sys;
966 + Colormap colormap;
969 +Window QSystemTrayIconWidget::sysTrayWindow = XNone;
970 +QList<QSystemTrayIconWidget *> QSystemTrayIconWidget::trayIcons;
971 +QCoreApplication::EventFilter QSystemTrayIconWidget::oldEventFilter = 0;
972 +Atom QSystemTrayIconWidget::sysTraySelection = XNone;
973 +XVisualInfo QSystemTrayIconWidget::sysTrayVisual = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
975 +QSystemTrayIconWidget::QSystemTrayIconWidget(QSystemTrayIcon* q, QXEmbedSystemTrayIconSys* sys)
976 +: QWidget(0, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint)
977 +, q(q)
978 +, sys(sys)
979 +, colormap(0)
981 + setAttribute(Qt::WA_AlwaysShowToolTips);
982 + setAttribute(Qt::WA_QuitOnClose, false);
983 + setAttribute(Qt::WA_NoSystemBackground, true);
984 + setAttribute(Qt::WA_PaintOnScreen);
985 + setMouseTracking(true);
986 +#ifndef QT_NO_TOOLTIP
987 + setToolTip(q->toolTip());
988 +#endif
990 + static bool eventFilterAdded = false;
991 + Display *display = QX11Info::display();
992 + if (!eventFilterAdded) {
993 + oldEventFilter = qApp->setEventFilter(sysTrayTracker);
994 + eventFilterAdded = true;
995 + Window root = QX11Info::appRootWindow();
996 + XWindowAttributes attr;
997 + XGetWindowAttributes(display, root, &attr);
998 + if ((attr.your_event_mask & StructureNotifyMask) != StructureNotifyMask) {
999 + (void) QApplication::desktop(); // lame trick to ensure our event mask is not overridden
1000 + XSelectInput(display, root, attr.your_event_mask | StructureNotifyMask); // for MANAGER selection
1003 + if (trayIcons.isEmpty()) {
1004 + sysTrayWindow = locateSystemTray();
1005 + if (sysTrayWindow != XNone)
1006 + XSelectInput(display, sysTrayWindow, StructureNotifyMask); // track tray events
1008 + trayIcons.append(this);
1009 + if (sysTrayWindow != XNone)
1010 + addToTray();
1013 +QSystemTrayIconWidget::~QSystemTrayIconWidget()
1015 + trayIcons.removeAt(trayIcons.indexOf(this));
1016 + Display *display = QX11Info::display();
1017 + if (trayIcons.isEmpty()) {
1018 + if (sysTrayWindow == XNone)
1019 + return;
1020 + if (display)
1021 + XSelectInput(display, sysTrayWindow, 0); // stop tracking the tray
1022 + sysTrayWindow = XNone;
1024 + if (colormap)
1025 + XFreeColormap(display, colormap);
1028 +void QSystemTrayIconWidget::resizeEvent(QResizeEvent *re)
1030 + QWidget::resizeEvent(re);
1031 + update();
1034 +void QSystemTrayIconWidget::paintEvent(QPaintEvent*)
1036 + QPainter p(this);
1037 + if (!getSysTrayVisualInfo()) {
1038 + const QRegion oldSystemClip = p.paintEngine()->systemClip();
1039 + const QRect clearedRect = oldSystemClip.boundingRect();
1040 + XClearArea(QX11Info::display(), winId(), clearedRect.x(), clearedRect.y(),
1041 + clearedRect.width(), clearedRect.height(), False);
1042 + QPaintEngine *pe = p.paintEngine();
1043 + pe->setSystemClip(clearedRect);
1044 + q->icon().paint(&p, rect());
1045 + pe->setSystemClip(oldSystemClip);
1046 + } else {
1047 + p.setCompositionMode(QPainter::CompositionMode_Source);
1048 + p.fillRect(rect(), Qt::transparent);
1049 + p.setCompositionMode(QPainter::CompositionMode_SourceOver);
1050 + q->icon().paint(&p, rect());
1054 +void QSystemTrayIconWidget::mousePressEvent(QMouseEvent *ev)
1056 + QPoint globalPos = ev->globalPos();
1057 + if (ev->button() == Qt::RightButton && q->contextMenu())
1058 + q->contextMenu()->popup(globalPos);
1060 + if (QBalloonTip::isBalloonVisible()) {
1061 + QMetaObject::invokeMethod(q, "messageClicked");
1062 + QBalloonTip::hideBalloon();
1065 + if (ev->button() == Qt::LeftButton)
1066 + qtsystray_sendActivated(q, QSystemTrayIcon::Trigger);
1067 + else if (ev->button() == Qt::RightButton)
1068 + qtsystray_sendActivated(q, QSystemTrayIcon::Context);
1069 + else if (ev->button() == Qt::MidButton)
1070 + qtsystray_sendActivated(q, QSystemTrayIcon::MiddleClick);
1073 +void QSystemTrayIconWidget::mouseDoubleClickEvent(QMouseEvent *ev)
1075 + if (ev->button() == Qt::LeftButton)
1076 + qtsystray_sendActivated(q, QSystemTrayIcon::DoubleClick);
1079 +#ifndef QT_NO_WHEELEVENT
1080 +void QSystemTrayIconWidget::wheelEvent(QWheelEvent *e)
1082 + sys->sendWheelEventToTrayIcon(e->delta(), e->orientation());
1084 +#endif
1086 +bool QSystemTrayIconWidget::event(QEvent *e)
1088 + if (e->type() == QEvent::ToolTip) {
1089 + sys->sendToolTipEventToTrayIcon();
1091 + return QWidget::event(e);
1094 +bool QSystemTrayIconWidget::x11Event(XEvent *event)
1096 + if (event->type == ReparentNotify)
1097 + show();
1098 + return QWidget::x11Event(event);
1101 +// Locate the system tray
1102 +Window QSystemTrayIconWidget::locateSystemTray()
1104 + Display *display = QX11Info::display();
1105 + if (sysTraySelection == XNone) {
1106 + int screen = QX11Info::appScreen();
1107 + QString net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen);
1108 + sysTraySelection = XInternAtom(display, net_sys_tray.toLatin1(), False);
1111 + return XGetSelectionOwner(QX11Info::display(), sysTraySelection);
1114 +XVisualInfo* QSystemTrayIconWidget::getSysTrayVisualInfo()
1116 + Display *display = QX11Info::display();
1118 + if (!sysTrayVisual.visual) {
1119 + Window win = locateSystemTray();
1120 + if (win != XNone) {
1121 + Atom actual_type;
1122 + int actual_format;
1123 + ulong nitems, bytes_remaining;
1124 + uchar *data = 0;
1125 + int result = XGetWindowProperty(display, win, ATOM(_NET_SYSTEM_TRAY_VISUAL), 0, 1,
1126 + False, XA_VISUALID, &actual_type,
1127 + &actual_format, &nitems, &bytes_remaining, &data);
1128 + VisualID vid = 0;
1129 + if (result == Success && data && actual_type == XA_VISUALID && actual_format == 32 &&
1130 + nitems == 1 && bytes_remaining == 0)
1131 + vid = *(VisualID*)data;
1132 + if (data)
1133 + XFree(data);
1134 + if (vid == 0)
1135 + return 0;
1137 + uint mask = VisualIDMask;
1138 + XVisualInfo *vi, rvi;
1139 + int count;
1140 + rvi.visualid = vid;
1141 + vi = XGetVisualInfo(display, mask, &rvi, &count);
1142 + if (vi) {
1143 + sysTrayVisual = vi[0];
1144 + XFree((char*)vi);
1146 + if (sysTrayVisual.depth != 32)
1147 + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
1151 + return sysTrayVisual.visual ? &sysTrayVisual : 0;
1154 +bool QSystemTrayIconWidget::sysTrayTracker(void *message, long *result)
1156 + bool retval = false;
1157 + if (QSystemTrayIconWidget::oldEventFilter)
1158 + retval = QSystemTrayIconWidget::oldEventFilter(message, result);
1160 + if (trayIcons.isEmpty())
1161 + return retval;
1163 + Display *display = QX11Info::display();
1164 + XEvent *ev = (XEvent *)message;
1165 + if (ev->type == DestroyNotify && ev->xany.window == sysTrayWindow) {
1166 + sysTrayWindow = locateSystemTray();
1167 + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
1168 + for (int i = 0; i < trayIcons.count(); i++) {
1169 + if (sysTrayWindow == XNone) {
1170 + QBalloonTip::hideBalloon();
1171 + trayIcons[i]->hide(); // still no luck
1172 + trayIcons[i]->destroy();
1173 + trayIcons[i]->create();
1174 + } else
1175 + trayIcons[i]->addToTray(); // add it to the new tray
1177 + retval = true;
1178 + } else if (ev->type == ClientMessage && sysTrayWindow == XNone) {
1179 + static Atom manager_atom = XInternAtom(display, "MANAGER", False);
1180 + XClientMessageEvent *cm = (XClientMessageEvent *)message;
1181 + if ((cm->message_type == manager_atom) && ((Atom)cm->data.l[1] == sysTraySelection)) {
1182 + sysTrayWindow = cm->data.l[2];
1183 + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
1184 + XSelectInput(display, sysTrayWindow, StructureNotifyMask);
1185 + for (int i = 0; i < trayIcons.count(); i++) {
1186 + trayIcons[i]->addToTray();
1188 + retval = true;
1190 + } else if (ev->type == PropertyNotify && ev->xproperty.atom == ATOM(_NET_SYSTEM_TRAY_VISUAL) &&
1191 + ev->xproperty.window == sysTrayWindow) {
1192 + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual));
1193 + for (int i = 0; i < trayIcons.count(); i++) {
1194 + trayIcons[i]->addToTray();
1198 + return retval;
1201 +void QSystemTrayIconWidget::addToTray()
1203 + Q_ASSERT(sysTrayWindow != XNone);
1204 + Display *display = QX11Info::display();
1206 + XVisualInfo *vi = getSysTrayVisualInfo();
1207 + if (vi && vi->visual) {
1208 + Window root = RootWindow(display, vi->screen);
1209 + Window p = root;
1210 + if (QWidget *pw = parentWidget())
1211 + p = pw->effectiveWinId();
1212 + colormap = XCreateColormap(display, root, vi->visual, AllocNone);
1213 + XSetWindowAttributes wsa;
1214 + wsa.background_pixmap = 0;
1215 + wsa.colormap = colormap;
1216 + wsa.background_pixel = 0;
1217 + wsa.border_pixel = 0;
1218 + Window wid = XCreateWindow(display, p, -1, -1, 1, 1,
1219 + 0, vi->depth, InputOutput, vi->visual,
1220 + CWBackPixmap|CWBackPixel|CWBorderPixel|CWColormap, &wsa);
1221 + create(wid);
1222 + } else {
1223 + XSetWindowBackgroundPixmap(display, winId(), ParentRelative);
1226 + // GNOME, NET WM Specification
1227 + static Atom netwm_tray_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False);
1228 + long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, winId(), 0, 0 };
1229 + XEvent ev;
1230 + memset(&ev, 0, sizeof(ev));
1231 + ev.xclient.type = ClientMessage;
1232 + ev.xclient.window = sysTrayWindow;
1233 + ev.xclient.message_type = netwm_tray_atom;
1234 + ev.xclient.format = 32;
1235 + memcpy((char *)&ev.xclient.data, (const char *) l, sizeof(l));
1236 + XSendEvent(display, sysTrayWindow, False, 0, &ev);
1237 + setMinimumSize(22, 22); // required at least on GNOME
1240 +////////////////////////////////////////////////////////////////////////////
1241 +QXEmbedSystemTrayIconSys::QXEmbedSystemTrayIconSys(QSystemTrayIcon *q)
1242 +: QAbstractSystemTrayIconSys(q)
1243 +, widget(0)
1247 +QXEmbedSystemTrayIconSys::~QXEmbedSystemTrayIconSys()
1249 + delete widget;
1252 +QRect QXEmbedSystemTrayIconSys::geometry() const
1254 + if (!widget)
1255 + return QRect();
1256 + return QRect(widget->mapToGlobal(QPoint(0, 0)), widget->size());
1259 +void QXEmbedSystemTrayIconSys::updateIcon()
1261 + if (!widget)
1262 + return;
1263 + widget->update();
1266 +void QXEmbedSystemTrayIconSys::updateToolTip()
1268 + if (!widget)
1269 + return;
1270 + widget->setToolTip(trayIcon->toolTip());
1273 +void QXEmbedSystemTrayIconSys::showMessage(const QString &message, const QString &title,
1274 + QSystemTrayIcon::MessageIcon icon, int msecs)
1276 + if (!widget)
1277 + return;
1278 + QPoint point = geometry().center();
1279 + QBalloonTip::showBalloon(icon, message, title, trayIcon, point, msecs);
1282 +void QXEmbedSystemTrayIconSys::updateVisibility()
1284 + bool visible = trayIcon->isVisible();
1285 + if (visible && !widget)
1286 + widget = new QSystemTrayIconWidget(trayIcon, this);
1287 + else if (!visible && widget) {
1288 + delete widget;
1289 + widget = 0;
1293 +void QXEmbedSystemTrayIconSys::sendToolTipEventToTrayIcon()
1295 +#ifndef QT_NO_TOOLTIP
1296 + // Pass the event through QSystemTrayIcon so that it gets a chance to
1297 + // update the tooltip, then asks widget to show the tooltip
1298 + Q_ASSERT(widget);
1299 + QPoint globalPos = QCursor::pos();
1300 + QPoint pos = widget->mapFromGlobal(globalPos);
1301 + QHelpEvent event(QEvent::ToolTip, pos, globalPos);
1302 + QApplication::sendEvent(trayIcon, &event);
1303 +#endif
1306 +void QXEmbedSystemTrayIconSys::sendWheelEventToTrayIcon(int delta, Qt::Orientation orientation)
1308 +#ifndef QT_NO_WHEELEVENT
1309 + Q_ASSERT(widget);
1310 + QPoint globalPos = QCursor::pos();
1311 + QPoint pos = widget->mapFromGlobal(globalPos);
1312 + QWheelEvent event(pos, globalPos, delta, Qt::NoButton, Qt::NoModifier, orientation);
1313 + QApplication::sendEvent(trayIcon, &event);
1314 +#endif
1317 +void QXEmbedSystemTrayIconSys::updateMenu()
1321 +/////////////////////////////////////////////////////////////
1322 +QAbstractSystemTrayIconSys * QXEmbedSystemTrayIconSysFactory::create(QSystemTrayIcon *icon)
1324 + return new QXEmbedSystemTrayIconSys(icon);
1327 +bool QXEmbedSystemTrayIconSysFactory::isAvailable() const
1329 + return QSystemTrayIconWidget::locateSystemTray() != XNone;
1332 +QT_END_NAMESPACE
1333 +#endif //QT_NO_SYSTEMTRAYICON
1334 diff --git a/src/gui/util/qxembedsystemtrayicon_x11_p.h b/src/gui/util/qxembedsystemtrayicon_x11_p.h
1335 new file mode 100644
1336 index 0000000..9fcc908
1337 --- /dev/null
1338 +++ b/src/gui/util/qxembedsystemtrayicon_x11_p.h
1339 @@ -0,0 +1,104 @@
1340 +/****************************************************************************
1342 +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
1343 +** All rights reserved.
1344 +** Contact: Nokia Corporation (qt-info@nokia.com)
1346 +** This file is part of the QtGui module of the Qt Toolkit.
1348 +** $QT_BEGIN_LICENSE:LGPL$
1349 +** GNU Lesser General Public License Usage
1350 +** This file may be used under the terms of the GNU Lesser General Public
1351 +** License version 2.1 as published by the Free Software Foundation and
1352 +** appearing in the file LICENSE.LGPL included in the packaging of this
1353 +** file. Please review the following information to ensure the GNU Lesser
1354 +** General Public License version 2.1 requirements will be met:
1355 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
1357 +** In addition, as a special exception, Nokia gives you certain additional
1358 +** rights. These rights are described in the Nokia Qt LGPL Exception
1359 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
1361 +** GNU General Public License Usage
1362 +** Alternatively, this file may be used under the terms of the GNU General
1363 +** Public License version 3.0 as published by the Free Software Foundation
1364 +** and appearing in the file LICENSE.GPL included in the packaging of this
1365 +** file. Please review the following information to ensure the GNU General
1366 +** Public License version 3.0 requirements will be met:
1367 +** http://www.gnu.org/copyleft/gpl.html.
1369 +** Other Usage
1370 +** Alternatively, this file may be used in accordance with the terms and
1371 +** conditions contained in a signed written agreement between you and Nokia.
1377 +** $QT_END_LICENSE$
1379 +****************************************************************************/
1381 +#ifndef QXEMBEDSYSTEMTRAYICON_X11_P_H
1382 +#define QXEMBEDSYSTEMTRAYICON_X11_P_H
1385 +// W A R N I N G
1386 +// -------------
1388 +// This file is not part of the Qt API. It exists for the convenience
1389 +// of a number of Qt sources files. This header file may change from
1390 +// version to version without notice, or even be removed.
1392 +// We mean it.
1395 +#ifndef QT_NO_SYSTEMTRAYICON
1397 +#include "qabstractsystemtrayiconsys_p.h"
1399 +QT_BEGIN_NAMESPACE
1401 +class QSystemTrayIconWidget;
1403 +class QXEmbedSystemTrayIconSys : public QAbstractSystemTrayIconSys
1405 +public:
1406 + QXEmbedSystemTrayIconSys(QSystemTrayIcon *);
1407 + ~QXEmbedSystemTrayIconSys();
1409 + QRect geometry() const;
1411 + void updateVisibility();
1413 + void updateIcon();
1415 + void updateToolTip();
1417 + void updateMenu();
1419 + void showMessage(const QString &message, const QString &title,
1420 + QSystemTrayIcon::MessageIcon icon, int msecs);
1422 +private:
1423 + friend class QSystemTrayIconWidget;
1424 + QSystemTrayIconWidget *widget;
1426 + void sendToolTipEventToTrayIcon();
1428 + void sendWheelEventToTrayIcon(int delta, Qt::Orientation orientation);
1431 +struct QXEmbedSystemTrayIconSysFactory : public QSystemTrayIconSysFactoryInterface
1433 + QAbstractSystemTrayIconSys * create(QSystemTrayIcon *trayIcon);
1434 + bool isAvailable() const;
1438 +QT_END_NAMESPACE
1440 +#endif // QT_NO_SYSTEMTRAYICON
1442 +#endif // QXEMBEDSYSTEMTRAYICON_X11_P_H
1444 diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
1445 index d1c4ff8..c225183 100644
1446 --- a/src/gui/util/util.pri
1447 +++ b/src/gui/util/util.pri
1448 @@ -29,8 +29,13 @@ wince* {
1451 unix:x11 {
1452 + HEADERS += \
1453 + util/qabstractsystemtrayiconsys_p.h \
1454 + util/qxembedsystemtrayicon_x11_p.h
1455 SOURCES += \
1456 - util/qsystemtrayicon_x11.cpp
1457 + util/qabstractsystemtrayiconsys.cpp \
1458 + util/qsystemtrayicon_x11.cpp \
1459 + util/qxembedsystemtrayicon_x11.cpp
1462 embedded {
1463 @@ -56,4 +61,4 @@ symbian {
1464 } else {
1465 DEFINES += USE_SCHEMEHANDLER
1468 \ No newline at end of file