Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qwaylandquickshellsurfaceitem.cpp
Go to the documentation of this file.
1
// Copyright (C) 2017 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qwaylandquickshellsurfaceitem.h"
6
#
include
"qwaylandquickshellsurfaceitem_p.h"
7
8
#
include
<
QtWaylandCompositor
/
QWaylandShellSurface
>
9
#
include
<
QGuiApplication
>
10
11
QT_BEGIN_NAMESPACE
12
13
void
QWaylandQuickShellSurfaceItemPrivate::setShellSurface(QWaylandShellSurface *shellSurface)
14
{
15
Q_Q(QWaylandQuickShellSurfaceItem);
16
17
if
(m_shellSurface) {
18
QObject::disconnect(m_shellSurface, &QObject::destroyed, q,
nullptr
);
19
QObject::disconnect(m_shellSurface, &QWaylandShellSurface::modalChanged, q,
nullptr
);
20
}
21
22
m_shellSurface = shellSurface;
23
24
if
(m_shellIntegration) {
25
q->removeEventFilter(m_shellIntegration);
26
delete
m_shellIntegration;
27
m_shellIntegration =
nullptr
;
28
}
29
30
if
(m_shellSurface) {
31
m_shellIntegration = m_shellSurface->createIntegration(q);
32
q->installEventFilter(m_shellIntegration);
33
34
QObject::connect(m_shellSurface, &QObject::destroyed,
35
q, [
this
]() {
36
setShellSurface(
nullptr
);
37
emit q_func()->shellSurfaceChanged();
38
});
39
QObject::connect(m_shellSurface, &QWaylandShellSurface::modalChanged,
40
q, [
this
]() {
41
if
(m_shellSurface && m_shellSurface->isModal())
42
raise();
43
});
44
}
45
}
46
47
QWaylandQuickShellSurfaceItem *QWaylandQuickShellSurfaceItemPrivate::maybeCreateAutoPopup(QWaylandShellSurface* shellSurface)
48
{
49
if
(!m_autoCreatePopupItems)
50
return
nullptr
;
51
52
Q_Q(QWaylandQuickShellSurfaceItem);
53
auto
*popupItem =
new
QWaylandQuickShellSurfaceItem(q);
54
popupItem->setShellSurface(shellSurface);
55
popupItem->setAutoCreatePopupItems(
true
);
56
QObject::connect(popupItem, &QWaylandQuickShellSurfaceItem::surfaceDestroyed,
57
popupItem, &QObject::deleteLater);
58
return
popupItem;
59
}
60
61
/*!
62
* \qmltype ShellSurfaceItem
63
* \nativetype QWaylandQuickShellSurfaceItem
64
* \inherits WaylandQuickItem
65
* \inqmlmodule QtWayland.Compositor
66
* \since 5.8
67
* \brief A Qt Quick item type for displaying and interacting with a ShellSurface.
68
*
69
* This type is used to render \c xdg_shell, \c ivi_application, \c wl_shell or \c qt_shell
70
* surfaces as part of a Qt Quick scene.
71
*
72
* \sa WaylandQuickItem, XdgSurface, IviSurface, QtShellSurface, WlShellSurface
73
*/
74
75
/*!
76
* \class QWaylandQuickShellSurfaceItem
77
* \inmodule QtWaylandCompositor
78
* \since 5.8
79
* \brief The QWaylandQuickShellSurfaceItem class provides a Qt Quick item that represents a QWaylandShellSurface.
80
*
81
* This type is used to render \c xdg_shell, \c ivi_application, \c wl_shell or \c qt_shell
82
* surfaces as part of a Qt Quick scene.
83
*
84
* \sa QWaylandQuickItem, QWaylandXdgSurface, QWaylandIviSurface, QWaylandWlShellSurface
85
*/
86
87
/*!
88
* Constructs a QWaylandQuickWlShellSurfaceItem with the given \a parent.
89
*/
90
QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QQuickItem *parent)
91
: QWaylandQuickItem(*
new
QWaylandQuickShellSurfaceItemPrivate(), parent)
92
{
93
}
94
95
QWaylandQuickShellSurfaceItem::~QWaylandQuickShellSurfaceItem()
96
{
97
Q_D(QWaylandQuickShellSurfaceItem);
98
99
d->setShellSurface(
nullptr
);
100
}
101
102
/*!
103
* \internal
104
*/
105
QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent)
106
: QWaylandQuickItem(dd, parent)
107
{
108
}
109
110
/*!
111
* \qmlproperty ShellSurface QtWayland.Compositor::ShellSurfaceItem::shellSurface
112
*
113
* This property holds the ShellSurface rendered by this ShellSurfaceItem.
114
* It may either be an XdgSurfaceV5, WlShellSurface or IviSurface depending on which shell protocol
115
* is in use.
116
*/
117
118
/*!
119
* \property QWaylandQuickShellSurfaceItem::shellSurface
120
*
121
* This property holds the QWaylandShellSurface rendered by this QWaylandQuickShellSurfaceItem.
122
* It may either be a QWaylandXdgSurfaceV5, QWaylandWlShellSurface or QWaylandIviSurface depending
123
* on which shell protocol is in use.
124
*/
125
QWaylandShellSurface *QWaylandQuickShellSurfaceItem::shellSurface()
const
126
{
127
Q_D(
const
QWaylandQuickShellSurfaceItem);
128
return
d->m_shellSurface;
129
}
130
131
void
QWaylandQuickShellSurfaceItem::setShellSurface(QWaylandShellSurface *shellSurface)
132
{
133
Q_D(QWaylandQuickShellSurfaceItem);
134
if
(d->m_shellSurface == shellSurface)
135
return
;
136
137
d->setShellSurface(shellSurface);
138
139
emit shellSurfaceChanged();
140
}
141
142
/*!
143
* \qmlproperty Item QtWayland.Compositor::ShellSurfaceItem::moveItem
144
*
145
* This property holds the move item for this ShellSurfaceItem. This is the item that will be moved
146
* when the clients request the ShellSurface to be moved, maximized, resized etc. This property is
147
* useful when implementing server-side decorations.
148
*/
149
150
/*!
151
* \property QWaylandQuickShellSurfaceItem::moveItem
152
*
153
* This property holds the move item for this QWaylandQuickShellSurfaceItem. This is the item that
154
* will be moved when the clients request the QWaylandShellSurface to be moved, maximized, resized
155
* etc. This property is useful when implementing server-side decorations.
156
*/
157
QQuickItem *QWaylandQuickShellSurfaceItem::moveItem()
const
158
{
159
Q_D(
const
QWaylandQuickShellSurfaceItem);
160
return
d->m_moveItem ? d->m_moveItem :
const_cast
<QWaylandQuickShellSurfaceItem *>(
this
);
161
}
162
163
void
QWaylandQuickShellSurfaceItem::setMoveItem(QQuickItem *moveItem)
164
{
165
Q_D(QWaylandQuickShellSurfaceItem);
166
moveItem = moveItem ? moveItem :
this
;
167
if
(
this
->moveItem() == moveItem)
168
return
;
169
d->m_moveItem = moveItem;
170
moveItemChanged();
171
}
172
173
/*!
174
* \qmlproperty bool QtWayland.Compositor::ShellSurfaceItem::autoCreatePopupItems
175
* \default true
176
*
177
* This property holds whether ShellSurfaceItems for popups parented to the shell
178
* surface managed by this item should automatically be created.
179
*/
180
181
/*!
182
* \property QWaylandQuickShellSurfaceItem::autoCreatePopupItems
183
*
184
* This property holds whether QWaylandQuickShellSurfaceItems for popups
185
* parented to the shell surface managed by this item should automatically be created.
186
*/
187
bool
QWaylandQuickShellSurfaceItem::autoCreatePopupItems()
188
{
189
Q_D(
const
QWaylandQuickShellSurfaceItem);
190
return
d->m_autoCreatePopupItems;
191
}
192
193
void
QWaylandQuickShellSurfaceItem::setAutoCreatePopupItems(
bool
enabled)
194
{
195
Q_D(QWaylandQuickShellSurfaceItem);
196
197
if
(enabled == d->m_autoCreatePopupItems)
198
return
;
199
200
d->m_autoCreatePopupItems = enabled;
201
emit autoCreatePopupItemsChanged();
202
}
203
204
/*!
205
\class QWaylandQuickShellEventFilter
206
\brief QWaylandQuickShellEventFilter implements a Wayland popup grab
207
\internal
208
*/
209
210
void
QWaylandQuickShellEventFilter::startFilter(QWaylandClient *client, CallbackFunction closePopups)
211
{
212
if
(!self)
213
self =
new
QWaylandQuickShellEventFilter(qGuiApp);
214
if
(!self->eventFilterInstalled) {
215
qGuiApp->installEventFilter(self);
216
self->eventFilterInstalled =
true
;
217
self->client = client;
218
self->closePopups = closePopups;
219
}
220
}
221
222
void
QWaylandQuickShellEventFilter::cancelFilter()
223
{
224
if
(!self)
225
return
;
226
if
(self->eventFilterInstalled && !self->waitForRelease)
227
self->stopFilter();
228
}
229
230
void
QWaylandQuickShellEventFilter::stopFilter()
231
{
232
if
(eventFilterInstalled) {
233
qGuiApp->removeEventFilter(
this
);
234
eventFilterInstalled =
false
;
235
}
236
}
237
QWaylandQuickShellEventFilter *QWaylandQuickShellEventFilter::self =
nullptr
;
238
239
QWaylandQuickShellEventFilter::QWaylandQuickShellEventFilter(QObject *parent)
240
: QObject(parent)
241
{
242
}
243
244
bool
QWaylandQuickShellEventFilter::eventFilter(QObject *receiver, QEvent *e)
245
{
246
if
(e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease) {
247
bool
press = e->type() == QEvent::MouseButtonPress;
248
if
(press && !waitForRelease) {
249
// The user clicked something: we need to close popups unless this press is caught later
250
if
(!mousePressTimeout.isActive())
251
mousePressTimeout.start(0,
this
);
252
}
253
254
QQuickItem *item = qobject_cast<QQuickItem*>(receiver);
255
if
(!item)
256
return
false
;
257
258
QMouseEvent *event =
static_cast
<QMouseEvent*>(e);
259
QWaylandQuickShellSurfaceItem *shellSurfaceItem = qobject_cast<QWaylandQuickShellSurfaceItem*>(item);
260
bool
finalRelease = (event->type() == QEvent::MouseButtonRelease) && (event->buttons() == Qt::NoButton);
261
bool
popupClient = shellSurfaceItem && shellSurfaceItem->surface() && shellSurfaceItem->surface()->client() == client;
262
263
if
(waitForRelease) {
264
// We are eating events until all mouse buttons are released
265
if
(finalRelease) {
266
waitForRelease =
false
;
267
stopFilter();
268
}
269
return
true
;
270
}
271
272
if
(finalRelease && mousePressTimeout.isActive()) {
273
// the user somehow managed to press and release the mouse button in 0 milliseconds
274
qWarning(
"Badly written autotest detected"
);
275
mousePressTimeout.stop();
276
stopFilter();
277
}
278
279
if
(press && !shellSurfaceItem && !QQmlProperty(item, QStringLiteral(
"qtwayland_blocking_overlay"
)).isValid()) {
280
// the user clicked on something that's not blocking mouse events
281
e->ignore();
//propagate the event to items below
282
return
true
;
// don't give the event to the item
283
}
284
285
mousePressTimeout.stop();
// we've got this
286
287
if
(press && !popupClient) {
288
// The user clicked outside the active popup's client. The popups should
289
// be closed, but the event filter will stay to catch the release-
290
// event before removing itself.
291
waitForRelease =
true
;
292
closePopups();
293
return
true
;
294
}
295
}
296
297
return
false
;
298
}
299
300
void
QWaylandQuickShellEventFilter::timerEvent(QTimerEvent *event)
301
{
302
if
(event->timerId() == mousePressTimeout.timerId()) {
303
mousePressTimeout.stop();
304
closePopups();
305
stopFilter();
306
// Don't wait for release: Since the press wasn't accepted,
307
// the release won't be delivered.
308
}
309
}
310
311
static
QWaylandQuickShellSurfaceItem *
findSurfaceItemFromMoveItem
(QQuickItem *moveItem)
312
{
313
if
(Q_UNLIKELY(!moveItem))
314
return
nullptr
;
315
if
(
auto
*surf = qobject_cast<QWaylandQuickShellSurfaceItem *>(moveItem))
316
return
surf;
317
318
const
auto
childItems = moveItem->childItems();
319
for
(
auto
*item : childItems) {
320
if
(
auto
*surf = findSurfaceItemFromMoveItem(item))
321
return
surf;
322
}
323
return
nullptr
;
324
}
325
326
static
inline
bool
onTop
(QWaylandQuickShellSurfaceItem *surf)
327
{
328
return
surf->staysOnTop() || (surf->shellSurface() && surf->shellSurface()->isModal());
329
}
330
331
static
inline
bool
onBottom
(QWaylandQuickShellSurfaceItem *surf)
332
{
333
return
surf->staysOnBottom() && !(surf->shellSurface() && surf->shellSurface()->isModal());
334
}
335
336
/*
337
To raise a surface, find the topmost suitable surface and place above that.
338
We start from the top and:
339
If we don't have staysOnTop, skip all surfaces with staysOnTop
340
If we have staysOnBottom, skip all surfaces that don't have staysOnBottom
341
A modal dialog is handled as if it had staysOnTop
342
*/
343
void
QWaylandQuickShellSurfaceItemPrivate::raise()
344
{
345
Q_Q(QWaylandQuickShellSurfaceItem);
346
auto
*moveItem = q->moveItem();
347
QQuickItem *parent = moveItem->parentItem();
348
if
(!parent || !m_shellSurface)
349
return
;
350
const
bool
putOnTop = staysOnTop || m_shellSurface->isModal();
351
const
bool
putOnBottom = staysOnBottom && !m_shellSurface->isModal();
352
353
const
QList<QQuickItem *> childItems = parent->childItems();
354
auto
it = childItems.crbegin();
355
const
auto
end = childItems.crend();
356
auto
skip = [putOnTop, putOnBottom](QQuickItem *item) {
357
if
(
auto
*surf = findSurfaceItemFromMoveItem(item))
358
return
(!putOnTop && onTop(surf)) || (putOnBottom && !onBottom(surf));
359
return
true
;
// ignore any other Quick items that may be there
360
};
361
while
(it != end && skip(*it))
362
++it;
363
if
(it != end) {
364
QQuickItem *top = *it;
365
if
(moveItem != top)
366
moveItem->stackAfter(top);
367
}
368
}
369
370
/*
371
To lower a surface, find the lowest suitable surface and place below that.
372
We start from the bottom and:
373
If we don't have staysOnBottom, skip all surfaces with staysOnBottom
374
If we have staysOnTop, skip all surfaces that don't have staysOnTop
375
A modal dialog is handled as if it had staysOnTop
376
*/
377
void
QWaylandQuickShellSurfaceItemPrivate::lower()
378
{
379
Q_Q(QWaylandQuickShellSurfaceItem);
380
auto
*moveItem = q->moveItem();
381
QQuickItem *parent = moveItem->parentItem();
382
if
(!parent || !m_shellSurface)
383
return
;
384
const
bool
putOnTop = staysOnTop || m_shellSurface->isModal();
385
const
bool
putOnBottom = staysOnBottom && !m_shellSurface->isModal();
386
387
const
QList<QQuickItem *> childItems = parent->childItems();
388
auto
it = childItems.cbegin();
389
auto
skip = [putOnTop, putOnBottom](QQuickItem *item) {
390
if
(
auto
*surf = findSurfaceItemFromMoveItem(item))
391
return
(!putOnBottom && onBottom(surf)) || (putOnTop && !onTop(surf));
392
return
true
;
// ignore any other Quick items that may be there
393
};
394
while
(skip(*it))
395
++it;
396
397
QQuickItem *bottom = *it;
398
if
(moveItem != bottom)
399
moveItem->stackBefore(bottom);
400
}
401
402
/*!
403
* \property QWaylandQuickShellSurfaceItem::staysOnTop
404
*
405
* Keep this item above other Wayland surfaces
406
*/
407
bool
QWaylandQuickShellSurfaceItem::staysOnTop()
const
408
{
409
Q_D(
const
QWaylandQuickShellSurfaceItem);
410
return
d->staysOnTop;
411
}
412
413
void
QWaylandQuickShellSurfaceItem::setStaysOnTop(
bool
onTop)
414
{
415
Q_D(QWaylandQuickShellSurfaceItem);
416
if
(d->staysOnTop == onTop)
417
return
;
418
d->staysOnTop = onTop;
419
if
(d->staysOnBottom) {
420
d->staysOnBottom =
false
;
421
emit staysOnBottomChanged();
422
}
423
// We need to call raise() even if onTop is false, since we need to stack under any other
424
// staysOnTop surfaces in that case
425
raise();
426
emit staysOnTopChanged();
427
Q_ASSERT(!(d->staysOnTop && d->staysOnBottom));
428
}
429
430
/*!
431
* \property QWaylandQuickShellSurfaceItem::staysOnBottom
432
*
433
* Keep this item above other Wayland surfaces
434
*/
435
bool
QWaylandQuickShellSurfaceItem::staysOnBottom()
const
436
{
437
Q_D(
const
QWaylandQuickShellSurfaceItem);
438
return
d->staysOnBottom;
439
}
440
441
void
QWaylandQuickShellSurfaceItem::setStaysOnBottom(
bool
onBottom)
442
{
443
Q_D(QWaylandQuickShellSurfaceItem);
444
if
(d->staysOnBottom == onBottom)
445
return
;
446
d->staysOnBottom = onBottom;
447
if
(d->staysOnTop) {
448
d->staysOnTop =
false
;
449
emit staysOnTopChanged();
450
}
451
// We need to call lower() even if onBottom is false, since we need to stack over any other
452
// staysOnBottom surfaces in that case
453
lower();
454
emit staysOnBottomChanged();
455
Q_ASSERT(!(d->staysOnTop && d->staysOnBottom));
456
}
457
458
QT_END_NAMESPACE
459
460
#
include
"moc_qwaylandquickshellsurfaceitem_p.cpp"
461
462
#
include
"moc_qwaylandquickshellsurfaceitem.cpp"
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
onBottom
static bool onBottom(QWaylandQuickShellSurfaceItem *surf)
Definition
qwaylandquickshellsurfaceitem.cpp:331
findSurfaceItemFromMoveItem
static QWaylandQuickShellSurfaceItem * findSurfaceItemFromMoveItem(QQuickItem *moveItem)
Definition
qwaylandquickshellsurfaceitem.cpp:311
onTop
static bool onTop(QWaylandQuickShellSurfaceItem *surf)
Definition
qwaylandquickshellsurfaceitem.cpp:326
qtwayland
src
compositor
extensions
qwaylandquickshellsurfaceitem.cpp
Generated on
for Qt by
1.18.0