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#ifndef QT_NO_CONTEXTMENU
90 if (ev->button() == Qt::RightButton && q->contextMenu()) {
91 const QPoint globalPos = ev->globalPosition().toPoint();
92 q->contextMenu()->popup(globalPos);
93 }
94#endif // QT_NO_CONTEXTMENU
95
97 emit q->messageClicked();
99 }
100
101 if (ev->button() == Qt::LeftButton)
102 emit q->activated(QSystemTrayIcon::Trigger);
103 else if (ev->button() == Qt::RightButton)
104 emit q->activated(QSystemTrayIcon::Context);
105 else if (ev->button() == Qt::MiddleButton)
106 emit q->activated(QSystemTrayIcon::MiddleClick);
107}
108
110{
111 if (ev->button() == Qt::LeftButton)
112 emit q->activated(QSystemTrayIcon::DoubleClick);
113}
114
115bool QSystemTrayIconSys::event(QEvent *e)
116{
117 switch (e->type()) {
118 case QEvent::ToolTip:
119 QCoreApplication::sendEvent(q, e);
120 break;
121#if QT_CONFIG(wheelevent)
122 case QEvent::Wheel:
123 return QCoreApplication::sendEvent(q, e);
124#endif
125 default:
126 break;
127 }
128 return QWidget::event(e);
129}
130
131void QSystemTrayIconSys::paintEvent(QPaintEvent *)
132{
133 const QRect rect(QPoint(0, 0), geometry().size());
134 QPainter painter(this);
135
136 q->icon().paint(&painter, rect);
137}
138
139void QSystemTrayIconSys::moveEvent(QMoveEvent *event)
140{
141 QWidget::moveEvent(event);
143 QBalloonTip::updateBalloonPosition(globalGeometry().center());
144}
145
146void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)
147{
148 update();
149 QWidget::resizeEvent(event);
151 QBalloonTip::updateBalloonPosition(globalGeometry().center());
152}
153////////////////////////////////////////////////////////////////////////////
154
156{
158public:
162 {
163 // This code uses string-based syntax because we want to connect to a signal
164 // which is defined in XCB plugin - QXcbNativeInterface::systemTrayWindowChanged().
167 }
168
169private slots:
171 {
172 auto icon = static_cast<QSystemTrayIconPrivate *>(QObjectPrivate::get(mTrayIcon));
173 icon->destroyIcon();
174 if (icon->visible && locateSystemTray()) {
176 icon->sys->show();
177 }
178 }
179
180private:
181 QSystemTrayIcon *mTrayIcon = nullptr;
182};
183////////////////////////////////////////////////////////////////////////////
184
185QSystemTrayIconPrivate::QSystemTrayIconPrivate()
186 : sys(nullptr),
187 qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
188 visible(false),
189 trayWatcher(nullptr)
190{
191}
192
194{
195 delete qpa_sys;
196}
197
199{
200 Q_Q(QSystemTrayIcon);
201
202 if (qpa_sys) {
203 install_sys_qpa();
204 return;
205 }
206
207 if (!sys) {
208 if (!trayWatcher)
209 trayWatcher = new QSystemTrayWatcher(q);
210
211 if (locateSystemTray()) {
212 sys = new QSystemTrayIconSys(q);
213 sys->show();
214 }
215 }
216}
217
219{
220 if (qpa_sys)
221 return qpa_sys->geometry();
222 if (!sys)
223 return QRect();
224 return sys->globalGeometry();
225}
226
228{
229 if (qpa_sys) {
230 remove_sys_qpa();
231 return;
232 }
233
235}
236
238{
239 if (!sys)
240 return;
242 sys->hide();
243 delete sys;
244 sys = nullptr;
245}
246
247
249{
250 if (qpa_sys) {
251 qpa_sys->updateIcon(icon);
252 return;
253 }
254 if (sys)
256}
257
259{
260#if QT_CONFIG(menu)
261 if (qpa_sys && menu) {
262 addPlatformMenu(menu);
263 qpa_sys->updateMenu(menu->platformMenu());
264 }
265#endif
266}
267
269{
270 if (qpa_sys) {
271 qpa_sys->updateToolTip(toolTip);
272 return;
273 }
274 if (!sys)
275 return;
276#if QT_CONFIG(tooltip)
277 sys->setToolTip(toolTip);
278#endif
279}
280
282{
283 QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
284 if (sys && sys->isSystemTrayAvailable())
285 return true;
286
287 // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
288 const QString platform = QGuiApplication::platformName();
289 if (platform.compare("xcb"_L1, Qt::CaseInsensitive) == 0)
290 return locateSystemTray();
291 return false;
292}
293
295{
296 QScopedPointer<QPlatformSystemTrayIcon> sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon());
297 if (sys)
298 return sys->supportsMessages();
299
300 // no QPlatformSystemTrayIcon so fall back to default xcb platform behavior
301 return true;
302}
303
304void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,
305 const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs)
306{
307 if (qpa_sys) {
308 qpa_sys->showMessage(title, message, icon,
309 static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs);
310 return;
311 }
312 if (!sys)
313 return;
314 QBalloonTip::showBalloon(icon, title, message, sys->systemTrayIcon(),
315 sys->globalGeometry().center(),
316 msecs);
317}
318
319QT_END_NAMESPACE
320
321#include "qsystemtrayicon_x11.moc"
322
323#endif //QT_NO_SYSTEMTRAYICON
static void hideBalloon()
static bool isBalloonVisible()
static void updateBalloonPosition(const QPoint &pos)
friend class QPainter
\inmodule QtCore\reentrant
Definition qpoint.h:30
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...
Combined button and popup list for selecting options.
#define qGuiApp
static unsigned long locateSystemTray()