Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsystemtrayicon_x11.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6#if QT_CONFIG(label)
7#include "qlabel.h"
8#endif
9#include "qpainter.h"
10#include "qpixmap.h"
11#include "qbitmap.h"
12#include "qevent.h"
13#include "qapplication.h"
14#include "qlist.h"
15#if QT_CONFIG(menu)
16#include "qmenu.h"
17#endif
19#include "qpaintengine.h"
20#include <qwindow.h>
21#include <qguiapplication.h>
22#include <qscreen.h>
23#include <qbackingstore.h>
24#include <qpa/qplatformnativeinterface.h>
25#include <qpa/qplatformsystemtrayicon.h>
26#include <qpa/qplatformtheme.h>
27#include <private/qguiapplication_p.h>
28#include <qdebug.h>
29
30#ifndef QT_NO_SYSTEMTRAYICON
32
33using namespace Qt::StringLiterals;
34
35static inline unsigned long locateSystemTray()
36{
37 return (unsigned long)QGuiApplication::platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("traywindow"), QGuiApplication::primaryScreen());
38}
39
40// System tray widget. Could be replaced by a QWindow with
41// a backing store if it did not need tooltip handling.
43{
45public:
47
48 inline void updateIcon() { update(); }
49 inline QSystemTrayIcon *systemTrayIcon() const { return q; }
50
51 QRect globalGeometry() const;
52
53protected:
54 virtual void mousePressEvent(QMouseEvent *ev) override;
55 virtual void mouseDoubleClickEvent(QMouseEvent *ev) override;
56 virtual bool event(QEvent *) override;
57 virtual void paintEvent(QPaintEvent *) override;
58 virtual void resizeEvent(QResizeEvent *) override;
59 virtual void moveEvent(QMoveEvent *) override;
60
61private:
62 QSystemTrayIcon *q;
63};
64
65QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
66 : QWidget(nullptr, Qt::Window | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint)
67 , q(qIn)
68{
69 setObjectName(QStringLiteral("QSystemTrayIconSys"));
70#if QT_CONFIG(tooltip)
71 setToolTip(q->toolTip());
72#endif
73 setAttribute(Qt::WA_AlwaysShowToolTips, true);
74 setAttribute(Qt::WA_QuitOnClose, false);
75 const QSize size(22, 22); // Gnome, standard size
76 setGeometry(QRect(QPoint(0, 0), size));
77 setMinimumSize(size);
78 setAttribute(Qt::WA_TranslucentBackground);
79 setMouseTracking(true);
80}
81
83{
84 return QRect(mapToGlobal(QPoint(0, 0)), size());
85}
86
87void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)
88{
89 QPoint globalPos = ev->globalPosition().toPoint();
90#ifndef QT_NO_CONTEXTMENU
91 if (ev->button() == Qt::RightButton && q->contextMenu())
92 q->contextMenu()->popup(globalPos);
93#else
94 Q_UNUSED(globalPos);
95#endif // QT_NO_CONTEXTMENU
96
98 emit q->messageClicked();
100 }
101
102 if (ev->button() == Qt::LeftButton)
103 emit q->activated(QSystemTrayIcon::Trigger);
104 else if (ev->button() == Qt::RightButton)
105 emit q->activated(QSystemTrayIcon::Context);
106 else if (ev->button() == Qt::MiddleButton)
107 emit q->activated(QSystemTrayIcon::MiddleClick);
108}
109
111{
112 if (ev->button() == Qt::LeftButton)
113 emit q->activated(QSystemTrayIcon::DoubleClick);
114}
115
116bool QSystemTrayIconSys::event(QEvent *e)
117{
118 switch (e->type()) {
119 case QEvent::ToolTip:
120 QCoreApplication::sendEvent(q, e);
121 break;
122#if QT_CONFIG(wheelevent)
123 case QEvent::Wheel:
124 return QCoreApplication::sendEvent(q, e);
125#endif
126 default:
127 break;
128 }
129 return QWidget::event(e);
130}
131
132void QSystemTrayIconSys::paintEvent(QPaintEvent *)
133{
134 const QRect rect(QPoint(0, 0), geometry().size());
135 QPainter painter(this);
136
137 q->icon().paint(&painter, rect);
138}
139
140void QSystemTrayIconSys::moveEvent(QMoveEvent *event)
141{
142 QWidget::moveEvent(event);
143 if (QBalloonTip::isBalloonVisible())
144 QBalloonTip::updateBalloonPosition(globalGeometry().center());
145}
146
147void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)
148{
149 update();
150 QWidget::resizeEvent(event);
151 if (QBalloonTip::isBalloonVisible())
152 QBalloonTip::updateBalloonPosition(globalGeometry().center());
153}
154////////////////////////////////////////////////////////////////////////////
155
157{
159public:
163 {
164 // This code uses string-based syntax because we want to connect to a signal
165 // which is defined in XCB plugin - QXcbNativeInterface::systemTrayWindowChanged().
168 }
169
170private slots:
172 {
173 auto icon = static_cast<QSystemTrayIconPrivate *>(QObjectPrivate::get(mTrayIcon));
174 icon->destroyIcon();
175 if (icon->visible && locateSystemTray()) {
177 icon->sys->show();
178 }
179 }
180
181private:
182 QSystemTrayIcon *mTrayIcon = nullptr;
183};
184////////////////////////////////////////////////////////////////////////////
185
186QSystemTrayIconPrivate::QSystemTrayIconPrivate()
187 : sys(nullptr),
188 qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
189 visible(false),
190 trayWatcher(nullptr)
191{
192}
193
195{
196 delete qpa_sys;
197}
198
200{
201 Q_Q(QSystemTrayIcon);
202
203 if (qpa_sys) {
204 install_sys_qpa();
205 return;
206 }
207
208 if (!sys) {
209 if (!trayWatcher)
210 trayWatcher = new QSystemTrayWatcher(q);
211
212 if (locateSystemTray()) {
213 sys = new QSystemTrayIconSys(q);
214 sys->show();
215 }
216 }
217}
218
220{
221 if (qpa_sys)
222 return qpa_sys->geometry();
223 if (!sys)
224 return QRect();
225 return sys->globalGeometry();
226}
227
229{
230 if (qpa_sys) {
231 remove_sys_qpa();
232 return;
233 }
234
236}
237
239{
240 if (!sys)
241 return;
243 sys->hide();
244 delete sys;
245 sys = nullptr;
246}
247
248
250{
251 if (qpa_sys) {
252 qpa_sys->updateIcon(icon);
253 return;
254 }
255 if (sys)
257}
258
260{
261#if QT_CONFIG(menu)
262 if (qpa_sys && menu) {
263 addPlatformMenu(menu);
264 qpa_sys->updateMenu(menu->platformMenu());
265 }
266#endif
267}
268
270{
271 if (qpa_sys) {
272 qpa_sys->updateToolTip(toolTip);
273 return;
274 }
275 if (!sys)
276 return;
277#if QT_CONFIG(tooltip)
278 sys->setToolTip(toolTip);
279#endif
280}
281
283{
284 QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
285 if (sys && sys->isSystemTrayAvailable())
286 return true;
287
288 // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
289 const QString platform = QGuiApplication::platformName();
290 if (platform.compare("xcb"_L1, Qt::CaseInsensitive) == 0)
291 return locateSystemTray();
292 return false;
293}
294
296{
297 QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
298 if (sys)
299 return sys->supportsMessages();
300
301 // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
302 return true;
303}
304
305void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,
306 const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs)
307{
308 if (qpa_sys) {
309 qpa_sys->showMessage(title, message, icon,
310 static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs);
311 return;
312 }
313 if (!sys)
314 return;
315 QBalloonTip::showBalloon(icon, title, message, sys->systemTrayIcon(),
316 sys->globalGeometry().center(),
317 msecs);
318}
319
320QT_END_NAMESPACE
321
322#include "qsystemtrayicon_x11.moc"
323
324#endif //QT_NO_SYSTEMTRAYICON
static void hideBalloon()
static bool isBalloonVisible()
friend class QPainter
\inmodule QtCore\reentrant
Definition qpoint.h:29
QSystemTrayIconSys * sys
static bool isSystemTrayAvailable_sys()
QSystemTrayWatcher * trayWatcher
QPlatformSystemTrayIcon * qpa_sys
QSystemTrayIcon * systemTrayIcon() const
virtual void moveEvent(QMoveEvent *) override
This event handler can be reimplemented in a subclass to receive widget move events which are passed ...
virtual bool event(QEvent *) override
This virtual function receives events to an object and should return true if the event e was recogniz...
virtual void mouseDoubleClickEvent(QMouseEvent *ev) override
This event handler, for event event, can be reimplemented in a subclass to receive mouse double click...
virtual void paintEvent(QPaintEvent *) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
virtual void resizeEvent(QResizeEvent *) override
This event handler can be reimplemented in a subclass to receive widget resize events which are passe...
virtual void mousePressEvent(QMouseEvent *ev) override
This event handler, for event event, can be reimplemented in a subclass to receive mouse press events...
#define qGuiApp
static unsigned long locateSystemTray()