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
5#if QT_CONFIG(label)
6#include "qlabel.h"
7#endif
8#include "qpainter.h"
9#include "qpixmap.h"
10#include "qbitmap.h"
11#include "qevent.h"
12#include "qapplication.h"
13#include "qlist.h"
14#if QT_CONFIG(menu)
15#include "qmenu.h"
16#endif
18#include "qpaintengine.h"
19#include <qwindow.h>
20#include <qguiapplication.h>
21#include <qscreen.h>
22#include <qbackingstore.h>
23#include <qpa/qplatformnativeinterface.h>
24#include <qpa/qplatformsystemtrayicon.h>
25#include <qpa/qplatformtheme.h>
26#include <private/qguiapplication_p.h>
27#include <qdebug.h>
28
29#ifndef QT_NO_SYSTEMTRAYICON
31
32using namespace Qt::StringLiterals;
33
34static inline unsigned long locateSystemTray()
35{
36 return (unsigned long)QGuiApplication::platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("traywindow"), QGuiApplication::primaryScreen());
37}
38
39// System tray widget. Could be replaced by a QWindow with
40// a backing store if it did not need tooltip handling.
42{
44public:
46
47 inline void updateIcon() { update(); }
48 inline QSystemTrayIcon *systemTrayIcon() const { return q; }
49
50 QRect globalGeometry() const;
51
52protected:
53 virtual void mousePressEvent(QMouseEvent *ev) override;
54 virtual void mouseDoubleClickEvent(QMouseEvent *ev) override;
55 virtual bool event(QEvent *) override;
56 virtual void paintEvent(QPaintEvent *) override;
57 virtual void resizeEvent(QResizeEvent *) override;
58 virtual void moveEvent(QMoveEvent *) override;
59
60private:
61 QSystemTrayIcon *q;
62};
63
64QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
65 : QWidget(nullptr, Qt::Window | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint)
66 , q(qIn)
67{
68 setObjectName(QStringLiteral("QSystemTrayIconSys"));
69#if QT_CONFIG(tooltip)
70 setToolTip(q->toolTip());
71#endif
72 setAttribute(Qt::WA_AlwaysShowToolTips, true);
73 setAttribute(Qt::WA_QuitOnClose, false);
74 const QSize size(22, 22); // Gnome, standard size
75 setGeometry(QRect(QPoint(0, 0), size));
76 setMinimumSize(size);
77 setAttribute(Qt::WA_TranslucentBackground);
78 setMouseTracking(true);
79}
80
82{
83 return QRect(mapToGlobal(QPoint(0, 0)), size());
84}
85
86void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)
87{
88 QPoint globalPos = ev->globalPosition().toPoint();
89#ifndef QT_NO_CONTEXTMENU
90 if (ev->button() == Qt::RightButton && q->contextMenu())
91 q->contextMenu()->popup(globalPos);
92#else
93 Q_UNUSED(globalPos);
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);
142 if (QBalloonTip::isBalloonVisible())
143 QBalloonTip::updateBalloonPosition(globalGeometry().center());
144}
145
146void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)
147{
148 update();
149 QWidget::resizeEvent(event);
150 if (QBalloonTip::isBalloonVisible())
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()
friend class QPainter
\inmodule QtCore\reentrant
Definition qpoint.h:28
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()