qsystemtrayicon_x11.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/widgets/util/qsystemtrayicon_x11.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtWidgets module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qlabel.h"-
41#include "qpainter.h"-
42#include "qpixmap.h"-
43#include "qbitmap.h"-
44#include "qevent.h"-
45#include "qapplication.h"-
46#include "qlist.h"-
47#include "qmenu.h"-
48#include "qtimer.h"-
49#include "qsystemtrayicon_p.h"-
50#include "qpaintengine.h"-
51#include <qwindow.h>-
52#include <qguiapplication.h>-
53#include <qscreen.h>-
54#include <qbackingstore.h>-
55#include <qpa/qplatformnativeinterface.h>-
56#include <qpa/qplatformsystemtrayicon.h>-
57#include <qpa/qplatformtheme.h>-
58#include <private/qguiapplication_p.h>-
59#include <qdebug.h>-
60-
61#include <QtPlatformHeaders/qxcbwindowfunctions.h>-
62#include <QtPlatformHeaders/qxcbintegrationfunctions.h>-
63#ifndef QT_NO_SYSTEMTRAYICON-
64QT_BEGIN_NAMESPACE-
65-
66static inline unsigned long locateSystemTray()-
67{-
68 return (unsigned long)QGuiApplication::platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("traywindow"), QGuiApplication::primaryScreen());
never executed: return (unsigned long)QGuiApplication::platformNativeInterface()->nativeResourceForScreen(([]() -> QByteArray { enum { Size = sizeof("traywindow") - 1 }; static const QStaticByteArrayData<Size> qbytearray_literal = { { { { -1 } }, Size, 0, 0, sizeof(QByteArrayData) }, "traywindow" }; QByteArrayDataPtr holder = { qbytearray_literal.data_ptr() }; const QByteArray ba(holder); return ba; }()), QGuiApplication::primaryScreen());
never executed: return ba;
0
69}-
70-
71// System tray widget. Could be replaced by a QWindow with-
72// a backing store if it did not need tooltip handling.-
73class QSystemTrayIconSys : public QWidget-
74{-
75 Q_OBJECT-
76public:-
77 explicit QSystemTrayIconSys(QSystemTrayIcon *q);-
78-
79 inline void updateIcon() { update(); }
never executed: end of block
0
80 inline QSystemTrayIcon *systemTrayIcon() const { return q; }
never executed: return q;
0
81-
82 QRect globalGeometry() const;-
83-
84protected:-
85 virtual void mousePressEvent(QMouseEvent *ev) Q_DECL_OVERRIDE;-
86 virtual void mouseDoubleClickEvent(QMouseEvent *ev) Q_DECL_OVERRIDE;-
87 virtual bool event(QEvent *) Q_DECL_OVERRIDE;-
88 virtual void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;-
89 virtual void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;-
90 virtual void moveEvent(QMoveEvent *) Q_DECL_OVERRIDE;-
91-
92private slots:-
93 void systemTrayWindowChanged(QScreen *screen);-
94-
95private:-
96 bool addToTray();-
97-
98 QSystemTrayIcon *q;-
99 QPixmap background;-
100};-
101-
102QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)-
103 : QWidget(0, Qt::Window | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint)-
104 , q(qIn)-
105{-
106 setObjectName(QStringLiteral("QSystemTrayIconSys"));
never executed: return qstring_literal_temp;
0
107 setToolTip(q->toolTip());-
108 setAttribute(Qt::WA_AlwaysShowToolTips, true);-
109 setAttribute(Qt::WA_QuitOnClose, false);-
110 const QSize size(22, 22); // Gnome, standard size-
111 setGeometry(QRect(QPoint(0, 0), size));-
112 setMinimumSize(size);-
113-
114 // We need two different behaviors depending on whether the X11 visual for the system tray-
115 // (a) exists and (b) supports an alpha channel, i.e. is 32 bits.-
116 // If we have a visual that has an alpha channel, we can paint this widget with a transparent-
117 // background and it will work.-
118 // However, if there's no alpha channel visual, in order for transparent tray icons to work,-
119 // we do not have a transparent background on the widget, but set the BackPixmap property of our-
120 // window to ParentRelative (so that it inherits the background of its X11 parent window), call-
121 // xcb_clear_region before painting (so that the inherited background is visible) and then grab-
122 // the just-drawn background from the X11 server.-
123 bool hasAlphaChannel = QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannel();-
124 setAttribute(Qt::WA_TranslucentBackground, hasAlphaChannel);-
125 if (!hasAlphaChannel) {
!hasAlphaChannelDescription
TRUEnever evaluated
FALSEnever evaluated
0
126 createWinId();-
127 QXcbWindowFunctions::setParentRelativeBackPixmap(windowHandle());-
128-
129 // XXX: This is actually required, but breaks things ("QWidget::paintEngine: Should no-
130 // longer be called"). Why is this needed? When the widget is drawn, we use tricks to grab-
131 // the tray icon's background from the server. If the tray icon isn't visible (because-
132 // another window is on top of it), the trick fails and instead uses the content of that-
133 // other window as the background.-
134 // setAttribute(Qt::WA_PaintOnScreen);-
135 }
never executed: end of block
0
136-
137 addToTray();-
138}
never executed: end of block
0
139-
140bool QSystemTrayIconSys::addToTray()-
141{-
142 if (!locateSystemTray())
!locateSystemTray()Description
TRUEnever evaluated
FALSEnever evaluated
0
143 return false;
never executed: return false;
0
144-
145 createWinId();-
146 setMouseTracking(true);-
147-
148 if (!QXcbWindowFunctions::requestSystemTrayWindowDock(windowHandle()))
!QXcbWindowFun...indowHandle())Description
TRUEnever evaluated
FALSEnever evaluated
0
149 return false;
never executed: return false;
0
150-
151 if (!background.isNull())
!background.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
152 background = QPixmap();
never executed: background = QPixmap();
0
153 show();-
154 return true;
never executed: return true;
0
155}-
156-
157void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)-
158{-
159 if (locateSystemTray()) {
locateSystemTray()Description
TRUEnever evaluated
FALSEnever evaluated
0
160 addToTray();-
161 } else {
never executed: end of block
0
162 QBalloonTip::hideBalloon();-
163 hide(); // still no luck-
164 destroy();-
165 }
never executed: end of block
0
166}-
167-
168QRect QSystemTrayIconSys::globalGeometry() const-
169{-
170 return QXcbWindowFunctions::systemTrayWindowGlobalGeometry(windowHandle());
never executed: return QXcbWindowFunctions::systemTrayWindowGlobalGeometry(windowHandle());
0
171}-
172-
173void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)-
174{-
175 QPoint globalPos = ev->globalPos();-
176#ifndef QT_NO_CONTEXTMENU-
177 if (ev->button() == Qt::RightButton && q->contextMenu())
ev->button() =...t::RightButtonDescription
TRUEnever evaluated
FALSEnever evaluated
q->contextMenu()Description
TRUEnever evaluated
FALSEnever evaluated
0
178 q->contextMenu()->popup(globalPos);
never executed: q->contextMenu()->popup(globalPos);
0
179#else-
180 Q_UNUSED(globalPos)-
181#endif // QT_NO_CONTEXTMENU-
182-
183 if (QBalloonTip::isBalloonVisible()) {
QBalloonTip::i...lloonVisible()Description
TRUEnever evaluated
FALSEnever evaluated
0
184 emit q->messageClicked();-
185 QBalloonTip::hideBalloon();-
186 }
never executed: end of block
0
187-
188 if (ev->button() == Qt::LeftButton)
ev->button() == Qt::LeftButtonDescription
TRUEnever evaluated
FALSEnever evaluated
0
189 emit q->activated(QSystemTrayIcon::Trigger);
never executed: q->activated(QSystemTrayIcon::Trigger);
0
190 else if (ev->button() == Qt::RightButton)
ev->button() =...t::RightButtonDescription
TRUEnever evaluated
FALSEnever evaluated
0
191 emit q->activated(QSystemTrayIcon::Context);
never executed: q->activated(QSystemTrayIcon::Context);
0
192 else if (ev->button() == Qt::MidButton)
ev->button() == Qt::MidButtonDescription
TRUEnever evaluated
FALSEnever evaluated
0
193 emit q->activated(QSystemTrayIcon::MiddleClick);
never executed: q->activated(QSystemTrayIcon::MiddleClick);
0
194}
never executed: end of block
0
195-
196void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev)-
197{-
198 if (ev->button() == Qt::LeftButton)
ev->button() == Qt::LeftButtonDescription
TRUEnever evaluated
FALSEnever evaluated
0
199 emit q->activated(QSystemTrayIcon::DoubleClick);
never executed: q->activated(QSystemTrayIcon::DoubleClick);
0
200}
never executed: end of block
0
201-
202bool QSystemTrayIconSys::event(QEvent *e)-
203{-
204 switch (e->type()) {-
205 case QEvent::ToolTip:
never executed: case QEvent::ToolTip:
0
206 QApplication::sendEvent(q, e);-
207 break;
never executed: break;
0
208#ifndef QT_NO_WHEELEVENT-
209 case QEvent::Wheel:
never executed: case QEvent::Wheel:
0
210 return QApplication::sendEvent(q, e);
never executed: return QApplication::sendEvent(q, e);
0
211#endif-
212 default:
never executed: default:
0
213 break;
never executed: break;
0
214 }-
215 return QWidget::event(e);
never executed: return QWidget::event(e);
0
216}-
217-
218void QSystemTrayIconSys::paintEvent(QPaintEvent *)-
219{-
220 const QRect rect(QPoint(0, 0), geometry().size());-
221 QPainter painter(this);-
222-
223 // If we have Qt::WA_TranslucentBackground set, during widget creation-
224 // we detected the systray visual supported an alpha channel-
225 if (testAttribute(Qt::WA_TranslucentBackground)) {
testAttribute(...entBackground)Description
TRUEnever evaluated
FALSEnever evaluated
0
226 painter.setCompositionMode(QPainter::CompositionMode_Source);-
227 painter.fillRect(rect, Qt::transparent);-
228 } else {
never executed: end of block
0
229 // clearRegion() was called on XEMBED_EMBEDDED_NOTIFY, so we hope that got done by now.-
230 // Grab the tray background pixmap, before rendering the icon for the first time.-
231 if (background.isNull()) {
background.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
232 background = QGuiApplication::primaryScreen()->grabWindow(winId(),-
233 0, 0, rect.size().width(), rect.size().height());-
234 }
never executed: end of block
0
235 // Then paint over the icon area with the background before compositing the icon on top.-
236 painter.drawPixmap(QPoint(0, 0), background);-
237 }
never executed: end of block
0
238 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);-
239 q->icon().paint(&painter, rect);-
240}
never executed: end of block
0
241-
242void QSystemTrayIconSys::moveEvent(QMoveEvent *event)-
243{-
244 QWidget::moveEvent(event);-
245 if (QBalloonTip::isBalloonVisible())
QBalloonTip::i...lloonVisible()Description
TRUEnever evaluated
FALSEnever evaluated
0
246 QBalloonTip::updateBalloonPosition(globalGeometry().center());
never executed: QBalloonTip::updateBalloonPosition(globalGeometry().center());
0
247}
never executed: end of block
0
248-
249void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)-
250{-
251 update();-
252 QWidget::resizeEvent(event);-
253 if (QBalloonTip::isBalloonVisible())
QBalloonTip::i...lloonVisible()Description
TRUEnever evaluated
FALSEnever evaluated
0
254 QBalloonTip::updateBalloonPosition(globalGeometry().center());
never executed: QBalloonTip::updateBalloonPosition(globalGeometry().center());
0
255}
never executed: end of block
0
256////////////////////////////////////////////////////////////////////////////-
257-
258QSystemTrayIconPrivate::QSystemTrayIconPrivate()-
259 : sys(0),-
260 qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),-
261 visible(false)-
262{-
263}
never executed: end of block
0
264-
265QSystemTrayIconPrivate::~QSystemTrayIconPrivate()-
266{-
267 delete qpa_sys;-
268}
never executed: end of block
0
269-
270void QSystemTrayIconPrivate::install_sys()-
271{-
272 if (qpa_sys) {
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
273 install_sys_qpa();-
274 return;
never executed: return;
0
275 }-
276 Q_Q(QSystemTrayIcon);-
277 if (!sys && locateSystemTray()) {
!sysDescription
TRUEnever evaluated
FALSEnever evaluated
locateSystemTray()Description
TRUEnever evaluated
FALSEnever evaluated
0
278 sys = new QSystemTrayIconSys(q);-
279 QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),-
280 sys, SLOT(systemTrayWindowChanged(QScreen*)));-
281 }
never executed: end of block
0
282}
never executed: end of block
0
283-
284QRect QSystemTrayIconPrivate::geometry_sys() const-
285{-
286 if (qpa_sys)
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
287 return geometry_sys_qpa();
never executed: return geometry_sys_qpa();
0
288 if (!sys)
!sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
289 return QRect();
never executed: return QRect();
0
290 return sys->globalGeometry();
never executed: return sys->globalGeometry();
0
291}-
292-
293void QSystemTrayIconPrivate::remove_sys()-
294{-
295 if (qpa_sys) {
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
296 remove_sys_qpa();-
297 return;
never executed: return;
0
298 }-
299 if (!sys)
!sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
300 return;
never executed: return;
0
301 QBalloonTip::hideBalloon();-
302 sys->hide(); // this should do the trick, but...-
303 delete sys; // wm may resize system tray only for DestroyEvents-
304 sys = 0;-
305}
never executed: end of block
0
306-
307void QSystemTrayIconPrivate::updateIcon_sys()-
308{-
309 if (qpa_sys) {
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
310 updateIcon_sys_qpa();-
311 return;
never executed: return;
0
312 }-
313 if (sys)
sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
314 sys->updateIcon();
never executed: sys->updateIcon();
0
315}
never executed: end of block
0
316-
317void QSystemTrayIconPrivate::updateMenu_sys()-
318{-
319 if (qpa_sys)
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
320 updateMenu_sys_qpa();
never executed: updateMenu_sys_qpa();
0
321}
never executed: end of block
0
322-
323void QSystemTrayIconPrivate::updateToolTip_sys()-
324{-
325 if (qpa_sys) {
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
326 updateToolTip_sys_qpa();-
327 return;
never executed: return;
0
328 }-
329 if (!sys)
!sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
330 return;
never executed: return;
0
331#ifndef QT_NO_TOOLTIP-
332 sys->setToolTip(toolTip);-
333#endif-
334}
never executed: end of block
0
335-
336bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()-
337{-
338 QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());-
339 if (sys && sys->isSystemTrayAvailable())
sysDescription
TRUEnever evaluated
FALSEnever evaluated
sys->isSystemTrayAvailable()Description
TRUEnever evaluated
FALSEnever evaluated
0
340 return true;
never executed: return true;
0
341-
342 // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior-
343 const QString platform = QGuiApplication::platformName();-
344 if (platform.compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0)
platform.compa...ensitive) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
345 return locateSystemTray();
never executed: return locateSystemTray();
0
346 return false;
never executed: return false;
0
347}-
348-
349bool QSystemTrayIconPrivate::supportsMessages_sys()-
350{-
351 QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());-
352 if (sys)
sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
353 return sys->supportsMessages();
never executed: return sys->supportsMessages();
0
354-
355 // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior-
356 return true;
never executed: return true;
0
357}-
358-
359void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,-
360 QSystemTrayIcon::MessageIcon icon, int msecs)-
361{-
362 if (qpa_sys) {
qpa_sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
363 showMessage_sys_qpa(title, message, icon, msecs);-
364 return;
never executed: return;
0
365 }-
366 if (!sys)
!sysDescription
TRUEnever evaluated
FALSEnever evaluated
0
367 return;
never executed: return;
0
368 QBalloonTip::showBalloon(icon, title, message, sys->systemTrayIcon(),-
369 sys->globalGeometry().center(),-
370 msecs);-
371}
never executed: end of block
0
372-
373QT_END_NAMESPACE-
374-
375#include "qsystemtrayicon_x11.moc"-
376-
377#endif //QT_NO_SYSTEMTRAYICON-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9