qt5-quickcontrols2 ,svg,wayland,translations rebuild

This commit is contained in:
Rmys
2022-08-25 11:48:33 +03:00
parent 67378ef76e
commit da9a063b36
7 changed files with 619 additions and 43 deletions
@@ -75,6 +75,66 @@ index f38c2b09c..6eed2a024 100644
return;
contentHeight = implicitContentHeight;
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index bbbd0e622..1f4b47343 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -845,6 +845,13 @@ void QQuickControlPrivate::executeBackground(bool complete)
quickCompleteDeferred(q, backgroundName(), background);
}
+/*
+ \internal
+
+ Hides an item that was replaced by a newer one, rather than
+ deleting it, as the item is typically created in QML and hence
+ we don't own it.
+*/
void QQuickControlPrivate::hideOldItem(QQuickItem *item)
{
if (!item)
@@ -863,6 +870,29 @@ void QQuickControlPrivate::hideOldItem(QQuickItem *item)
#endif
}
+/*
+ \internal
+
+ Named "unhide" because it's used for cases where an item
+ that was previously hidden by \l hideOldItem() wants to be
+ shown by a control again, such as a ScrollBar in ScrollView.
+*/
+void QQuickControlPrivate::unhideOldItem(QQuickControl *control, QQuickItem *item)
+{
+ Q_ASSERT(item);
+ qCDebug(lcItemManagement) << "unhiding old item" << item;
+
+ item->setVisible(true);
+ item->setParentItem(control);
+
+#if QT_CONFIG(accessibility)
+ // Add the item back in to the accessibility tree.
+ QQuickAccessibleAttached *accessible = accessibleAttached(item);
+ if (accessible)
+ accessible->setIgnored(false);
+#endif
+}
+
void QQuickControlPrivate::updateBaselineOffset()
{
Q_Q(QQuickControl);
diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h
index 8e979079e..a6e624c91 100644
--- a/src/quicktemplates2/qquickcontrol_p_p.h
+++ b/src/quicktemplates2/qquickcontrol_p_p.h
@@ -173,6 +173,7 @@ public:
virtual void executeBackground(bool complete = false);
static void hideOldItem(QQuickItem *item);
+ static void unhideOldItem(QQuickControl *control, QQuickItem *item);
void updateBaselineOffset();
diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp
index e6db14eb5..6197d1547 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox.cpp
@@ -522,6 +582,35 @@ index 65b33b21e..a12e43e0a 100644
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp
index 4e2f509db..1c4b308cd 100644
--- a/src/quicktemplates2/qquickscrollbar.cpp
+++ b/src/quicktemplates2/qquickscrollbar.cpp
@@ -797,6 +797,14 @@ void QQuickScrollBarAttachedPrivate::initHorizontal()
if (parent && parent == flickable->parentItem())
horizontal->stackAfter(flickable);
+ // If a scroll bar was previously hidden (due to e.g. setting a new contentItem
+ // on a ScrollView), we need to make sure that we un-hide it.
+ // We don't bother checking if the item is actually the old one, because
+ // if it's not, all of the things the function does (setting parent, visibility, etc.)
+ // should be no-ops anyway.
+ if (auto control = qobject_cast<QQuickControl*>(q_ptr->parent()))
+ QQuickControlPrivate::unhideOldItem(control, horizontal);
+
layoutHorizontal();
horizontal->setSize(area->property("widthRatio").toReal());
horizontal->setPosition(area->property("xPosition").toReal());
@@ -818,6 +826,9 @@ void QQuickScrollBarAttachedPrivate::initVertical()
if (parent && parent == flickable->parentItem())
vertical->stackAfter(flickable);
+ if (auto control = qobject_cast<QQuickControl*>(q_ptr->parent()))
+ QQuickControlPrivate::unhideOldItem(control, vertical);
+
layoutVertical();
vertical->setSize(area->property("heightRatio").toReal());
vertical->setPosition(area->property("yPosition").toReal());
diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri
index ba09591bf..fa6929f92 100644
--- a/src/quicktemplates2/quicktemplates2.pri
@@ -534,6 +623,62 @@ index ba09591bf..fa6929f92 100644
$$PWD/qquickpopupitem_p_p.h \
$$PWD/qquickpopuppositioner_p_p.h \
$$PWD/qquickpresshandler_p_p.h \
diff --git a/tests/auto/controls/data/tst_scrollview.qml b/tests/auto/controls/data/tst_scrollview.qml
index 0e8b08352..cd4931184 100644
--- a/tests/auto/controls/data/tst_scrollview.qml
+++ b/tests/auto/controls/data/tst_scrollview.qml
@@ -576,4 +576,51 @@ TestCase {
verify(newHorizontalScrollBar.visible)
verify(!oldHorizontalScrollBar.visible)
}
+
+ Component {
+ id: bindingToContentItemAndStandaloneFlickable
+
+ Item {
+ width: 200
+ height: 200
+
+ property alias scrollView: scrollView
+
+ ScrollView {
+ id: scrollView
+ anchors.fill: parent
+ contentItem: listView
+
+ property Item someBinding: contentItem
+ }
+ ListView {
+ id: listView
+ model: 10
+ delegate: ItemDelegate {
+ text: modelData
+ width: listView.width
+ }
+ }
+ }
+ }
+
+ // Tests that scroll bars show up for a ScrollView where
+ // - its contentItem is declared as a standalone, separate item
+ // - there is a binding to contentItem (which causes a default Flickable to be created)
+ function test_bindingToContentItemAndStandaloneFlickable() {
+ let root = createTemporaryObject(bindingToContentItemAndStandaloneFlickable, testCase)
+ verify(root)
+
+ let control = root.scrollView
+ let verticalScrollBar = control.ScrollBar.vertical
+ let horizontalScrollBar = control.ScrollBar.horizontal
+ compare(verticalScrollBar.parent, control)
+ compare(horizontalScrollBar.parent, control)
+ verify(verticalScrollBar.visible)
+ verify(horizontalScrollBar.visible)
+
+ mouseDrag(verticalScrollBar, verticalScrollBar.width / 2, verticalScrollBar.height / 2, 0, 50)
+ verify(verticalScrollBar.active)
+ verify(horizontalScrollBar.active)
+ }
}
diff --git a/tests/auto/controls/data/tst_switch.qml b/tests/auto/controls/data/tst_switch.qml
index b3fab41ca..10b6baa02 100644
--- a/tests/auto/controls/data/tst_switch.qml
@@ -64,6 +64,13 @@
</Package>
<History>
<Update release="29">
<Date>2022-08-24</Date>
<Version>5.15.5</Version>
<Comment>Rebuild.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="28">
<Date>2022-07-05</Date>
<Version>5.15.5</Version>
@@ -421,6 +421,37 @@ index b89608b..89c9e4e 100644
if (key <= MAX_HASH_VALUE && key >= 0)
return str == QLatin1String(wordlist[key]);
}
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index 63d0797..19e7154 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -433,8 +433,16 @@ void QSvgTinyDocument::draw(QPainter *p, QSvgExtraStates &)
draw(p);
}
+static bool isValidMatrix(const QTransform &transform)
+{
+ qreal determinant = transform.determinant();
+ return qIsFinite(determinant);
+}
+
void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect, const QRectF &sourceRect)
{
+ QTransform oldTransform = p->worldTransform();
+
QRectF target = targetRect;
if (target.isEmpty()) {
QPaintDevice *dev = p->device();
@@ -487,6 +495,9 @@ void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect,
}
#endif
}
+
+ if (!isValidMatrix(p->worldTransform()))
+ p->setWorldTransform(oldTransform);
}
QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
index 8f1f03b..36c76ec 100644
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
+7
View File
@@ -60,6 +60,13 @@
</Package>
<History>
<Update release="28">
<Date>2022-08-24</Date>
<Version>5.15.5</Version>
<Comment>Version bump.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="27">
<Date>2022-07-05</Date>
<Version>5.15.5</Version>
@@ -35,6 +35,13 @@
</Package>
<History>
<Update release="25">
<Date>2022-08-24</Date>
<Version>5.15.5</Version>
<Comment>Version bump.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="24">
<Date>2022-07-05</Date>
<Version>5.15.5</Version>
@@ -491,7 +491,7 @@ index 25afff79..96f07bc3 100644
}
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index f10c1f79..86045a35 100644
index f10c1f79..e8613ed8 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -85,10 +85,203 @@
@@ -722,10 +722,15 @@ index f10c1f79..86045a35 100644
if (mSyncCallback)
wl_callback_destroy(mSyncCallback);
@@ -189,6 +381,18 @@ QWaylandDisplay::~QWaylandDisplay(void)
@@ -187,6 +379,21 @@ QWaylandDisplay::~QWaylandDisplay(void)
#endif
if (mDisplay)
wl_display_disconnect(mDisplay);
}
+
+ if (m_frameEventQueue)
+ wl_event_queue_destroy(m_frameEventQueue);
+}
+
+// Steps which is called just after constructor. This separates registry_global() out of the constructor
+// so that factory functions in integration can be overridden.
+void QWaylandDisplay::initialize()
@@ -736,12 +741,10 @@ index f10c1f79..86045a35 100644
+ // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
+ forceRoundTrip();
+ }
+}
+
}
void QWaylandDisplay::ensureScreen()
{
if (!mScreens.empty() || mPlaceholderScreen)
@@ -203,98 +407,37 @@ void QWaylandDisplay::ensureScreen()
@@ -203,98 +410,37 @@ void QWaylandDisplay::ensureScreen()
void QWaylandDisplay::checkError() const
{
@@ -860,7 +863,7 @@ index f10c1f79..86045a35 100644
}
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
@@ -345,7 +488,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
@@ -345,7 +491,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
if (interface == QStringLiteral("wl_output")) {
mWaitingScreens << new QWaylandScreen(this, version, id);
} else if (interface == QStringLiteral("wl_compositor")) {
@@ -869,7 +872,7 @@ index f10c1f79..86045a35 100644
mCompositor.init(registry, id, mCompositorVersion);
} else if (interface == QStringLiteral("wl_shm")) {
mShm.reset(new QWaylandShm(this, version, id));
@@ -354,7 +497,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
@@ -354,7 +500,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mInputDevices.append(inputDevice);
#if QT_CONFIG(wayland_datadevice)
} else if (interface == QStringLiteral("wl_data_device_manager")) {
@@ -878,7 +881,7 @@ index f10c1f79..86045a35 100644
#endif
} else if (interface == QStringLiteral("qt_surface_extension")) {
mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
@@ -452,9 +595,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
@@ -452,9 +598,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
{
@@ -890,7 +893,7 @@ index f10c1f79..86045a35 100644
}
uint32_t QWaylandDisplay::currentTimeMillisec()
@@ -467,50 +611,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec()
@@ -467,50 +614,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec()
return 0;
}
@@ -942,7 +945,7 @@ index f10c1f79..86045a35 100644
}
bool QWaylandDisplay::supportsWindowDecoration() const
@@ -574,14 +677,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
@@ -574,14 +680,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
if (mLastKeyboardFocus == keyboardFocus)
return;
@@ -961,7 +964,7 @@ index f10c1f79..86045a35 100644
mLastKeyboardFocus = keyboardFocus;
}
@@ -600,6 +699,19 @@ void QWaylandDisplay::handleWaylandSync()
@@ -600,6 +702,19 @@ void QWaylandDisplay::handleWaylandSync()
QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
if (activeWindow != QGuiApplication::focusWindow())
QWindowSystemInterface::handleWindowActivated(activeWindow);
@@ -981,7 +984,7 @@ index f10c1f79..86045a35 100644
}
const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
@@ -626,6 +738,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
@@ -626,6 +741,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
}
@@ -995,7 +998,7 @@ index f10c1f79..86045a35 100644
#if QT_CONFIG(cursor)
QWaylandCursor *QWaylandDisplay::waylandCursor()
@@ -652,4 +771,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
@@ -652,4 +774,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
} // namespace QtWaylandClient
@@ -1402,7 +1405,7 @@ index df1c94f2..050cfdc0 100644
#if QT_CONFIG(cursor)
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index e96d8fe9..ceaa4c73 100644
index e96d8fe9..c90a0ebf 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
@@ -1423,7 +1426,15 @@ index e96d8fe9..ceaa4c73 100644
delete mWindowDecoration;
if (mSurface)
@@ -266,6 +262,8 @@ void QWaylandWindow::reset()
@@ -243,6 +239,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
void QWaylandWindow::reset()
{
+ closeChildPopups();
delete mShellSurface;
mShellSurface = nullptr;
delete mSubSurfaceWindow;
@@ -266,6 +263,8 @@ void QWaylandWindow::reset()
mMask = QRegion();
mQueuedBuffer = nullptr;
@@ -1432,7 +1443,7 @@ index e96d8fe9..ceaa4c73 100644
}
QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
@@ -374,7 +372,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
@@ -374,7 +373,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
mShellSurface->setWindowGeometry(windowContentGeometry());
if (isOpaque() && mMask.isEmpty())
@@ -1441,15 +1452,48 @@ index e96d8fe9..ceaa4c73 100644
}
void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset)
@@ -435,7 +433,6 @@ void QWaylandWindow::setVisible(bool visible)
if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
activePopups << this;
@@ -399,21 +398,6 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
mLastExposeGeometry = rect;
}
-
-static QVector<QPointer<QWaylandWindow>> activePopups;
-
-void QWaylandWindow::closePopups(QWaylandWindow *parent)
-{
- while (!activePopups.isEmpty()) {
- auto popup = activePopups.takeLast();
- if (popup.isNull())
- continue;
- if (popup.data() == parent)
- return;
- popup->reset();
- }
-}
-
QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
{
if (mSurface) {
@@ -432,10 +416,7 @@ void QWaylandWindow::setVisible(bool visible)
lastVisible = visible;
if (visible) {
- if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
- activePopups << this;
initWindow();
- mDisplay->flushRequests();
setGeometry(windowGeometry());
// Don't flush the events here, or else the newly visible window may start drawing, but since
@@ -464,14 +461,15 @@ void QWaylandWindow::lower()
@@ -443,7 +424,6 @@ void QWaylandWindow::setVisible(bool visible)
// QWaylandShmBackingStore::beginPaint().
} else {
sendExposeEvent(QRect());
- closePopups(this);
reset();
}
}
@@ -464,14 +444,15 @@ void QWaylandWindow::lower()
void QWaylandWindow::setMask(const QRegion &mask)
{
@@ -1468,7 +1512,7 @@ index e96d8fe9..ceaa4c73 100644
if (mMask.isEmpty()) {
mSurface->set_input_region(nullptr);
@@ -554,8 +552,8 @@ void QWaylandWindow::sendRecursiveExposeEvent()
@@ -554,8 +535,8 @@ void QWaylandWindow::sendRecursiveExposeEvent()
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
{
@@ -1478,7 +1522,7 @@ index e96d8fe9..ceaa4c73 100644
handleUpdate();
buffer->setBusy();
@@ -573,7 +571,11 @@ void QWaylandWindow::attachOffset(QWaylandBuffer *buffer)
@@ -573,7 +554,11 @@ void QWaylandWindow::attachOffset(QWaylandBuffer *buffer)
void QWaylandWindow::damage(const QRect &rect)
{
@@ -1491,7 +1535,7 @@ index e96d8fe9..ceaa4c73 100644
}
void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
@@ -607,8 +609,14 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
@@ -607,8 +592,14 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
return;
attachOffset(buffer);
@@ -1508,7 +1552,7 @@ index e96d8fe9..ceaa4c73 100644
Q_ASSERT(!buffer->committed());
buffer->setCommitted();
mSurface->commit();
@@ -621,42 +629,50 @@ void QWaylandWindow::commit()
@@ -621,42 +612,50 @@ void QWaylandWindow::commit()
const wl_callback_listener QWaylandWindow::callbackListener = {
[](void *data, wl_callback *callback, uint32_t time) {
@@ -1574,7 +1618,7 @@ index e96d8fe9..ceaa4c73 100644
if (mWaitingForFrameCallback) {
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
@@ -805,7 +821,7 @@ bool QWaylandWindow::createDecoration()
@@ -805,7 +804,7 @@ bool QWaylandWindow::createDecoration()
decoration = false;
if (mSubSurfaceWindow)
decoration = false;
@@ -1583,7 +1627,7 @@ index e96d8fe9..ceaa4c73 100644
decoration = false;
bool hadDecoration = mWindowDecoration;
@@ -1078,10 +1094,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
@@ -1078,10 +1077,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
return true;
}
@@ -1603,7 +1647,7 @@ index e96d8fe9..ceaa4c73 100644
mLastReportedWindowStates = states;
}
@@ -1144,8 +1168,11 @@ void QWaylandWindow::requestUpdate()
@@ -1144,8 +1151,11 @@ void QWaylandWindow::requestUpdate()
Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
// If we have a frame callback all is good and will be taken care of there
@@ -1617,7 +1661,7 @@ index e96d8fe9..ceaa4c73 100644
// If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
// This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
@@ -1158,7 +1185,12 @@ void QWaylandWindow::requestUpdate()
@@ -1158,7 +1168,12 @@ void QWaylandWindow::requestUpdate()
// so use invokeMethod to delay the delivery a bit.
QMetaObject::invokeMethod(this, [this] {
// Things might have changed in the meantime
@@ -1631,7 +1675,7 @@ index e96d8fe9..ceaa4c73 100644
deliverUpdateRequest();
}, Qt::QueuedConnection);
}
@@ -1169,19 +1201,19 @@ void QWaylandWindow::requestUpdate()
@@ -1169,19 +1184,19 @@ void QWaylandWindow::requestUpdate()
void QWaylandWindow::handleUpdate()
{
qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
@@ -1657,7 +1701,7 @@ index e96d8fe9..ceaa4c73 100644
mFrameCallback = wl_surface_frame(wrappedSurface);
wl_proxy_wrapper_destroy(wrappedSurface);
wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
@@ -1191,6 +1223,8 @@ void QWaylandWindow::handleUpdate()
@@ -1191,6 +1206,8 @@ void QWaylandWindow::handleUpdate()
// Start a timer for handling the case when the compositor stops sending frame callbacks.
if (mFrameCallbackTimeout > 0) {
QMetaObject::invokeMethod(this, [this] {
@@ -1666,8 +1710,29 @@ index e96d8fe9..ceaa4c73 100644
if (mWaitingForFrameCallback) {
if (mFrameCallbackCheckIntervalTimerId < 0)
mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
@@ -1251,6 +1268,20 @@ void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
wl_region_destroy(region);
}
+void QWaylandWindow::addChildPopup(QWaylandWindow *surface) {
+ mChildPopups.append(surface);
+}
+
+void QWaylandWindow::removeChildPopup(QWaylandWindow *surface) {
+ mChildPopups.removeAll(surface);
+}
+
+void QWaylandWindow::closeChildPopups() {
+ while (!mChildPopups.isEmpty()) {
+ auto popup = mChildPopups.takeLast();
+ popup->reset();
+ }
+}
}
QT_END_NAMESPACE
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 6cc1664b..cb9135f6 100644
index 6cc1664b..d211178a 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -148,6 +148,7 @@ public:
@@ -1678,7 +1743,18 @@ index 6cc1664b..cb9135f6 100644
void raise() override;
void lower() override;
@@ -227,11 +228,11 @@ protected:
@@ -206,6 +207,10 @@ public:
void handleUpdate();
void deliverUpdateRequest() override;
+ void addChildPopup(QWaylandWindow* child);
+ void removeChildPopup(QWaylandWindow* child);
+ void closeChildPopups();
+
public slots:
void applyConfigure();
@@ -227,11 +232,11 @@ protected:
WId mWindowId;
bool mWaitingForFrameCallback = false;
bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
@@ -1692,6 +1768,15 @@ index 6cc1664b..cb9135f6 100644
QWaitCondition mFrameSyncWait;
// True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
@@ -261,6 +266,8 @@ protected:
QWaylandBuffer *mQueuedBuffer = nullptr;
QRegion mQueuedBufferDamage;
+ QList<QPointer<QWaylandWindow>> mChildPopups;
+
private:
void setGeometry_helper(const QRect &rect);
void initWindow();
diff --git a/src/client/shellintegration/qwaylandshellintegration_p.h b/src/client/shellintegration/qwaylandshellintegration_p.h
index ccad0048..4cc9b3b8 100644
--- a/src/client/shellintegration/qwaylandshellintegration_p.h
@@ -1811,6 +1896,80 @@ index 5b1f4d56..0079dfef 100644
};
}
diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
index 56a710c3..c6a8b6c6 100644
--- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
+++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
@@ -41,6 +41,8 @@
#include <QtCore/QTextStream>
#include <QtGui/QOpenGLTexture>
+#include <array>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
index 85d25e3c..60bdd491 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5.cpp
@@ -47,18 +47,21 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandXdgPopupV5::QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow *window)
+QWaylandXdgPopupV5::QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow* parent, QWaylandWindow *window)
: QWaylandShellSurface(window)
, QtWayland::xdg_popup_v5(popup)
+ , m_parent(parent)
, m_window(window)
{
if (window->display()->windowExtension())
m_extendedWindow = new QWaylandExtendedSurface(window);
+ m_parent->addChildPopup(m_window);
}
QWaylandXdgPopupV5::~QWaylandXdgPopupV5()
{
xdg_popup_destroy(object());
+ m_parent->removeChildPopup(m_window);
delete m_extendedWindow;
}
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
index 7494f6a6..d85f130b 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgpopupv5_p.h
@@ -70,7 +70,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgPopupV5 : public QWaylandShellSurface
{
Q_OBJECT
public:
- QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow *window);
+ QWaylandXdgPopupV5(struct ::xdg_popup_v5 *popup, QWaylandWindow* parent, QWaylandWindow *window);
~QWaylandXdgPopupV5() override;
protected:
@@ -78,6 +78,7 @@ protected:
private:
QWaylandExtendedSurface *m_extendedWindow = nullptr;
+ QWaylandWindow *m_parent = nullptr;
QWaylandWindow *m_window = nullptr;
};
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
index 7e242c4a..def8452a 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
@@ -84,7 +84,7 @@ QWaylandXdgPopupV5 *QWaylandXdgShellV5::createXdgPopup(QWaylandWindow *window, Q
int x = position.x() + parentWindow->frameMargins().left();
int y = position.y() + parentWindow->frameMargins().top();
- auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), window);
+ auto popup = new QWaylandXdgPopupV5(get_xdg_popup(window->wlSurface(), parentSurface, seat, m_popupSerial, x, y), parentWindow, window);
m_popups.append(window);
QObject::connect(popup, &QWaylandXdgPopupV5::destroyed, [this, window](){
m_popups.removeOne(window);
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
index 4e25949f..cfc60939 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
@@ -1841,6 +2000,27 @@ index ce6bdb9e..aed88670 100644
private:
QScopedPointer<QWaylandXdgShellV5> m_xdgShell;
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
index 8c371661..151c78e3 100644
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6.cpp
@@ -174,6 +174,7 @@ QWaylandXdgSurfaceV6::Popup::Popup(QWaylandXdgSurfaceV6 *xdgSurface, QWaylandXdg
, m_xdgSurface(xdgSurface)
, m_parent(parent)
{
+ m_parent->window()->addChildPopup(m_xdgSurface->window());
}
QWaylandXdgSurfaceV6::Popup::~Popup()
@@ -181,6 +182,8 @@ QWaylandXdgSurfaceV6::Popup::~Popup()
if (isInitialized())
destroy();
+ m_parent->window()->removeChildPopup(m_xdgSurface->window());
+
if (m_grabbing) {
auto *shell = m_xdgSurface->m_shell;
Q_ASSERT(shell->m_topmostGrabbingPopup == this);
diff --git a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp b/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
index 03164316..e8da8ba1 100644
--- a/src/plugins/shellintegration/xdg-shell-v6/qwaylandxdgshellv6integration.cpp
@@ -1879,7 +2059,7 @@ index 261f8cbb..c1bcd5c6 100644
private:
QScopedPointer<QWaylandXdgShellV6> m_xdgShell;
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index 3a1569f7..d7d0ddf7 100644
index 3a1569f7..3999a5ee 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -67,11 +67,6 @@ QWaylandXdgSurface::Toplevel::Toplevel(QWaylandXdgSurface *xdgSurface)
@@ -1925,7 +2105,44 @@ index 3a1569f7..d7d0ddf7 100644
m_applied = m_pending;
qCDebug(lcQpaWayland) << "Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states;
}
@@ -257,6 +249,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
@@ -203,12 +195,17 @@ QtWayland::xdg_toplevel::resize_edge QWaylandXdgSurface::Toplevel::convertToResi
| ((edges & Qt::RightEdge) ? resize_edge_right : 0));
}
-QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent,
+QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent,
QtWayland::xdg_positioner *positioner)
- : xdg_popup(xdgSurface->get_popup(parent->object(), positioner->object()))
- , m_xdgSurface(xdgSurface)
+ : m_xdgSurface(xdgSurface)
+ , m_parentXdgSurface(qobject_cast<QWaylandXdgSurface *>(parent->shellSurface()))
, m_parent(parent)
{
+
+ init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() : nullptr, positioner->object()));
+ if (m_parent) {
+ m_parent->addChildPopup(m_xdgSurface->window());
+ }
}
QWaylandXdgSurface::Popup::~Popup()
@@ -216,10 +213,14 @@ QWaylandXdgSurface::Popup::~Popup()
if (isInitialized())
destroy();
+ if (m_parent) {
+ m_parent->removeChildPopup(m_xdgSurface->window());
+ }
+
if (m_grabbing) {
auto *shell = m_xdgSurface->m_shell;
Q_ASSERT(shell->m_topmostGrabbingPopup == this);
- shell->m_topmostGrabbingPopup = m_parent->m_popup;
+ shell->m_topmostGrabbingPopup = m_parentXdgSurface ? m_parentXdgSurface->m_popup : nullptr;
}
}
@@ -257,6 +258,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s
m_toplevel->set_parent(parentXdgSurface->m_toplevel->object());
}
}
@@ -1933,6 +2150,48 @@ index 3a1569f7..d7d0ddf7 100644
}
QWaylandXdgSurface::~QWaylandXdgSurface()
@@ -399,8 +401,6 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
{
Q_ASSERT(!m_toplevel && !m_popup);
- auto parentXdgSurface = static_cast<QWaylandXdgSurface *>(parent->shellSurface());
-
auto positioner = new QtWayland::xdg_positioner(m_shell->create_positioner());
// set_popup expects a position relative to the parent
QPoint transientPos = m_window->geometry().topLeft(); // this is absolute
@@ -413,8 +413,9 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent)
positioner->set_anchor(QtWayland::xdg_positioner::anchor_top_left);
positioner->set_gravity(QtWayland::xdg_positioner::gravity_bottom_right);
positioner->set_size(m_window->geometry().width(), m_window->geometry().height());
- m_popup = new Popup(this, parentXdgSurface, positioner);
+ m_popup = new Popup(this, parent, positioner);
positioner->destroy();
+
delete positioner;
}
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
index 0c98be35..28ff76ba 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
+++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h
@@ -131,14 +131,15 @@ private:
class Popup : public QtWayland::xdg_popup {
public:
- Popup(QWaylandXdgSurface *xdgSurface, QWaylandXdgSurface *parent, QtWayland::xdg_positioner *positioner);
+ Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow *parent, QtWayland::xdg_positioner *positioner);
~Popup() override;
void grab(QWaylandInputDevice *seat, uint serial);
void xdg_popup_popup_done() override;
QWaylandXdgSurface *m_xdgSurface = nullptr;
- QWaylandXdgSurface *m_parent = nullptr;
+ QWaylandXdgSurface *m_parentXdgSurface = nullptr;
+ QWaylandWindow *m_parent = nullptr;
bool m_grabbing = false;
};
diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
index 8769d971..da0dd6a7 100644
--- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp
@@ -2070,6 +2329,18 @@ index 1568b3b9..067410d0 100644
class DataDeviceCompositor : public DefaultCompositor {
public:
diff --git a/tests/auto/client/shared/corecompositor.cpp b/tests/auto/client/shared/corecompositor.cpp
index 5c6c83ba..fa9b7662 100644
--- a/tests/auto/client/shared/corecompositor.cpp
+++ b/tests/auto/client/shared/corecompositor.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include "corecompositor.h"
+#include <thread>
namespace MockCompositor {
diff --git a/tests/auto/client/shared/coreprotocol.h b/tests/auto/client/shared/coreprotocol.h
index a1af137a..296dbf47 100644
--- a/tests/auto/client/shared/coreprotocol.h
@@ -2131,7 +2402,7 @@ index 949dc23d..d176837e 100644
uint32_t callback) override;
void surface_commit(Resource *resource) override;
diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp
index 2277bbb8..73d1eb9c 100644
index 2277bbb8..747875b4 100644
--- a/tests/auto/client/xdgshell/tst_xdgshell.cpp
+++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp
@@ -31,6 +31,7 @@
@@ -2142,7 +2413,15 @@ index 2277bbb8..73d1eb9c 100644
using namespace MockCompositor;
@@ -138,6 +139,7 @@ void tst_xdgshell::configureSize()
@@ -45,6 +46,7 @@ private slots:
void configureStates();
void popup();
void tooltipOnPopup();
+ void tooltipAndSiblingPopup();
void switchPopups();
void hidePopupParent();
void pongs();
@@ -138,6 +140,7 @@ void tst_xdgshell::configureSize()
void tst_xdgshell::configureStates()
{
@@ -2150,7 +2429,7 @@ index 2277bbb8..73d1eb9c 100644
QRasterWindow window;
window.resize(64, 48);
window.show();
@@ -154,9 +156,12 @@ void tst_xdgshell::configureStates()
@@ -154,9 +157,12 @@ void tst_xdgshell::configureStates()
// Toplevel windows don't know their position on xdg-shell
// QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
@@ -2166,7 +2445,7 @@ index 2277bbb8..73d1eb9c 100644
const QSize screenSize(640, 480);
const uint maximizedSerial = exec([=] {
@@ -186,6 +191,7 @@ void tst_xdgshell::configureStates()
@@ -186,6 +192,7 @@ void tst_xdgshell::configureStates()
QCOMPARE(window.windowStates(), Qt::WindowNoState);
QCOMPARE(window.frameGeometry().size(), windowedSize);
// QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled
@@ -2174,7 +2453,100 @@ index 2277bbb8..73d1eb9c 100644
}
void tst_xdgshell::popup()
@@ -505,7 +511,7 @@ void tst_xdgshell::minMaxSize()
@@ -340,6 +347,92 @@ void tst_xdgshell::tooltipOnPopup()
QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
}
+void tst_xdgshell::tooltipAndSiblingPopup()
+{
+ class ToolTip : public QRasterWindow {
+ public:
+ explicit ToolTip(QWindow *parent) {
+ setTransientParent(parent);
+ setFlags(Qt::ToolTip);
+ resize(100, 100);
+ show();
+ }
+ void mousePressEvent(QMouseEvent *event) override {
+ QRasterWindow::mousePressEvent(event);
+ m_popup = new QRasterWindow;
+ m_popup->setTransientParent(transientParent());
+ m_popup->setFlags(Qt::Popup);
+ m_popup->resize(100, 100);
+ m_popup->show();
+ }
+
+ QRasterWindow *m_popup = nullptr;
+ };
+
+ class Window : public QRasterWindow {
+ public:
+ void mousePressEvent(QMouseEvent *event) override {
+ QRasterWindow::mousePressEvent(event);
+ m_tooltip = new ToolTip(this);
+ }
+ ToolTip *m_tooltip = nullptr;
+ };
+
+ Window window;
+ window.resize(200, 200);
+ window.show();
+
+ QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
+ exec([=] { xdgToplevel()->sendCompleteConfigure(); });
+ QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial);
+
+ exec([=] {
+ auto *surface = xdgToplevel()->surface();
+ auto *p = pointer();
+ auto *c = client();
+ p->sendEnter(surface, {100, 100});
+ p->sendFrame(c);
+ p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
+ p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
+ p->sendFrame(c);
+ p->sendLeave(surface);
+ p->sendFrame(c);
+ });
+
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup());
+ exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial);
+ QCOMPOSITOR_TRY_VERIFY(!xdgPopup()->m_grabbed);
+
+ exec([=] {
+ auto *surface = xdgPopup()->surface();
+ auto *p = pointer();
+ auto *c = client();
+ p->sendEnter(surface, {100, 100});
+ p->sendFrame(c);
+ p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
+ p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
+ p->sendFrame(c);
+ });
+
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup(1));
+ exec([=] { xdgPopup(1)->sendCompleteConfigure(QRect(100, 100, 100, 100)); });
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_xdgSurface->m_committedConfigureSerial);
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_grabbed);
+
+ // Close the middle tooltip (it should not close the sibling popup)
+ window.m_tooltip->close();
+
+ QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr);
+ // Verify the remaining xdg surface is a grab popup..
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup(0));
+ QCOMPOSITOR_TRY_VERIFY(xdgPopup(0)->m_grabbed);
+
+ window.m_tooltip->m_popup->close();
+ QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr);
+ QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr);
+}
+
// QTBUG-65680
void tst_xdgshell::switchPopups()
{
@@ -505,7 +598,7 @@ void tst_xdgshell::minMaxSize()
window.show();
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
@@ -85,6 +85,13 @@
</Package>
<History>
<Update release="30">
<Date>2022-08-24</Date>
<Version>5.15.5</Version>
<Comment>Rebuild.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="29">
<Date>2022-07-05</Date>
<Version>5.15.5</Version>