Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
6
7#include <QtWaylandCompositor/QWaylandShellSurface>
8#include <QGuiApplication>
9
11
13{
15 return nullptr;
16
18 auto *popupItem = new QWaylandQuickShellSurfaceItem(q);
19 popupItem->setShellSurface(shellSurface);
20 popupItem->setAutoCreatePopupItems(true);
22 popupItem, &QObject::deleteLater);
23 return popupItem;
24}
25
59
61{
63
64 if (d->m_shellIntegration) {
65 removeEventFilter(d->m_shellIntegration);
66 delete d->m_shellIntegration;
67 }
68}
69
77
98
100{
102 if (d->m_shellSurface == shellSurface)
103 return;
104
105 if (Q_UNLIKELY(d->m_shellSurface))
106 disconnect(d->m_shellSurface, &QWaylandShellSurface::modalChanged, this, nullptr);
107
108 d->m_shellSurface = shellSurface;
109
110 if (d->m_shellIntegration) {
111 removeEventFilter(d->m_shellIntegration);
112 delete d->m_shellIntegration;
113 d->m_shellIntegration = nullptr;
114 }
115
116 if (shellSurface) {
117 d->m_shellIntegration = shellSurface->createIntegration(this);
118 installEventFilter(d->m_shellIntegration);
119 }
120
122 [d](){ if (d->m_shellSurface->modal()) d->raise(); });
123
125}
126
143{
145 return d->m_moveItem ? d->m_moveItem : const_cast<QWaylandQuickShellSurfaceItem *>(this);
146}
147
149{
151 moveItem = moveItem ? moveItem : this;
152 if (this->moveItem() == moveItem)
153 return;
154 d->m_moveItem = moveItem;
156}
157
172{
174 return d->m_autoCreatePopupItems;
175}
176
178{
180
181 if (enabled == d->m_autoCreatePopupItems)
182 return;
183
184 d->m_autoCreatePopupItems = enabled;
186}
187
195{
196 if (!self)
198 if (!self->eventFilterInstalled) {
199 qGuiApp->installEventFilter(self);
200 self->eventFilterInstalled = true;
201 self->client = client;
202 self->closePopups = closePopups;
203 }
204}
205
207{
208 if (!self)
209 return;
210 if (self->eventFilterInstalled && !self->waitForRelease)
211 self->stopFilter();
212}
213
214void QWaylandQuickShellEventFilter::stopFilter()
215{
216 if (eventFilterInstalled) {
217 qGuiApp->removeEventFilter(this);
218 eventFilterInstalled = false;
219 }
220}
221QWaylandQuickShellEventFilter *QWaylandQuickShellEventFilter::self = nullptr;
222
223QWaylandQuickShellEventFilter::QWaylandQuickShellEventFilter(QObject *parent)
224 : QObject(parent)
225{
226}
227
229{
231 bool press = e->type() == QEvent::MouseButtonPress;
232 if (press && !waitForRelease) {
233 // The user clicked something: we need to close popups unless this press is caught later
234 if (!mousePressTimeout.isActive())
235 mousePressTimeout.start(0, this);
236 }
237
239 if (!item)
240 return false;
241
242 QMouseEvent *event = static_cast<QMouseEvent*>(e);
243 QWaylandQuickShellSurfaceItem *shellSurfaceItem = qobject_cast<QWaylandQuickShellSurfaceItem*>(item);
244 bool finalRelease = (event->type() == QEvent::MouseButtonRelease) && (event->buttons() == Qt::NoButton);
245 bool popupClient = shellSurfaceItem && shellSurfaceItem->surface() && shellSurfaceItem->surface()->client() == client;
246
247 if (waitForRelease) {
248 // We are eating events until all mouse buttons are released
249 if (finalRelease) {
250 waitForRelease = false;
251 stopFilter();
252 }
253 return true;
254 }
255
256 if (finalRelease && mousePressTimeout.isActive()) {
257 // the user somehow managed to press and release the mouse button in 0 milliseconds
258 qWarning("Badly written autotest detected");
259 mousePressTimeout.stop();
260 stopFilter();
261 }
262
263 if (press && !shellSurfaceItem && !QQmlProperty(item, QStringLiteral("qtwayland_blocking_overlay")).isValid()) {
264 // the user clicked on something that's not blocking mouse events
265 e->ignore(); //propagate the event to items below
266 return true; // don't give the event to the item
267 }
268
269 mousePressTimeout.stop(); // we've got this
270
271 if (press && !popupClient) {
272 // The user clicked outside the active popup's client. The popups should
273 // be closed, but the event filter will stay to catch the release-
274 // event before removing itself.
275 waitForRelease = true;
276 closePopups();
277 return true;
278 }
279 }
280
281 return false;
282}
283
285{
286 if (event->timerId() == mousePressTimeout.timerId()) {
287 mousePressTimeout.stop();
288 closePopups();
289 stopFilter();
290 // Don't wait for release: Since the press wasn't accepted,
291 // the release won't be delivered.
292 }
293}
294
296{
297 if (Q_UNLIKELY(!moveItem))
298 return nullptr;
299 if (auto *surf = qobject_cast<QWaylandQuickShellSurfaceItem *>(moveItem))
300 return surf;
301 for (auto *item : moveItem->childItems()) {
302 if (auto *surf = findSurfaceItemFromMoveItem(item))
303 return surf;
304 }
305 return nullptr;
306}
307
308static inline bool onTop(QWaylandQuickShellSurfaceItem *surf)
309{
310 return surf->staysOnTop() || surf->shellSurface()->modal();
311}
312
314{
315 return surf->staysOnBottom() && !surf->shellSurface()->modal();
316}
317
318/*
319 To raise a surface, find the topmost suitable surface and place above that.
320 We start from the top and:
321 If we don't have staysOnTop, skip all surfaces with staysOnTop
322 If we have staysOnBottom, skip all surfaces that don't have staysOnBottom
323 A modal dialog is handled as if it had staysOnTop
324 */
326{
328 auto *moveItem = q->moveItem();
329 QQuickItem *parent = moveItem->parentItem();
330 if (!parent)
331 return;
332 const bool putOnTop = staysOnTop || m_shellSurface->modal();
333 const bool putOnBottom = staysOnBottom && !m_shellSurface->modal();
334
335 auto it = parent->childItems().crbegin();
336 auto skip = [=](QQuickItem *item) {
337 if (auto *surf = findSurfaceItemFromMoveItem(item))
338 return (!putOnTop && onTop(surf)) || (putOnBottom && !onBottom(surf));
339 return true; // ignore any other Quick items that may be there
340 };
341 auto end = parent->childItems().crend();
342 while (it != end && skip(*it))
343 ++it;
344 if (it != end) {
345 QQuickItem *top = *it;
346 if (moveItem != top)
347 moveItem->stackAfter(top);
348 }
349}
350
351/*
352 To lower a surface, find the lowest suitable surface and place below that.
353 We start from the bottom and:
354 If we don't have staysOnBottom, skip all surfaces with staysOnBottom
355 If we have staysOnTop, skip all surfaces that don't have staysOnTop
356 A modal dialog is handled as if it had staysOnTop
357 */
359{
361 auto *moveItem = q->moveItem();
362 QQuickItem *parent = moveItem->parentItem();
363 if (!parent)
364 return;
365 const bool putOnTop = staysOnTop || m_shellSurface->modal();
366 const bool putOnBottom = staysOnBottom && !m_shellSurface->modal();
367
368 auto it = parent->childItems().cbegin();
369 auto skip = [=](QQuickItem *item) {
370 if (auto *surf = findSurfaceItemFromMoveItem(item))
371 return (!putOnBottom && onBottom(surf)) || (putOnTop && !onTop(surf));
372 return true; // ignore any other Quick items that may be there
373 };
374 while (skip(*it))
375 ++it;
376
377 QQuickItem *bottom = *it;
378 if (moveItem != bottom)
379 moveItem->stackBefore(bottom);
380}
381
388{
390 return d->staysOnTop;
391}
392
394{
396 if (d->staysOnTop == onTop)
397 return;
398 d->staysOnTop = onTop;
399 if (d->staysOnBottom) {
400 d->staysOnBottom = false;
402 }
403 // We need to call raise() even if onTop is false, since we need to stack under any other
404 // staysOnTop surfaces in that case
405 raise();
407 Q_ASSERT(!(d->staysOnTop && d->staysOnBottom));
408}
409
416{
418 return d->staysOnBottom;
419}
420
422{
424 if (d->staysOnBottom == onBottom)
425 return;
426 d->staysOnBottom = onBottom;
427 if (d->staysOnTop) {
428 d->staysOnTop = false;
430 }
431 // We need to call lower() even if onBottom is false, since we need to stack over any other
432 // staysOnBottom surfaces in that case
433 lower();
435 Q_ASSERT(!(d->staysOnTop && d->staysOnBottom));
436}
437
439
440#include "moc_qwaylandquickshellsurfaceitem_p.cpp"
441
442#include "moc_qwaylandquickshellsurfaceitem.cpp"
void start(int msec, QObject *obj)
\obsolete Use chrono overload instead.
int timerId() const noexcept
Returns the timer's ID.
Definition qbasictimer.h:35
void stop()
Stops the timer.
bool isActive() const noexcept
Returns true if the timer is running and has not been stopped; otherwise returns false.
Definition qbasictimer.h:34
\inmodule QtCore
Definition qcoreevent.h:45
@ MouseButtonPress
Definition qcoreevent.h:60
@ MouseButtonRelease
Definition qcoreevent.h:61
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void ignore()
Clears the accept flag parameter of the event object, the equivalent of calling setAccepted(false).
Definition qcoreevent.h:311
\inmodule QtGui
Definition qevent.h:196
QObject * parent
Definition qobject.h:73
\inmodule QtCore
Definition qobject.h:103
void installEventFilter(QObject *filterObj)
Installs an event filter filterObj on this object.
Definition qobject.cpp:2339
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void removeEventFilter(QObject *obj)
Removes an event filter object obj from this object.
Definition qobject.cpp:2370
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
The QQmlProperty class abstracts accessing properties on objects created from QML.
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QList< QQuickItem * > childItems() const
Returns the children of this item.
bool enabled
\qmlproperty bool QtQuick::Item::enabled
Definition qquickitem.h:79
\inmodule QtCore
Definition qcoreevent.h:366
\qmltype WaylandClient \instantiates QWaylandClient \inqmlmodule QtWayland.Compositor
\qmltype WaylandQuickItem \instantiates QWaylandQuickItem \inqmlmodule QtWayland.Compositor
void surfaceDestroyed()
\qmlsignal void QtWayland.Compositor::WaylandQuickItem::surfaceDestroyed()
QWaylandSurface * surface
\qmlproperty WaylandSurface QtWayland.Compositor::WaylandQuickItem::surface
QWaylandQuickShellEventFilter implements a Wayland popup grab.
bool eventFilter(QObject *, QEvent *) override
Filters events if this object has been installed as an event filter for the watched object.
static void startFilter(QWaylandClient *client, CallbackFunction closePopupCallback)
void timerEvent(QTimerEvent *event) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
QWaylandQuickShellSurfaceItem * maybeCreateAutoPopup(QWaylandShellSurface *shellSurface)
\qmltype ShellSurfaceItem \instantiates QWaylandQuickShellSurfaceItem \inherits WaylandQuickItem \inq...
QQuickItem * moveItem
\qmlproperty Item QtWayland.Compositor::ShellSurfaceItem::moveItem
bool staysOnTop
Keep this item above other Wayland surfaces.
QWaylandShellSurface * shellSurface
\qmlproperty ShellSurface QtWayland.Compositor::ShellSurfaceItem::shellSurface
bool staysOnBottom
Keep this item above other Wayland surfaces.
QWaylandQuickShellSurfaceItem(QQuickItem *parent=nullptr)
Constructs a QWaylandQuickWlShellSurfaceItem with the given parent.
bool autoCreatePopupItems
\qmlproperty bool QtWayland.Compositor::ShellSurfaceItem::autoCreatePopupItems
void setShellSurface(QWaylandShellSurface *shellSurface)
\qmltype ShellSurface \instantiates QWaylandShellSurface \inqmlmodule QtWayland.Compositor
bool modal
\qmlproperty bool QtWayland.Compositor::ShellSurface::modal
QWaylandClient * client
\qmlproperty WaylandClient QtWayland.Compositor::WaylandSurface::client
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ NoButton
Definition qnamespace.h:57
#define Q_UNLIKELY(x)
#define qGuiApp
#define qWarning
Definition qlogging.h:166
GLuint GLuint end
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLint bottom
struct _cl_event * event
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:492
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define emit
static bool onBottom(QWaylandQuickShellSurfaceItem *surf)
static QWaylandQuickShellSurfaceItem * findSurfaceItemFromMoveItem(QQuickItem *moveItem)
static bool onTop(QWaylandQuickShellSurfaceItem *surf)
myObject disconnect()
[26]
QGraphicsItem * item