Annotation of /trunk/qt4/patches/qt-4.8.7-systemtrayicon.patch
Parent Directory | Revision Log
Revision 2917 -
(hide annotations)
(download)
Wed May 17 09:04:25 2017 UTC (7 years, 4 months ago) by niro
File size: 48692 byte(s)
Wed May 17 09:04:25 2017 UTC (7 years, 4 months ago) by niro
File size: 48692 byte(s)
-fixed patches
1 | niro | 2917 | Description: Introduce a plugin system for QSystemTrayIcon. |
2 | niro | 2912 | Designed to be used with sni-qt (https://launchpad.net/sni-qt) |
3 | niro | 2917 | Author: agateau@kde.org |
4 | niro | 2912 | Forwarded: no |
5 | |||
6 | Introduce a plugin system for QSystemTrayIcon. Designed to be used with sni-qt | ||
7 | (https://launchpad.net/sni-qt) | ||
8 | niro | 2917 | --- |
9 | niro | 2912 | examples/desktop/systray/window.cpp | 40 ++ |
10 | examples/desktop/systray/window.h | 6 | ||
11 | src/gui/util/qabstractsystemtrayiconsys.cpp | 65 +++ | ||
12 | src/gui/util/qabstractsystemtrayiconsys_p.h | 106 ++++++ | ||
13 | src/gui/util/qsystemtrayicon.cpp | 6 | ||
14 | src/gui/util/qsystemtrayicon_p.h | 85 ++--- | ||
15 | src/gui/util/qsystemtrayicon_x11.cpp | 356 ++++----------------- | ||
16 | src/gui/util/qxembedsystemtrayicon_x11.cpp | 469 ++++++++++++++++++++++++++++ | ||
17 | src/gui/util/qxembedsystemtrayicon_x11_p.h | 104 ++++++ | ||
18 | src/gui/util/util.pri | 7 | ||
19 | 10 files changed, 916 insertions(+), 328 deletions(-) | ||
20 | |||
21 | niro | 2917 | --- a/examples/desktop/systray/window.cpp |
22 | +++ b/examples/desktop/systray/window.cpp | ||
23 | @@ -158,15 +158,23 @@ | ||
24 | iconComboBox->addItem(QIcon(":/images/bad.svg"), tr("Bad")); | ||
25 | iconComboBox->addItem(QIcon(":/images/heart.svg"), tr("Heart")); | ||
26 | iconComboBox->addItem(QIcon(":/images/trash.svg"), tr("Trash")); | ||
27 | + iconComboBox->addItem(QIcon::fromTheme("system-file-manager"), tr("File Manager")); | ||
28 | niro | 2912 | |
29 | niro | 2917 | showIconCheckBox = new QCheckBox(tr("Show icon")); |
30 | showIconCheckBox->setChecked(true); | ||
31 | niro | 2912 | |
32 | niro | 2917 | +#if defined(Q_WS_X11) |
33 | + jitToolTipCheckBox = new QCheckBox(tr("Just In Time Tooltip")); | ||
34 | +#endif | ||
35 | + | ||
36 | niro | 2912 | QHBoxLayout *iconLayout = new QHBoxLayout; |
37 | niro | 2917 | iconLayout->addWidget(iconLabel); |
38 | iconLayout->addWidget(iconComboBox); | ||
39 | iconLayout->addStretch(); | ||
40 | iconLayout->addWidget(showIconCheckBox); | ||
41 | +#if defined(Q_WS_X11) | ||
42 | + iconLayout->addWidget(jitToolTipCheckBox); | ||
43 | +#endif | ||
44 | iconGroupBox->setLayout(iconLayout); | ||
45 | niro | 2912 | } |
46 | |||
47 | niro | 2917 | @@ -254,5 +262,37 @@ |
48 | trayIconMenu->addAction(quitAction); | ||
49 | niro | 2912 | |
50 | trayIcon = new QSystemTrayIcon(this); | ||
51 | niro | 2917 | + QByteArray category = qgetenv("SNI_CATEGORY"); |
52 | + if (!category.isEmpty()) { | ||
53 | + trayIcon->setProperty("_qt_sni_category", QString::fromLocal8Bit(category)); | ||
54 | + } | ||
55 | trayIcon->setContextMenu(trayIconMenu); | ||
56 | + | ||
57 | +#if defined(Q_WS_X11) | ||
58 | + trayIcon->installEventFilter(this); | ||
59 | +#endif | ||
60 | +} | ||
61 | + | ||
62 | +#if defined(Q_WS_X11) | ||
63 | +bool Window::eventFilter(QObject *, QEvent *event) | ||
64 | +{ | ||
65 | + switch(event->type()) { | ||
66 | + case QEvent::ToolTip: | ||
67 | + if (jitToolTipCheckBox->isChecked()) { | ||
68 | + QString timeString = QTime::currentTime().toString(); | ||
69 | + trayIcon->setToolTip(tr("Current Time: %1").arg(timeString)); | ||
70 | + } | ||
71 | + break; | ||
72 | + case QEvent::Wheel: { | ||
73 | + QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event); | ||
74 | + int delta = wheelEvent->delta() > 0 ? 1 : -1; | ||
75 | + int index = (iconComboBox->currentIndex() + delta) % iconComboBox->count(); | ||
76 | + iconComboBox->setCurrentIndex(index); | ||
77 | + break; | ||
78 | + } | ||
79 | + default: | ||
80 | + break; | ||
81 | + } | ||
82 | + return false; | ||
83 | niro | 2912 | } |
84 | niro | 2917 | +#endif |
85 | --- a/examples/desktop/systray/window.h | ||
86 | +++ b/examples/desktop/systray/window.h | ||
87 | @@ -69,6 +69,9 @@ | ||
88 | niro | 2912 | |
89 | protected: | ||
90 | void closeEvent(QCloseEvent *event); | ||
91 | niro | 2917 | +#if defined(Q_WS_X11) |
92 | + bool eventFilter(QObject *object, QEvent *event); | ||
93 | +#endif | ||
94 | niro | 2912 | |
95 | private slots: | ||
96 | void setIcon(int index); | ||
97 | niro | 2917 | @@ -86,6 +89,9 @@ |
98 | niro | 2912 | QLabel *iconLabel; |
99 | QComboBox *iconComboBox; | ||
100 | QCheckBox *showIconCheckBox; | ||
101 | niro | 2917 | +#if defined(Q_WS_X11) |
102 | + QCheckBox *jitToolTipCheckBox; | ||
103 | +#endif | ||
104 | niro | 2912 | |
105 | QGroupBox *messageGroupBox; | ||
106 | QLabel *typeLabel; | ||
107 | niro | 2917 | --- /dev/null |
108 | +++ b/src/gui/util/qabstractsystemtrayiconsys.cpp | ||
109 | @@ -0,0 +1,65 @@ | ||
110 | +/**************************************************************************** | ||
111 | +** | ||
112 | +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | ||
113 | +** All rights reserved. | ||
114 | +** Contact: Nokia Corporation (qt-info@nokia.com) | ||
115 | +** | ||
116 | +** This file is part of the QtGui module of the Qt Toolkit. | ||
117 | +** | ||
118 | +** $QT_BEGIN_LICENSE:LGPL$ | ||
119 | +** GNU Lesser General Public License Usage | ||
120 | +** This file may be used under the terms of the GNU Lesser General Public | ||
121 | +** License version 2.1 as published by the Free Software Foundation and | ||
122 | +** appearing in the file LICENSE.LGPL included in the packaging of this | ||
123 | +** file. Please review the following information to ensure the GNU Lesser | ||
124 | +** General Public License version 2.1 requirements will be met: | ||
125 | +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
126 | +** | ||
127 | +** In addition, as a special exception, Nokia gives you certain additional | ||
128 | +** rights. These rights are described in the Nokia Qt LGPL Exception | ||
129 | +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
130 | +** | ||
131 | +** GNU General Public License Usage | ||
132 | +** Alternatively, this file may be used under the terms of the GNU General | ||
133 | +** Public License version 3.0 as published by the Free Software Foundation | ||
134 | +** and appearing in the file LICENSE.GPL included in the packaging of this | ||
135 | +** file. Please review the following information to ensure the GNU General | ||
136 | +** Public License version 3.0 requirements will be met: | ||
137 | +** http://www.gnu.org/copyleft/gpl.html. | ||
138 | +** | ||
139 | +** Other Usage | ||
140 | +** Alternatively, this file may be used in accordance with the terms and | ||
141 | +** conditions contained in a signed written agreement between you and Nokia. | ||
142 | +** | ||
143 | +** | ||
144 | +** | ||
145 | +** | ||
146 | +** | ||
147 | +** $QT_END_LICENSE$ | ||
148 | +** | ||
149 | +****************************************************************************/ | ||
150 | +#ifndef QT_NO_SYSTEMTRAYICON | ||
151 | + | ||
152 | +#include "qabstractsystemtrayiconsys_p.h" | ||
153 | + | ||
154 | + | ||
155 | +QSystemTrayIconSysFactoryInterface::QSystemTrayIconSysFactoryInterface() | ||
156 | +{ | ||
157 | +} | ||
158 | + | ||
159 | +///////////////////////////////////////////////// | ||
160 | +QAbstractSystemTrayIconSys::QAbstractSystemTrayIconSys(QSystemTrayIcon *icon) | ||
161 | +: trayIcon(icon) | ||
162 | +{ | ||
163 | +} | ||
164 | + | ||
165 | +QAbstractSystemTrayIconSys::~QAbstractSystemTrayIconSys() | ||
166 | +{ | ||
167 | +} | ||
168 | + | ||
169 | +void QAbstractSystemTrayIconSys::sendActivated(QSystemTrayIcon::ActivationReason reason) | ||
170 | +{ | ||
171 | + qtsystray_sendActivated(trayIcon, reason); | ||
172 | +} | ||
173 | + | ||
174 | +#endif | ||
175 | --- /dev/null | ||
176 | +++ b/src/gui/util/qabstractsystemtrayiconsys_p.h | ||
177 | @@ -0,0 +1,106 @@ | ||
178 | +/**************************************************************************** | ||
179 | +** | ||
180 | +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | ||
181 | +** All rights reserved. | ||
182 | +** Contact: Nokia Corporation (qt-info@nokia.com) | ||
183 | +** | ||
184 | +** This file is part of the QtGui module of the Qt Toolkit. | ||
185 | +** | ||
186 | +** $QT_BEGIN_LICENSE:LGPL$ | ||
187 | +** GNU Lesser General Public License Usage | ||
188 | +** This file may be used under the terms of the GNU Lesser General Public | ||
189 | +** License version 2.1 as published by the Free Software Foundation and | ||
190 | +** appearing in the file LICENSE.LGPL included in the packaging of this | ||
191 | +** file. Please review the following information to ensure the GNU Lesser | ||
192 | +** General Public License version 2.1 requirements will be met: | ||
193 | +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
194 | +** | ||
195 | +** In addition, as a special exception, Nokia gives you certain additional | ||
196 | +** rights. These rights are described in the Nokia Qt LGPL Exception | ||
197 | +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
198 | +** | ||
199 | +** GNU General Public License Usage | ||
200 | +** Alternatively, this file may be used under the terms of the GNU General | ||
201 | +** Public License version 3.0 as published by the Free Software Foundation | ||
202 | +** and appearing in the file LICENSE.GPL included in the packaging of this | ||
203 | +** file. Please review the following information to ensure the GNU General | ||
204 | +** Public License version 3.0 requirements will be met: | ||
205 | +** http://www.gnu.org/copyleft/gpl.html. | ||
206 | +** | ||
207 | +** Other Usage | ||
208 | +** Alternatively, this file may be used in accordance with the terms and | ||
209 | +** conditions contained in a signed written agreement between you and Nokia. | ||
210 | +** | ||
211 | +** | ||
212 | +** | ||
213 | +** | ||
214 | +** | ||
215 | +** $QT_END_LICENSE$ | ||
216 | +** | ||
217 | +****************************************************************************/ | ||
218 | + | ||
219 | +#ifndef QABSTRACTSYSTEMTRAYICONSYS_P_H | ||
220 | +#define QABSTRACTSYSTEMTRAYICONSYS_P_H | ||
221 | + | ||
222 | +// | ||
223 | +// W A R N I N G | ||
224 | +// ------------- | ||
225 | +// | ||
226 | +// This file is not part of the Qt API. It exists for the convenience | ||
227 | +// of a number of Qt sources files. This header file may change from | ||
228 | +// version to version without notice, or even be removed. | ||
229 | +// | ||
230 | +// We mean it. | ||
231 | +// | ||
232 | + | ||
233 | +#ifndef QT_NO_SYSTEMTRAYICON | ||
234 | + | ||
235 | +#include <qfactoryinterface.h> | ||
236 | +#include <qsystemtrayicon.h> | ||
237 | + | ||
238 | +class QAbstractSystemTrayIconSys; | ||
239 | + | ||
240 | +class Q_GUI_EXPORT QSystemTrayIconSysFactoryInterface : public QObject, public QFactoryInterface | ||
241 | +{ | ||
242 | + Q_OBJECT | ||
243 | +public: | ||
244 | + QSystemTrayIconSysFactoryInterface(); | ||
245 | + virtual QAbstractSystemTrayIconSys * create(QSystemTrayIcon *) = 0; | ||
246 | + virtual bool isAvailable() const = 0; | ||
247 | + | ||
248 | + // \reimp | ||
249 | + virtual QStringList keys() const { return QStringList() << QLatin1String("default"); } | ||
250 | + | ||
251 | +Q_SIGNALS: | ||
252 | + void availableChanged(bool); | ||
253 | +}; | ||
254 | + | ||
255 | +#define QSystemTrayIconSysFactoryInterface_iid "com.nokia.qt.QSystemTrayIconSysFactoryInterface" | ||
256 | +Q_DECLARE_INTERFACE(QSystemTrayIconSysFactoryInterface, QSystemTrayIconSysFactoryInterface_iid) | ||
257 | + | ||
258 | +class QRect; | ||
259 | + | ||
260 | +class Q_GUI_EXPORT QAbstractSystemTrayIconSys | ||
261 | +{ | ||
262 | +public: | ||
263 | + QAbstractSystemTrayIconSys(QSystemTrayIcon *icon); | ||
264 | + virtual ~QAbstractSystemTrayIconSys(); | ||
265 | + | ||
266 | + virtual QRect geometry() const = 0; | ||
267 | + virtual void updateVisibility() = 0; | ||
268 | + virtual void updateIcon() = 0; | ||
269 | + virtual void updateToolTip() = 0; | ||
270 | + virtual void updateMenu() = 0; | ||
271 | + virtual void showMessage(const QString &title, const QString &message, | ||
272 | + QSystemTrayIcon::MessageIcon icon, int msecs) = 0; | ||
273 | + | ||
274 | + void sendActivated(QSystemTrayIcon::ActivationReason); | ||
275 | + | ||
276 | +protected: | ||
277 | + QSystemTrayIcon *trayIcon; | ||
278 | +}; | ||
279 | + | ||
280 | +#endif // QT_NO_SYSTEMTRAYICON | ||
281 | + | ||
282 | +#endif // QABSTRACTSYSTEMTRAYICONSYS_P_H | ||
283 | + | ||
284 | --- a/src/gui/util/qsystemtrayicon.cpp | ||
285 | +++ b/src/gui/util/qsystemtrayicon.cpp | ||
286 | @@ -287,12 +287,6 @@ | ||
287 | niro | 2912 | */ |
288 | bool QSystemTrayIcon::event(QEvent *e) | ||
289 | { | ||
290 | niro | 2917 | -#if defined(Q_WS_X11) |
291 | - if (e->type() == QEvent::ToolTip) { | ||
292 | - Q_D(QSystemTrayIcon); | ||
293 | - return d->sys->deliverToolTipEvent(e); | ||
294 | - } | ||
295 | -#endif | ||
296 | niro | 2912 | return QObject::event(e); |
297 | } | ||
298 | |||
299 | niro | 2917 | --- a/src/gui/util/qsystemtrayicon_p.h |
300 | +++ b/src/gui/util/qsystemtrayicon_p.h | ||
301 | @@ -62,10 +62,17 @@ | ||
302 | #include "QtGui/qpixmap.h" | ||
303 | #include "QtCore/qstring.h" | ||
304 | #include "QtCore/qpointer.h" | ||
305 | +#if defined(Q_WS_X11) | ||
306 | +#include "QtCore/qset.h" | ||
307 | +#endif | ||
308 | niro | 2912 | |
309 | QT_BEGIN_NAMESPACE | ||
310 | |||
311 | niro | 2917 | +#if defined(Q_WS_X11) |
312 | +class QAbstractSystemTrayIconSys; | ||
313 | +#else | ||
314 | niro | 2912 | class QSystemTrayIconSys; |
315 | niro | 2917 | +#endif |
316 | niro | 2912 | class QToolButton; |
317 | class QLabel; | ||
318 | |||
319 | niro | 2917 | @@ -75,6 +82,9 @@ |
320 | niro | 2912 | |
321 | public: | ||
322 | QSystemTrayIconPrivate() : sys(0), visible(false) { } | ||
323 | niro | 2917 | + #if defined(Q_WS_X11) |
324 | + ~QSystemTrayIconPrivate(); | ||
325 | + #endif | ||
326 | niro | 2912 | |
327 | void install_sys(); | ||
328 | void remove_sys(); | ||
329 | niro | 2917 | @@ -90,7 +100,11 @@ |
330 | QPointer<QMenu> menu; | ||
331 | niro | 2912 | QIcon icon; |
332 | QString toolTip; | ||
333 | niro | 2917 | + #if defined(Q_WS_X11) |
334 | + QAbstractSystemTrayIconSys *sys; | ||
335 | + #else | ||
336 | niro | 2912 | QSystemTrayIconSys *sys; |
337 | niro | 2917 | + #endif |
338 | niro | 2912 | bool visible; |
339 | }; | ||
340 | |||
341 | niro | 2917 | @@ -123,60 +137,37 @@ |
342 | niro | 2912 | }; |
343 | |||
344 | #if defined(Q_WS_X11) | ||
345 | niro | 2917 | -QT_BEGIN_INCLUDE_NAMESPACE |
346 | -#include <QtCore/qcoreapplication.h> | ||
347 | -#include <X11/Xlib.h> | ||
348 | -#include <X11/Xatom.h> | ||
349 | -#include <X11/Xutil.h> | ||
350 | -QT_END_INCLUDE_NAMESPACE | ||
351 | +class QSystemTrayIconSysFactoryInterface; | ||
352 | niro | 2912 | |
353 | niro | 2917 | -class QSystemTrayIconSys : public QWidget |
354 | +/** | ||
355 | + * This class acts as a composite QSystemTrayIconSysFactory: It can create | ||
356 | + * instances of QAbstractSystemTrayIconSys* using either a plugin or the | ||
357 | + * builtin factory and will cause QSystemTrayIconPrivate to recreate their | ||
358 | + * 'sys' instances if the plugin availability changes. | ||
359 | + */ | ||
360 | +class QSystemTrayIconSysFactory : public QObject | ||
361 | niro | 2912 | { |
362 | niro | 2917 | - friend class QSystemTrayIconPrivate; |
363 | - | ||
364 | + Q_OBJECT | ||
365 | niro | 2912 | public: |
366 | niro | 2917 | - QSystemTrayIconSys(QSystemTrayIcon *q); |
367 | - ~QSystemTrayIconSys(); | ||
368 | - enum { | ||
369 | - SYSTEM_TRAY_REQUEST_DOCK = 0, | ||
370 | - SYSTEM_TRAY_BEGIN_MESSAGE = 1, | ||
371 | - SYSTEM_TRAY_CANCEL_MESSAGE =2 | ||
372 | - }; | ||
373 | - | ||
374 | - void addToTray(); | ||
375 | - void updateIcon(); | ||
376 | - XVisualInfo* getSysTrayVisualInfo(); | ||
377 | - | ||
378 | - // QObject::event is public but QWidget's ::event() re-implementation | ||
379 | - // is protected ;( | ||
380 | - inline bool deliverToolTipEvent(QEvent *e) | ||
381 | - { return QWidget::event(e); } | ||
382 | - | ||
383 | - static Window sysTrayWindow; | ||
384 | - static QList<QSystemTrayIconSys *> trayIcons; | ||
385 | - static QCoreApplication::EventFilter oldEventFilter; | ||
386 | - static bool sysTrayTracker(void *message, long *result); | ||
387 | - static Window locateSystemTray(); | ||
388 | - static Atom sysTraySelection; | ||
389 | - static XVisualInfo sysTrayVisual; | ||
390 | + QSystemTrayIconSysFactory(); | ||
391 | + void registerSystemTrayIconPrivate(QSystemTrayIconPrivate *iconPrivate); | ||
392 | + void unregisterSystemTrayIconPrivate(QSystemTrayIconPrivate *iconPrivate); | ||
393 | niro | 2912 | |
394 | niro | 2917 | -protected: |
395 | - void paintEvent(QPaintEvent *pe); | ||
396 | - void resizeEvent(QResizeEvent *re); | ||
397 | - bool x11Event(XEvent *event); | ||
398 | - void mousePressEvent(QMouseEvent *event); | ||
399 | - void mouseDoubleClickEvent(QMouseEvent *event); | ||
400 | -#ifndef QT_NO_WHEELEVENT | ||
401 | - void wheelEvent(QWheelEvent *event); | ||
402 | -#endif | ||
403 | - bool event(QEvent *e); | ||
404 | + QAbstractSystemTrayIconSys *create(QSystemTrayIcon *) const; | ||
405 | + | ||
406 | + bool isAvailable() const; | ||
407 | + | ||
408 | +private Q_SLOTS: | ||
409 | + void refreshTrayIconPrivates(); | ||
410 | niro | 2912 | |
411 | private: | ||
412 | niro | 2917 | - QPixmap background; |
413 | - QSystemTrayIcon *q; | ||
414 | - Colormap colormap; | ||
415 | + QSystemTrayIconSysFactoryInterface *factory() const; | ||
416 | + void loadPluginFactory(); | ||
417 | + | ||
418 | + QSystemTrayIconSysFactoryInterface *pluginFactory; | ||
419 | + QSet<QSystemTrayIconPrivate *> trayIconPrivates; | ||
420 | niro | 2912 | }; |
421 | niro | 2917 | -#endif // Q_WS_X11 |
422 | +#endif | ||
423 | niro | 2912 | |
424 | QT_END_NAMESPACE | ||
425 | |||
426 | niro | 2917 | --- a/src/gui/util/qsystemtrayicon_x11.cpp |
427 | +++ b/src/gui/util/qsystemtrayicon_x11.cpp | ||
428 | @@ -38,311 +38,122 @@ | ||
429 | niro | 2912 | ** $QT_END_LICENSE$ |
430 | ** | ||
431 | ****************************************************************************/ | ||
432 | niro | 2917 | +#ifndef QT_NO_SYSTEMTRAYICON |
433 | + | ||
434 | +#include <private/qfactoryloader_p.h> | ||
435 | niro | 2912 | |
436 | niro | 2917 | -#include "private/qt_x11_p.h" |
437 | -#include "qlabel.h" | ||
438 | -#include "qx11info_x11.h" | ||
439 | -#include "qpainter.h" | ||
440 | -#include "qpixmap.h" | ||
441 | -#include "qbitmap.h" | ||
442 | -#include "qevent.h" | ||
443 | -#include "qapplication.h" | ||
444 | -#include "qlist.h" | ||
445 | -#include "qmenu.h" | ||
446 | -#include "qtimer.h" | ||
447 | #include "qsystemtrayicon_p.h" | ||
448 | -#include "qpaintengine.h" | ||
449 | +#include "qabstractsystemtrayiconsys_p.h" | ||
450 | +#include "qcoreapplication.h" | ||
451 | +#include "qxembedsystemtrayicon_x11_p.h" | ||
452 | niro | 2912 | |
453 | niro | 2917 | -#ifndef QT_NO_SYSTEMTRAYICON |
454 | niro | 2912 | QT_BEGIN_NAMESPACE |
455 | |||
456 | niro | 2917 | -Window QSystemTrayIconSys::sysTrayWindow = XNone; |
457 | -QList<QSystemTrayIconSys *> QSystemTrayIconSys::trayIcons; | ||
458 | -QCoreApplication::EventFilter QSystemTrayIconSys::oldEventFilter = 0; | ||
459 | -Atom QSystemTrayIconSys::sysTraySelection = XNone; | ||
460 | -XVisualInfo QSystemTrayIconSys::sysTrayVisual = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
461 | - | ||
462 | -// Locate the system tray | ||
463 | -Window QSystemTrayIconSys::locateSystemTray() | ||
464 | -{ | ||
465 | - Display *display = QX11Info::display(); | ||
466 | - if (sysTraySelection == XNone) { | ||
467 | - int screen = QX11Info::appScreen(); | ||
468 | - QString net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen); | ||
469 | - sysTraySelection = XInternAtom(display, net_sys_tray.toLatin1(), False); | ||
470 | - } | ||
471 | - | ||
472 | - return XGetSelectionOwner(QX11Info::display(), sysTraySelection); | ||
473 | -} | ||
474 | +Q_GLOBAL_STATIC(QSystemTrayIconSysFactory, qt_guiSystemTrayIconSysFactory) | ||
475 | niro | 2912 | |
476 | niro | 2917 | -XVisualInfo* QSystemTrayIconSys::getSysTrayVisualInfo() |
477 | +QSystemTrayIconSysFactory::QSystemTrayIconSysFactory() | ||
478 | +: pluginFactory(0) | ||
479 | niro | 2912 | { |
480 | niro | 2917 | - Display *display = QX11Info::display(); |
481 | - | ||
482 | - if (!sysTrayVisual.visual) { | ||
483 | - Window win = locateSystemTray(); | ||
484 | - if (win != XNone) { | ||
485 | - Atom actual_type; | ||
486 | - int actual_format; | ||
487 | - ulong nitems, bytes_remaining; | ||
488 | - uchar *data = 0; | ||
489 | - int result = XGetWindowProperty(display, win, ATOM(_NET_SYSTEM_TRAY_VISUAL), 0, 1, | ||
490 | - False, XA_VISUALID, &actual_type, | ||
491 | - &actual_format, &nitems, &bytes_remaining, &data); | ||
492 | - VisualID vid = 0; | ||
493 | - if (result == Success && data && actual_type == XA_VISUALID && actual_format == 32 && | ||
494 | - nitems == 1 && bytes_remaining == 0) | ||
495 | - vid = *(VisualID*)data; | ||
496 | - if (data) | ||
497 | - XFree(data); | ||
498 | - if (vid == 0) | ||
499 | - return 0; | ||
500 | - | ||
501 | - uint mask = VisualIDMask; | ||
502 | - XVisualInfo *vi, rvi; | ||
503 | - int count; | ||
504 | - rvi.visualid = vid; | ||
505 | - vi = XGetVisualInfo(display, mask, &rvi, &count); | ||
506 | - if (vi) { | ||
507 | - sysTrayVisual = vi[0]; | ||
508 | - XFree((char*)vi); | ||
509 | - } | ||
510 | - if (sysTrayVisual.depth != 32) | ||
511 | - memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); | ||
512 | - } | ||
513 | - } | ||
514 | - | ||
515 | - return sysTrayVisual.visual ? &sysTrayVisual : 0; | ||
516 | niro | 2912 | } |
517 | |||
518 | niro | 2917 | -bool QSystemTrayIconSys::sysTrayTracker(void *message, long *result) |
519 | +void QSystemTrayIconSysFactory::loadPluginFactory() | ||
520 | niro | 2912 | { |
521 | niro | 2917 | - bool retval = false; |
522 | - if (QSystemTrayIconSys::oldEventFilter) | ||
523 | - retval = QSystemTrayIconSys::oldEventFilter(message, result); | ||
524 | - | ||
525 | - if (trayIcons.isEmpty()) | ||
526 | - return retval; | ||
527 | - | ||
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 | ||
541 | - } | ||
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(); | ||
552 | - } | ||
553 | - retval = true; | ||
554 | - } | ||
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(); | ||
560 | - } | ||
561 | - } | ||
562 | - | ||
563 | - return retval; | ||
564 | -} | ||
565 | - | ||
566 | -QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *q) | ||
567 | - : QWidget(0, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint), | ||
568 | - q(q), colormap(0) | ||
569 | -{ | ||
570 | - setAttribute(Qt::WA_AlwaysShowToolTips); | ||
571 | - setAttribute(Qt::WA_QuitOnClose, false); | ||
572 | - setAttribute(Qt::WA_NoSystemBackground, true); | ||
573 | - setAttribute(Qt::WA_PaintOnScreen); | ||
574 | - | ||
575 | - static bool eventFilterAdded = false; | ||
576 | - Display *display = QX11Info::display(); | ||
577 | - if (!eventFilterAdded) { | ||
578 | - oldEventFilter = qApp->setEventFilter(sysTrayTracker); | ||
579 | - eventFilterAdded = true; | ||
580 | - Window root = QX11Info::appRootWindow(); | ||
581 | - XWindowAttributes attr; | ||
582 | - XGetWindowAttributes(display, root, &attr); | ||
583 | - if ((attr.your_event_mask & StructureNotifyMask) != StructureNotifyMask) { | ||
584 | - (void) QApplication::desktop(); // lame trick to ensure our event mask is not overridden | ||
585 | - XSelectInput(display, root, attr.your_event_mask | StructureNotifyMask); // for MANAGER selection | ||
586 | - } | ||
587 | + if (pluginFactory) { | ||
588 | + return; | ||
589 | niro | 2912 | } |
590 | niro | 2917 | - if (trayIcons.isEmpty()) { |
591 | - sysTrayWindow = locateSystemTray(); | ||
592 | - if (sysTrayWindow != XNone) | ||
593 | - XSelectInput(display, sysTrayWindow, StructureNotifyMask); // track tray events | ||
594 | +#ifndef QT_NO_LIBRARY | ||
595 | + QFactoryLoader loader(QSystemTrayIconSysFactoryInterface_iid, QLatin1String("/systemtrayicon")); | ||
596 | + pluginFactory = qobject_cast<QSystemTrayIconSysFactoryInterface *>(loader.instance(QLatin1String("default"))); | ||
597 | + if (pluginFactory) { | ||
598 | + // Set parent to ensure factory destructor is called when application | ||
599 | + // is closed | ||
600 | + pluginFactory->setParent(QCoreApplication::instance()); | ||
601 | + connect(pluginFactory, SIGNAL(availableChanged(bool)), SLOT(refreshTrayIconPrivates())); | ||
602 | niro | 2912 | } |
603 | niro | 2917 | - trayIcons.append(this); |
604 | - setMouseTracking(true); | ||
605 | -#ifndef QT_NO_TOOLTIP | ||
606 | - setToolTip(q->toolTip()); | ||
607 | -#endif | ||
608 | - if (sysTrayWindow != XNone) | ||
609 | - addToTray(); | ||
610 | +#endif // QT_NO_LIBRARY | ||
611 | niro | 2912 | } |
612 | |||
613 | niro | 2917 | -QSystemTrayIconSys::~QSystemTrayIconSys() |
614 | +QSystemTrayIconSysFactoryInterface *QSystemTrayIconSysFactory::factory() const | ||
615 | niro | 2912 | { |
616 | niro | 2917 | - 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) { | ||
625 | + const_cast<QSystemTrayIconSysFactory*>(this)->loadPluginFactory(); | ||
626 | niro | 2912 | } |
627 | niro | 2917 | - if (colormap) |
628 | - XFreeColormap(display, colormap); | ||
629 | + if (pluginFactory && pluginFactory->isAvailable()) { | ||
630 | + return pluginFactory; | ||
631 | + } | ||
632 | + static QXEmbedSystemTrayIconSysFactory def; | ||
633 | + return def.isAvailable() ? &def : 0; | ||
634 | niro | 2912 | } |
635 | |||
636 | niro | 2917 | -void QSystemTrayIconSys::addToTray() |
637 | +void QSystemTrayIconSysFactory::refreshTrayIconPrivates() | ||
638 | niro | 2912 | { |
639 | niro | 2917 | - Q_ASSERT(sysTrayWindow != XNone); |
640 | - Display *display = QX11Info::display(); | ||
641 | - | ||
642 | - XVisualInfo *vi = getSysTrayVisualInfo(); | ||
643 | - if (vi && vi->visual) { | ||
644 | - Window root = RootWindow(display, vi->screen); | ||
645 | - Window p = root; | ||
646 | - if (QWidget *pw = parentWidget()) | ||
647 | - p = pw->effectiveWinId(); | ||
648 | - colormap = XCreateColormap(display, root, vi->visual, AllocNone); | ||
649 | - XSetWindowAttributes wsa; | ||
650 | - wsa.background_pixmap = 0; | ||
651 | - wsa.colormap = colormap; | ||
652 | - wsa.background_pixel = 0; | ||
653 | - wsa.border_pixel = 0; | ||
654 | - Window wid = XCreateWindow(display, p, -1, -1, 1, 1, | ||
655 | - 0, vi->depth, InputOutput, vi->visual, | ||
656 | - CWBackPixmap|CWBackPixel|CWBorderPixel|CWColormap, &wsa); | ||
657 | - create(wid); | ||
658 | - } else { | ||
659 | - XSetWindowBackgroundPixmap(display, winId(), ParentRelative); | ||
660 | - } | ||
661 | - | ||
662 | - // GNOME, NET WM Specification | ||
663 | - static Atom netwm_tray_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False); | ||
664 | - long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, static_cast<long>(winId()), 0, 0 }; | ||
665 | - XEvent ev; | ||
666 | - memset(&ev, 0, sizeof(ev)); | ||
667 | - ev.xclient.type = ClientMessage; | ||
668 | - ev.xclient.window = sysTrayWindow; | ||
669 | - ev.xclient.message_type = netwm_tray_atom; | ||
670 | - ev.xclient.format = 32; | ||
671 | - memcpy((char *)&ev.xclient.data, (const char *) l, sizeof(l)); | ||
672 | - XSendEvent(display, sysTrayWindow, False, 0, &ev); | ||
673 | - setMinimumSize(22, 22); // required at least on GNOME | ||
674 | -} | ||
675 | - | ||
676 | -void QSystemTrayIconSys::updateIcon() | ||
677 | -{ | ||
678 | - update(); | ||
679 | -} | ||
680 | - | ||
681 | -void QSystemTrayIconSys::resizeEvent(QResizeEvent *re) | ||
682 | -{ | ||
683 | - QWidget::resizeEvent(re); | ||
684 | - updateIcon(); | ||
685 | -} | ||
686 | - | ||
687 | -void QSystemTrayIconSys::paintEvent(QPaintEvent*) | ||
688 | -{ | ||
689 | - QPainter p(this); | ||
690 | - if (!getSysTrayVisualInfo()) { | ||
691 | - const QRegion oldSystemClip = p.paintEngine()->systemClip(); | ||
692 | - const QRect clearedRect = oldSystemClip.boundingRect(); | ||
693 | - XClearArea(QX11Info::display(), winId(), clearedRect.x(), clearedRect.y(), | ||
694 | - clearedRect.width(), clearedRect.height(), False); | ||
695 | - QPaintEngine *pe = p.paintEngine(); | ||
696 | - pe->setSystemClip(clearedRect); | ||
697 | - q->icon().paint(&p, rect()); | ||
698 | - pe->setSystemClip(oldSystemClip); | ||
699 | - } else { | ||
700 | - p.setCompositionMode(QPainter::CompositionMode_Source); | ||
701 | - p.fillRect(rect(), Qt::transparent); | ||
702 | - p.setCompositionMode(QPainter::CompositionMode_SourceOver); | ||
703 | - q->icon().paint(&p, rect()); | ||
704 | + Q_FOREACH(QSystemTrayIconPrivate *trayIconPrivate, trayIconPrivates) { | ||
705 | + if (trayIconPrivate->sys) { | ||
706 | + delete trayIconPrivate->sys; | ||
707 | + trayIconPrivate->sys = 0; | ||
708 | + } | ||
709 | + // When visible is true, sys is usually not 0 but it can be 0 if the | ||
710 | + // call to install_sys() failed. | ||
711 | + if (trayIconPrivate->visible) { | ||
712 | + trayIconPrivate->install_sys(); | ||
713 | + } | ||
714 | niro | 2912 | } |
715 | } | ||
716 | |||
717 | niro | 2917 | -void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev) |
718 | +void QSystemTrayIconSysFactory::registerSystemTrayIconPrivate(QSystemTrayIconPrivate* trayIconPrivate) | ||
719 | niro | 2912 | { |
720 | niro | 2917 | - QPoint globalPos = ev->globalPos(); |
721 | - if (ev->button() == Qt::RightButton && q->contextMenu()) | ||
722 | - q->contextMenu()->popup(globalPos); | ||
723 | - | ||
724 | - if (QBalloonTip::isBalloonVisible()) { | ||
725 | - emit q->messageClicked(); | ||
726 | - QBalloonTip::hideBalloon(); | ||
727 | - } | ||
728 | - | ||
729 | - if (ev->button() == Qt::LeftButton) | ||
730 | - emit q->activated(QSystemTrayIcon::Trigger); | ||
731 | - else if (ev->button() == Qt::RightButton) | ||
732 | - emit q->activated(QSystemTrayIcon::Context); | ||
733 | - else if (ev->button() == Qt::MidButton) | ||
734 | - emit q->activated(QSystemTrayIcon::MiddleClick); | ||
735 | + trayIconPrivates.insert(trayIconPrivate); | ||
736 | niro | 2912 | } |
737 | |||
738 | niro | 2917 | -void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev) |
739 | +void QSystemTrayIconSysFactory::unregisterSystemTrayIconPrivate(QSystemTrayIconPrivate* trayIconPrivate) | ||
740 | niro | 2912 | { |
741 | niro | 2917 | - if (ev->button() == Qt::LeftButton) |
742 | - emit q->activated(QSystemTrayIcon::DoubleClick); | ||
743 | + trayIconPrivates.remove(trayIconPrivate); | ||
744 | niro | 2912 | } |
745 | |||
746 | niro | 2917 | -#ifndef QT_NO_WHEELEVENT |
747 | -void QSystemTrayIconSys::wheelEvent(QWheelEvent *e) | ||
748 | +QAbstractSystemTrayIconSys *QSystemTrayIconSysFactory::create(QSystemTrayIcon *trayIcon) const | ||
749 | niro | 2912 | { |
750 | niro | 2917 | - QApplication::sendEvent(q, e); |
751 | + QSystemTrayIconSysFactoryInterface *f = factory(); | ||
752 | + if (!f) { | ||
753 | + qWarning("No systemtrayicon available"); | ||
754 | + return 0; | ||
755 | + } | ||
756 | + return f->create(trayIcon); | ||
757 | niro | 2912 | } |
758 | niro | 2917 | -#endif |
759 | niro | 2912 | |
760 | niro | 2917 | -bool QSystemTrayIconSys::event(QEvent *e) |
761 | +bool QSystemTrayIconSysFactory::isAvailable() const | ||
762 | niro | 2912 | { |
763 | niro | 2917 | - if (e->type() == QEvent::ToolTip) { |
764 | - return QApplication::sendEvent(q, e); | ||
765 | - } | ||
766 | - return QWidget::event(e); | ||
767 | + return factory(); | ||
768 | niro | 2912 | } |
769 | |||
770 | niro | 2917 | -bool QSystemTrayIconSys::x11Event(XEvent *event) |
771 | +//////////////////////////////////////////////// | ||
772 | +QSystemTrayIconPrivate::~QSystemTrayIconPrivate() | ||
773 | niro | 2912 | { |
774 | niro | 2917 | - if (event->type == ReparentNotify) |
775 | - show(); | ||
776 | - return QWidget::x11Event(event); | ||
777 | + qt_guiSystemTrayIconSysFactory()->unregisterSystemTrayIconPrivate(this); | ||
778 | + delete sys; | ||
779 | niro | 2912 | } |
780 | |||
781 | niro | 2917 | -//////////////////////////////////////////////////////////////////////////// |
782 | niro | 2912 | void QSystemTrayIconPrivate::install_sys() |
783 | { | ||
784 | Q_Q(QSystemTrayIcon); | ||
785 | niro | 2917 | - if (!sys) |
786 | - sys = new QSystemTrayIconSys(q); | ||
787 | + if (!sys) { | ||
788 | + // Register ourself even if create() fails: our "sys" will get created | ||
789 | + // later by refreshTrayIconPrivates() if a systemtray becomes | ||
790 | + // available. This situation can happen for applications which are | ||
791 | + // started at login time, while the desktop itself is starting up. | ||
792 | + qt_guiSystemTrayIconSysFactory()->registerSystemTrayIconPrivate(this); | ||
793 | + sys = qt_guiSystemTrayIconSysFactory()->create(q); | ||
794 | + if (!sys) { | ||
795 | + return; | ||
796 | + } | ||
797 | + } | ||
798 | + sys->updateVisibility(); | ||
799 | niro | 2912 | } |
800 | |||
801 | QRect QSystemTrayIconPrivate::geometry_sys() const | ||
802 | { | ||
803 | niro | 2917 | - if (!sys) |
804 | - return QRect(); | ||
805 | - return QRect(sys->mapToGlobal(QPoint(0, 0)), sys->size()); | ||
806 | + if (!sys || !visible) | ||
807 | + return QRect(); | ||
808 | + return sys->geometry(); | ||
809 | niro | 2912 | } |
810 | |||
811 | void QSystemTrayIconPrivate::remove_sys() | ||
812 | niro | 2917 | @@ -350,35 +161,35 @@ |
813 | niro | 2912 | if (!sys) |
814 | return; | ||
815 | QBalloonTip::hideBalloon(); | ||
816 | niro | 2917 | - sys->hide(); // this should do the trick, but... |
817 | - delete sys; // wm may resize system tray only for DestroyEvents | ||
818 | - sys = 0; | ||
819 | + sys->updateVisibility(); | ||
820 | niro | 2912 | } |
821 | |||
822 | void QSystemTrayIconPrivate::updateIcon_sys() | ||
823 | { | ||
824 | niro | 2917 | - if (!sys) |
825 | + if (!sys || !visible) | ||
826 | niro | 2912 | return; |
827 | niro | 2917 | sys->updateIcon(); |
828 | niro | 2912 | } |
829 | |||
830 | void QSystemTrayIconPrivate::updateMenu_sys() | ||
831 | { | ||
832 | niro | 2917 | - |
833 | + if (!sys || !visible) | ||
834 | + return; | ||
835 | + sys->updateMenu(); | ||
836 | niro | 2912 | } |
837 | |||
838 | void QSystemTrayIconPrivate::updateToolTip_sys() | ||
839 | { | ||
840 | niro | 2917 | - if (!sys) |
841 | + if (!sys || !visible) | ||
842 | niro | 2912 | return; |
843 | #ifndef QT_NO_TOOLTIP | ||
844 | niro | 2917 | - sys->setToolTip(toolTip); |
845 | + sys->updateToolTip(); | ||
846 | niro | 2912 | #endif |
847 | } | ||
848 | |||
849 | bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() | ||
850 | { | ||
851 | niro | 2917 | - return QSystemTrayIconSys::locateSystemTray() != XNone; |
852 | + return qt_guiSystemTrayIconSysFactory()->isAvailable(); | ||
853 | niro | 2912 | } |
854 | |||
855 | bool QSystemTrayIconPrivate::supportsMessages_sys() | ||
856 | niro | 2917 | @@ -389,12 +200,9 @@ |
857 | void QSystemTrayIconPrivate::showMessage_sys(const QString &message, const QString &title, | ||
858 | niro | 2912 | QSystemTrayIcon::MessageIcon icon, int msecs) |
859 | { | ||
860 | niro | 2917 | - if (!sys) |
861 | + if (!sys || !visible) | ||
862 | niro | 2912 | return; |
863 | niro | 2917 | - QPoint g = sys->mapToGlobal(QPoint(0, 0)); |
864 | - QBalloonTip::showBalloon(icon, message, title, sys->q, | ||
865 | - QPoint(g.x() + sys->width()/2, g.y() + sys->height()/2), | ||
866 | - msecs); | ||
867 | + sys->showMessage(message, title, icon, msecs); | ||
868 | niro | 2912 | } |
869 | |||
870 | QT_END_NAMESPACE | ||
871 | niro | 2917 | --- /dev/null |
872 | +++ b/src/gui/util/qxembedsystemtrayicon_x11.cpp | ||
873 | @@ -0,0 +1,469 @@ | ||
874 | +/**************************************************************************** | ||
875 | +** | ||
876 | +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | ||
877 | +** All rights reserved. | ||
878 | +** Contact: Nokia Corporation (qt-info@nokia.com) | ||
879 | +** | ||
880 | +** This file is part of the QtGui module of the Qt Toolkit. | ||
881 | +** | ||
882 | +** $QT_BEGIN_LICENSE:LGPL$ | ||
883 | +** GNU Lesser General Public License Usage | ||
884 | +** This file may be used under the terms of the GNU Lesser General Public | ||
885 | +** License version 2.1 as published by the Free Software Foundation and | ||
886 | +** appearing in the file LICENSE.LGPL included in the packaging of this | ||
887 | +** file. Please review the following information to ensure the GNU Lesser | ||
888 | +** General Public License version 2.1 requirements will be met: | ||
889 | +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
890 | +** | ||
891 | +** In addition, as a special exception, Nokia gives you certain additional | ||
892 | +** rights. These rights are described in the Nokia Qt LGPL Exception | ||
893 | +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
894 | +** | ||
895 | +** GNU General Public License Usage | ||
896 | +** Alternatively, this file may be used under the terms of the GNU General | ||
897 | +** Public License version 3.0 as published by the Free Software Foundation | ||
898 | +** and appearing in the file LICENSE.GPL included in the packaging of this | ||
899 | +** file. Please review the following information to ensure the GNU General | ||
900 | +** Public License version 3.0 requirements will be met: | ||
901 | +** http://www.gnu.org/copyleft/gpl.html. | ||
902 | +** | ||
903 | +** Other Usage | ||
904 | +** Alternatively, this file may be used in accordance with the terms and | ||
905 | +** conditions contained in a signed written agreement between you and Nokia. | ||
906 | +** | ||
907 | +** | ||
908 | +** | ||
909 | +** | ||
910 | +** | ||
911 | +** $QT_END_LICENSE$ | ||
912 | +** | ||
913 | +****************************************************************************/ | ||
914 | +#include "qxembedsystemtrayicon_x11_p.h" | ||
915 | + | ||
916 | +#ifndef QT_NO_SYSTEMTRAYICON | ||
917 | + | ||
918 | +#include "private/qt_x11_p.h" | ||
919 | +#include "qapplication.h" | ||
920 | +#include "qevent.h" | ||
921 | +#include "qlist.h" | ||
922 | +#include "qmenu.h" | ||
923 | +#include "qpainter.h" | ||
924 | +#include "qpaintengine.h" | ||
925 | +#include "qsystemtrayicon_p.h" | ||
926 | +#include "qx11info_x11.h" | ||
927 | + | ||
928 | +QT_BEGIN_INCLUDE_NAMESPACE | ||
929 | +#include <QtCore/qcoreapplication.h> | ||
930 | +#include <X11/Xlib.h> | ||
931 | +#include <X11/Xatom.h> | ||
932 | +#include <X11/Xutil.h> | ||
933 | +QT_END_INCLUDE_NAMESPACE | ||
934 | + | ||
935 | +QT_BEGIN_NAMESPACE | ||
936 | + | ||
937 | +class QSystemTrayIconWidget : public QWidget | ||
938 | +{ | ||
939 | +public: | ||
940 | + QSystemTrayIconWidget(QSystemTrayIcon *q, QXEmbedSystemTrayIconSys *s); | ||
941 | + ~QSystemTrayIconWidget(); | ||
942 | + | ||
943 | + static Window locateSystemTray(); | ||
944 | + | ||
945 | +protected: | ||
946 | + void paintEvent(QPaintEvent *pe); | ||
947 | + void resizeEvent(QResizeEvent *re); | ||
948 | + bool x11Event(XEvent *event); | ||
949 | + void mousePressEvent(QMouseEvent *event); | ||
950 | + void mouseDoubleClickEvent(QMouseEvent *event); | ||
951 | +#ifndef QT_NO_WHEELEVENT | ||
952 | + void wheelEvent(QWheelEvent *event); | ||
953 | +#endif | ||
954 | + bool event(QEvent *e); | ||
955 | + | ||
956 | +private: | ||
957 | + enum { | ||
958 | + SYSTEM_TRAY_REQUEST_DOCK = 0, | ||
959 | + SYSTEM_TRAY_BEGIN_MESSAGE = 1, | ||
960 | + SYSTEM_TRAY_CANCEL_MESSAGE =2 | ||
961 | + }; | ||
962 | + | ||
963 | + void addToTray(); | ||
964 | + static XVisualInfo* getSysTrayVisualInfo(); | ||
965 | + | ||
966 | + static Window sysTrayWindow; | ||
967 | + static QList<QSystemTrayIconWidget *> trayIcons; | ||
968 | + static QCoreApplication::EventFilter oldEventFilter; | ||
969 | + static bool sysTrayTracker(void *message, long *result); | ||
970 | + static Atom sysTraySelection; | ||
971 | + static XVisualInfo sysTrayVisual; | ||
972 | + | ||
973 | + QSystemTrayIcon *q; | ||
974 | + QXEmbedSystemTrayIconSys *sys; | ||
975 | + Colormap colormap; | ||
976 | +}; | ||
977 | + | ||
978 | +Window QSystemTrayIconWidget::sysTrayWindow = XNone; | ||
979 | +QList<QSystemTrayIconWidget *> QSystemTrayIconWidget::trayIcons; | ||
980 | +QCoreApplication::EventFilter QSystemTrayIconWidget::oldEventFilter = 0; | ||
981 | +Atom QSystemTrayIconWidget::sysTraySelection = XNone; | ||
982 | +XVisualInfo QSystemTrayIconWidget::sysTrayVisual = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
983 | + | ||
984 | +QSystemTrayIconWidget::QSystemTrayIconWidget(QSystemTrayIcon* q, QXEmbedSystemTrayIconSys* sys) | ||
985 | +: QWidget(0, Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint) | ||
986 | +, q(q) | ||
987 | +, sys(sys) | ||
988 | +, colormap(0) | ||
989 | +{ | ||
990 | + setAttribute(Qt::WA_AlwaysShowToolTips); | ||
991 | + setAttribute(Qt::WA_QuitOnClose, false); | ||
992 | + setAttribute(Qt::WA_NoSystemBackground, true); | ||
993 | + setAttribute(Qt::WA_PaintOnScreen); | ||
994 | + setMouseTracking(true); | ||
995 | +#ifndef QT_NO_TOOLTIP | ||
996 | + setToolTip(q->toolTip()); | ||
997 | +#endif | ||
998 | + | ||
999 | + static bool eventFilterAdded = false; | ||
1000 | + Display *display = QX11Info::display(); | ||
1001 | + if (!eventFilterAdded) { | ||
1002 | + oldEventFilter = qApp->setEventFilter(sysTrayTracker); | ||
1003 | + eventFilterAdded = true; | ||
1004 | + Window root = QX11Info::appRootWindow(); | ||
1005 | + XWindowAttributes attr; | ||
1006 | + XGetWindowAttributes(display, root, &attr); | ||
1007 | + if ((attr.your_event_mask & StructureNotifyMask) != StructureNotifyMask) { | ||
1008 | + (void) QApplication::desktop(); // lame trick to ensure our event mask is not overridden | ||
1009 | + XSelectInput(display, root, attr.your_event_mask | StructureNotifyMask); // for MANAGER selection | ||
1010 | + } | ||
1011 | + } | ||
1012 | + if (trayIcons.isEmpty()) { | ||
1013 | + sysTrayWindow = locateSystemTray(); | ||
1014 | + if (sysTrayWindow != XNone) | ||
1015 | + XSelectInput(display, sysTrayWindow, StructureNotifyMask); // track tray events | ||
1016 | + } | ||
1017 | + trayIcons.append(this); | ||
1018 | + if (sysTrayWindow != XNone) | ||
1019 | + addToTray(); | ||
1020 | +} | ||
1021 | + | ||
1022 | +QSystemTrayIconWidget::~QSystemTrayIconWidget() | ||
1023 | +{ | ||
1024 | + trayIcons.removeAt(trayIcons.indexOf(this)); | ||
1025 | + Display *display = QX11Info::display(); | ||
1026 | + if (trayIcons.isEmpty()) { | ||
1027 | + if (sysTrayWindow == XNone) | ||
1028 | + return; | ||
1029 | + if (display) | ||
1030 | + XSelectInput(display, sysTrayWindow, 0); // stop tracking the tray | ||
1031 | + sysTrayWindow = XNone; | ||
1032 | + } | ||
1033 | + if (colormap) | ||
1034 | + XFreeColormap(display, colormap); | ||
1035 | +} | ||
1036 | + | ||
1037 | +void QSystemTrayIconWidget::resizeEvent(QResizeEvent *re) | ||
1038 | +{ | ||
1039 | + QWidget::resizeEvent(re); | ||
1040 | + update(); | ||
1041 | +} | ||
1042 | + | ||
1043 | +void QSystemTrayIconWidget::paintEvent(QPaintEvent*) | ||
1044 | +{ | ||
1045 | + QPainter p(this); | ||
1046 | + if (!getSysTrayVisualInfo()) { | ||
1047 | + const QRegion oldSystemClip = p.paintEngine()->systemClip(); | ||
1048 | + const QRect clearedRect = oldSystemClip.boundingRect(); | ||
1049 | + XClearArea(QX11Info::display(), winId(), clearedRect.x(), clearedRect.y(), | ||
1050 | + clearedRect.width(), clearedRect.height(), False); | ||
1051 | + QPaintEngine *pe = p.paintEngine(); | ||
1052 | + pe->setSystemClip(clearedRect); | ||
1053 | + q->icon().paint(&p, rect()); | ||
1054 | + pe->setSystemClip(oldSystemClip); | ||
1055 | + } else { | ||
1056 | + p.setCompositionMode(QPainter::CompositionMode_Source); | ||
1057 | + p.fillRect(rect(), Qt::transparent); | ||
1058 | + p.setCompositionMode(QPainter::CompositionMode_SourceOver); | ||
1059 | + q->icon().paint(&p, rect()); | ||
1060 | + } | ||
1061 | +} | ||
1062 | + | ||
1063 | +void QSystemTrayIconWidget::mousePressEvent(QMouseEvent *ev) | ||
1064 | +{ | ||
1065 | + QPoint globalPos = ev->globalPos(); | ||
1066 | + if (ev->button() == Qt::RightButton && q->contextMenu()) | ||
1067 | + q->contextMenu()->popup(globalPos); | ||
1068 | + | ||
1069 | + if (QBalloonTip::isBalloonVisible()) { | ||
1070 | + QMetaObject::invokeMethod(q, "messageClicked"); | ||
1071 | + QBalloonTip::hideBalloon(); | ||
1072 | + } | ||
1073 | + | ||
1074 | + if (ev->button() == Qt::LeftButton) | ||
1075 | + qtsystray_sendActivated(q, QSystemTrayIcon::Trigger); | ||
1076 | + else if (ev->button() == Qt::RightButton) | ||
1077 | + qtsystray_sendActivated(q, QSystemTrayIcon::Context); | ||
1078 | + else if (ev->button() == Qt::MidButton) | ||
1079 | + qtsystray_sendActivated(q, QSystemTrayIcon::MiddleClick); | ||
1080 | +} | ||
1081 | + | ||
1082 | +void QSystemTrayIconWidget::mouseDoubleClickEvent(QMouseEvent *ev) | ||
1083 | +{ | ||
1084 | + if (ev->button() == Qt::LeftButton) | ||
1085 | + qtsystray_sendActivated(q, QSystemTrayIcon::DoubleClick); | ||
1086 | +} | ||
1087 | + | ||
1088 | +#ifndef QT_NO_WHEELEVENT | ||
1089 | +void QSystemTrayIconWidget::wheelEvent(QWheelEvent *e) | ||
1090 | +{ | ||
1091 | + sys->sendWheelEventToTrayIcon(e->delta(), e->orientation()); | ||
1092 | +} | ||
1093 | +#endif | ||
1094 | + | ||
1095 | +bool QSystemTrayIconWidget::event(QEvent *e) | ||
1096 | +{ | ||
1097 | + if (e->type() == QEvent::ToolTip) { | ||
1098 | + sys->sendToolTipEventToTrayIcon(); | ||
1099 | + } | ||
1100 | + return QWidget::event(e); | ||
1101 | +} | ||
1102 | + | ||
1103 | +bool QSystemTrayIconWidget::x11Event(XEvent *event) | ||
1104 | +{ | ||
1105 | + if (event->type == ReparentNotify) | ||
1106 | + show(); | ||
1107 | + return QWidget::x11Event(event); | ||
1108 | +} | ||
1109 | + | ||
1110 | +// Locate the system tray | ||
1111 | +Window QSystemTrayIconWidget::locateSystemTray() | ||
1112 | +{ | ||
1113 | + Display *display = QX11Info::display(); | ||
1114 | + if (sysTraySelection == XNone) { | ||
1115 | + int screen = QX11Info::appScreen(); | ||
1116 | + QString net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen); | ||
1117 | + sysTraySelection = XInternAtom(display, net_sys_tray.toLatin1(), False); | ||
1118 | + } | ||
1119 | + | ||
1120 | + return XGetSelectionOwner(QX11Info::display(), sysTraySelection); | ||
1121 | +} | ||
1122 | + | ||
1123 | +XVisualInfo* QSystemTrayIconWidget::getSysTrayVisualInfo() | ||
1124 | +{ | ||
1125 | + Display *display = QX11Info::display(); | ||
1126 | + | ||
1127 | + if (!sysTrayVisual.visual) { | ||
1128 | + Window win = locateSystemTray(); | ||
1129 | + if (win != XNone) { | ||
1130 | + Atom actual_type; | ||
1131 | + int actual_format; | ||
1132 | + ulong nitems, bytes_remaining; | ||
1133 | + uchar *data = 0; | ||
1134 | + int result = XGetWindowProperty(display, win, ATOM(_NET_SYSTEM_TRAY_VISUAL), 0, 1, | ||
1135 | + False, XA_VISUALID, &actual_type, | ||
1136 | + &actual_format, &nitems, &bytes_remaining, &data); | ||
1137 | + VisualID vid = 0; | ||
1138 | + if (result == Success && data && actual_type == XA_VISUALID && actual_format == 32 && | ||
1139 | + nitems == 1 && bytes_remaining == 0) | ||
1140 | + vid = *(VisualID*)data; | ||
1141 | + if (data) | ||
1142 | + XFree(data); | ||
1143 | + if (vid == 0) | ||
1144 | + return 0; | ||
1145 | + | ||
1146 | + uint mask = VisualIDMask; | ||
1147 | + XVisualInfo *vi, rvi; | ||
1148 | + int count; | ||
1149 | + rvi.visualid = vid; | ||
1150 | + vi = XGetVisualInfo(display, mask, &rvi, &count); | ||
1151 | + if (vi) { | ||
1152 | + sysTrayVisual = vi[0]; | ||
1153 | + XFree((char*)vi); | ||
1154 | + } | ||
1155 | + if (sysTrayVisual.depth != 32) | ||
1156 | + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); | ||
1157 | + } | ||
1158 | + } | ||
1159 | + | ||
1160 | + return sysTrayVisual.visual ? &sysTrayVisual : 0; | ||
1161 | +} | ||
1162 | + | ||
1163 | +bool QSystemTrayIconWidget::sysTrayTracker(void *message, long *result) | ||
1164 | +{ | ||
1165 | + bool retval = false; | ||
1166 | + if (QSystemTrayIconWidget::oldEventFilter) | ||
1167 | + retval = QSystemTrayIconWidget::oldEventFilter(message, result); | ||
1168 | + | ||
1169 | + if (trayIcons.isEmpty()) | ||
1170 | + return retval; | ||
1171 | + | ||
1172 | + Display *display = QX11Info::display(); | ||
1173 | + XEvent *ev = (XEvent *)message; | ||
1174 | + if (ev->type == DestroyNotify && ev->xany.window == sysTrayWindow) { | ||
1175 | + sysTrayWindow = locateSystemTray(); | ||
1176 | + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); | ||
1177 | + for (int i = 0; i < trayIcons.count(); i++) { | ||
1178 | + if (sysTrayWindow == XNone) { | ||
1179 | + QBalloonTip::hideBalloon(); | ||
1180 | + trayIcons[i]->hide(); // still no luck | ||
1181 | + trayIcons[i]->destroy(); | ||
1182 | + trayIcons[i]->create(); | ||
1183 | + } else | ||
1184 | + trayIcons[i]->addToTray(); // add it to the new tray | ||
1185 | + } | ||
1186 | + retval = true; | ||
1187 | + } else if (ev->type == ClientMessage && sysTrayWindow == XNone) { | ||
1188 | + static Atom manager_atom = XInternAtom(display, "MANAGER", False); | ||
1189 | + XClientMessageEvent *cm = (XClientMessageEvent *)message; | ||
1190 | + if ((cm->message_type == manager_atom) && ((Atom)cm->data.l[1] == sysTraySelection)) { | ||
1191 | + sysTrayWindow = cm->data.l[2]; | ||
1192 | + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); | ||
1193 | + XSelectInput(display, sysTrayWindow, StructureNotifyMask); | ||
1194 | + for (int i = 0; i < trayIcons.count(); i++) { | ||
1195 | + trayIcons[i]->addToTray(); | ||
1196 | + } | ||
1197 | + retval = true; | ||
1198 | + } | ||
1199 | + } else if (ev->type == PropertyNotify && ev->xproperty.atom == ATOM(_NET_SYSTEM_TRAY_VISUAL) && | ||
1200 | + ev->xproperty.window == sysTrayWindow) { | ||
1201 | + memset(&sysTrayVisual, 0, sizeof(sysTrayVisual)); | ||
1202 | + for (int i = 0; i < trayIcons.count(); i++) { | ||
1203 | + trayIcons[i]->addToTray(); | ||
1204 | + } | ||
1205 | + } | ||
1206 | + | ||
1207 | + return retval; | ||
1208 | +} | ||
1209 | + | ||
1210 | +void QSystemTrayIconWidget::addToTray() | ||
1211 | +{ | ||
1212 | + Q_ASSERT(sysTrayWindow != XNone); | ||
1213 | + Display *display = QX11Info::display(); | ||
1214 | + | ||
1215 | + XVisualInfo *vi = getSysTrayVisualInfo(); | ||
1216 | + if (vi && vi->visual) { | ||
1217 | + Window root = RootWindow(display, vi->screen); | ||
1218 | + Window p = root; | ||
1219 | + if (QWidget *pw = parentWidget()) | ||
1220 | + p = pw->effectiveWinId(); | ||
1221 | + colormap = XCreateColormap(display, root, vi->visual, AllocNone); | ||
1222 | + XSetWindowAttributes wsa; | ||
1223 | + wsa.background_pixmap = 0; | ||
1224 | + wsa.colormap = colormap; | ||
1225 | + wsa.background_pixel = 0; | ||
1226 | + wsa.border_pixel = 0; | ||
1227 | + Window wid = XCreateWindow(display, p, -1, -1, 1, 1, | ||
1228 | + 0, vi->depth, InputOutput, vi->visual, | ||
1229 | + CWBackPixmap|CWBackPixel|CWBorderPixel|CWColormap, &wsa); | ||
1230 | + create(wid); | ||
1231 | + } else { | ||
1232 | + XSetWindowBackgroundPixmap(display, winId(), ParentRelative); | ||
1233 | + } | ||
1234 | + | ||
1235 | + // GNOME, NET WM Specification | ||
1236 | + static Atom netwm_tray_atom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False); | ||
1237 | + long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, static_cast<long>(winId()), 0, 0 }; | ||
1238 | + XEvent ev; | ||
1239 | + memset(&ev, 0, sizeof(ev)); | ||
1240 | + ev.xclient.type = ClientMessage; | ||
1241 | + ev.xclient.window = sysTrayWindow; | ||
1242 | + ev.xclient.message_type = netwm_tray_atom; | ||
1243 | + ev.xclient.format = 32; | ||
1244 | + memcpy((char *)&ev.xclient.data, (const char *) l, sizeof(l)); | ||
1245 | + XSendEvent(display, sysTrayWindow, False, 0, &ev); | ||
1246 | + setMinimumSize(22, 22); // required at least on GNOME | ||
1247 | +} | ||
1248 | + | ||
1249 | +//////////////////////////////////////////////////////////////////////////// | ||
1250 | +QXEmbedSystemTrayIconSys::QXEmbedSystemTrayIconSys(QSystemTrayIcon *q) | ||
1251 | +: QAbstractSystemTrayIconSys(q) | ||
1252 | +, widget(0) | ||
1253 | +{ | ||
1254 | +} | ||
1255 | + | ||
1256 | +QXEmbedSystemTrayIconSys::~QXEmbedSystemTrayIconSys() | ||
1257 | +{ | ||
1258 | + delete widget; | ||
1259 | +} | ||
1260 | + | ||
1261 | +QRect QXEmbedSystemTrayIconSys::geometry() const | ||
1262 | +{ | ||
1263 | + if (!widget) | ||
1264 | + return QRect(); | ||
1265 | + return QRect(widget->mapToGlobal(QPoint(0, 0)), widget->size()); | ||
1266 | +} | ||
1267 | + | ||
1268 | +void QXEmbedSystemTrayIconSys::updateIcon() | ||
1269 | +{ | ||
1270 | + if (!widget) | ||
1271 | + return; | ||
1272 | + widget->update(); | ||
1273 | +} | ||
1274 | + | ||
1275 | +void QXEmbedSystemTrayIconSys::updateToolTip() | ||
1276 | +{ | ||
1277 | + if (!widget) | ||
1278 | + return; | ||
1279 | + widget->setToolTip(trayIcon->toolTip()); | ||
1280 | +} | ||
1281 | + | ||
1282 | +void QXEmbedSystemTrayIconSys::showMessage(const QString &message, const QString &title, | ||
1283 | + QSystemTrayIcon::MessageIcon icon, int msecs) | ||
1284 | +{ | ||
1285 | + if (!widget) | ||
1286 | + return; | ||
1287 | + QPoint point = geometry().center(); | ||
1288 | + QBalloonTip::showBalloon(icon, message, title, trayIcon, point, msecs); | ||
1289 | +} | ||
1290 | + | ||
1291 | +void QXEmbedSystemTrayIconSys::updateVisibility() | ||
1292 | +{ | ||
1293 | + bool visible = trayIcon->isVisible(); | ||
1294 | + if (visible && !widget) | ||
1295 | + widget = new QSystemTrayIconWidget(trayIcon, this); | ||
1296 | + else if (!visible && widget) { | ||
1297 | + delete widget; | ||
1298 | + widget = 0; | ||
1299 | + } | ||
1300 | +} | ||
1301 | + | ||
1302 | +void QXEmbedSystemTrayIconSys::sendToolTipEventToTrayIcon() | ||
1303 | +{ | ||
1304 | +#ifndef QT_NO_TOOLTIP | ||
1305 | + // Pass the event through QSystemTrayIcon so that it gets a chance to | ||
1306 | + // update the tooltip, then asks widget to show the tooltip | ||
1307 | + Q_ASSERT(widget); | ||
1308 | + QPoint globalPos = QCursor::pos(); | ||
1309 | + QPoint pos = widget->mapFromGlobal(globalPos); | ||
1310 | + QHelpEvent event(QEvent::ToolTip, pos, globalPos); | ||
1311 | + QApplication::sendEvent(trayIcon, &event); | ||
1312 | +#endif | ||
1313 | +} | ||
1314 | + | ||
1315 | +void QXEmbedSystemTrayIconSys::sendWheelEventToTrayIcon(int delta, Qt::Orientation orientation) | ||
1316 | +{ | ||
1317 | +#ifndef QT_NO_WHEELEVENT | ||
1318 | + Q_ASSERT(widget); | ||
1319 | + QPoint globalPos = QCursor::pos(); | ||
1320 | + QPoint pos = widget->mapFromGlobal(globalPos); | ||
1321 | + QWheelEvent event(pos, globalPos, delta, Qt::NoButton, Qt::NoModifier, orientation); | ||
1322 | + QApplication::sendEvent(trayIcon, &event); | ||
1323 | +#endif | ||
1324 | +} | ||
1325 | + | ||
1326 | +void QXEmbedSystemTrayIconSys::updateMenu() | ||
1327 | +{ | ||
1328 | +} | ||
1329 | + | ||
1330 | +///////////////////////////////////////////////////////////// | ||
1331 | +QAbstractSystemTrayIconSys * QXEmbedSystemTrayIconSysFactory::create(QSystemTrayIcon *icon) | ||
1332 | +{ | ||
1333 | + return new QXEmbedSystemTrayIconSys(icon); | ||
1334 | +} | ||
1335 | + | ||
1336 | +bool QXEmbedSystemTrayIconSysFactory::isAvailable() const | ||
1337 | +{ | ||
1338 | + return QSystemTrayIconWidget::locateSystemTray() != XNone; | ||
1339 | +} | ||
1340 | + | ||
1341 | +QT_END_NAMESPACE | ||
1342 | +#endif //QT_NO_SYSTEMTRAYICON | ||
1343 | --- /dev/null | ||
1344 | +++ b/src/gui/util/qxembedsystemtrayicon_x11_p.h | ||
1345 | @@ -0,0 +1,104 @@ | ||
1346 | +/**************************************************************************** | ||
1347 | +** | ||
1348 | +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | ||
1349 | +** All rights reserved. | ||
1350 | +** Contact: Nokia Corporation (qt-info@nokia.com) | ||
1351 | +** | ||
1352 | +** This file is part of the QtGui module of the Qt Toolkit. | ||
1353 | +** | ||
1354 | +** $QT_BEGIN_LICENSE:LGPL$ | ||
1355 | +** GNU Lesser General Public License Usage | ||
1356 | +** This file may be used under the terms of the GNU Lesser General Public | ||
1357 | +** License version 2.1 as published by the Free Software Foundation and | ||
1358 | +** appearing in the file LICENSE.LGPL included in the packaging of this | ||
1359 | +** file. Please review the following information to ensure the GNU Lesser | ||
1360 | +** General Public License version 2.1 requirements will be met: | ||
1361 | +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
1362 | +** | ||
1363 | +** In addition, as a special exception, Nokia gives you certain additional | ||
1364 | +** rights. These rights are described in the Nokia Qt LGPL Exception | ||
1365 | +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
1366 | +** | ||
1367 | +** GNU General Public License Usage | ||
1368 | +** Alternatively, this file may be used under the terms of the GNU General | ||
1369 | +** Public License version 3.0 as published by the Free Software Foundation | ||
1370 | +** and appearing in the file LICENSE.GPL included in the packaging of this | ||
1371 | +** file. Please review the following information to ensure the GNU General | ||
1372 | +** Public License version 3.0 requirements will be met: | ||
1373 | +** http://www.gnu.org/copyleft/gpl.html. | ||
1374 | +** | ||
1375 | +** Other Usage | ||
1376 | +** Alternatively, this file may be used in accordance with the terms and | ||
1377 | +** conditions contained in a signed written agreement between you and Nokia. | ||
1378 | +** | ||
1379 | +** | ||
1380 | +** | ||
1381 | +** | ||
1382 | +** | ||
1383 | +** $QT_END_LICENSE$ | ||
1384 | +** | ||
1385 | +****************************************************************************/ | ||
1386 | + | ||
1387 | +#ifndef QXEMBEDSYSTEMTRAYICON_X11_P_H | ||
1388 | +#define QXEMBEDSYSTEMTRAYICON_X11_P_H | ||
1389 | + | ||
1390 | +// | ||
1391 | +// W A R N I N G | ||
1392 | +// ------------- | ||
1393 | +// | ||
1394 | +// This file is not part of the Qt API. It exists for the convenience | ||
1395 | +// of a number of Qt sources files. This header file may change from | ||
1396 | +// version to version without notice, or even be removed. | ||
1397 | +// | ||
1398 | +// We mean it. | ||
1399 | +// | ||
1400 | + | ||
1401 | +#ifndef QT_NO_SYSTEMTRAYICON | ||
1402 | + | ||
1403 | +#include "qabstractsystemtrayiconsys_p.h" | ||
1404 | + | ||
1405 | +QT_BEGIN_NAMESPACE | ||
1406 | + | ||
1407 | +class QSystemTrayIconWidget; | ||
1408 | + | ||
1409 | +class QXEmbedSystemTrayIconSys : public QAbstractSystemTrayIconSys | ||
1410 | +{ | ||
1411 | +public: | ||
1412 | + QXEmbedSystemTrayIconSys(QSystemTrayIcon *); | ||
1413 | + ~QXEmbedSystemTrayIconSys(); | ||
1414 | + | ||
1415 | + QRect geometry() const; | ||
1416 | + | ||
1417 | + void updateVisibility(); | ||
1418 | + | ||
1419 | + void updateIcon(); | ||
1420 | + | ||
1421 | + void updateToolTip(); | ||
1422 | + | ||
1423 | + void updateMenu(); | ||
1424 | + | ||
1425 | + void showMessage(const QString &message, const QString &title, | ||
1426 | + QSystemTrayIcon::MessageIcon icon, int msecs); | ||
1427 | + | ||
1428 | +private: | ||
1429 | + friend class QSystemTrayIconWidget; | ||
1430 | + QSystemTrayIconWidget *widget; | ||
1431 | + | ||
1432 | + void sendToolTipEventToTrayIcon(); | ||
1433 | + | ||
1434 | + void sendWheelEventToTrayIcon(int delta, Qt::Orientation orientation); | ||
1435 | +}; | ||
1436 | + | ||
1437 | +struct QXEmbedSystemTrayIconSysFactory : public QSystemTrayIconSysFactoryInterface | ||
1438 | +{ | ||
1439 | + QAbstractSystemTrayIconSys * create(QSystemTrayIcon *trayIcon); | ||
1440 | + bool isAvailable() const; | ||
1441 | +}; | ||
1442 | + | ||
1443 | + | ||
1444 | +QT_END_NAMESPACE | ||
1445 | + | ||
1446 | +#endif // QT_NO_SYSTEMTRAYICON | ||
1447 | + | ||
1448 | +#endif // QXEMBEDSYSTEMTRAYICON_X11_P_H | ||
1449 | + | ||
1450 | --- a/src/gui/util/util.pri | ||
1451 | +++ b/src/gui/util/util.pri | ||
1452 | @@ -29,8 +29,13 @@ | ||
1453 | niro | 2912 | } |
1454 | |||
1455 | unix:x11 { | ||
1456 | niro | 2917 | + HEADERS += \ |
1457 | + util/qabstractsystemtrayiconsys_p.h \ | ||
1458 | + util/qxembedsystemtrayicon_x11_p.h | ||
1459 | niro | 2912 | SOURCES += \ |
1460 | niro | 2917 | - util/qsystemtrayicon_x11.cpp |
1461 | + util/qabstractsystemtrayiconsys.cpp \ | ||
1462 | + util/qsystemtrayicon_x11.cpp \ | ||
1463 | + util/qxembedsystemtrayicon_x11.cpp | ||
1464 | niro | 2912 | } |
1465 | |||
1466 | embedded|qpa { |