diff --git a/desktop/toolkit/qt5/qt5-quickcontrols2/files/qt_kde.patch b/desktop/toolkit/qt5/qt5-quickcontrols2/files/qt_kde.patch index 3bc52fd9ae..a71785ce9b 100644 --- a/desktop/toolkit/qt5/qt5-quickcontrols2/files/qt_kde.patch +++ b/desktop/toolkit/qt5/qt5-quickcontrols2/files/qt_kde.patch @@ -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(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(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 diff --git a/desktop/toolkit/qt5/qt5-quickcontrols2/pspec.xml b/desktop/toolkit/qt5/qt5-quickcontrols2/pspec.xml index e41aa1bb1a..060d91a18b 100755 --- a/desktop/toolkit/qt5/qt5-quickcontrols2/pspec.xml +++ b/desktop/toolkit/qt5/qt5-quickcontrols2/pspec.xml @@ -64,6 +64,13 @@ + + 2022-08-24 + 5.15.5 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + 2022-07-05 5.15.5 diff --git a/desktop/toolkit/qt5/qt5-svg/files/qt_kde.patch b/desktop/toolkit/qt5/qt5-svg/files/qt_kde.patch index 4e4ceb1d6d..22461e3010 100644 --- a/desktop/toolkit/qt5/qt5-svg/files/qt_kde.patch +++ b/desktop/toolkit/qt5/qt5-svg/files/qt_kde.patch @@ -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 diff --git a/desktop/toolkit/qt5/qt5-svg/pspec.xml b/desktop/toolkit/qt5/qt5-svg/pspec.xml index 87a91702ee..8cadb2e36c 100755 --- a/desktop/toolkit/qt5/qt5-svg/pspec.xml +++ b/desktop/toolkit/qt5/qt5-svg/pspec.xml @@ -60,6 +60,13 @@ + + 2022-08-24 + 5.15.5 + Version bump. + Mustafa Cinasal + muscnsl@gmail.com + 2022-07-05 5.15.5 diff --git a/desktop/toolkit/qt5/qt5-translations/pspec.xml b/desktop/toolkit/qt5/qt5-translations/pspec.xml index c42c2f640e..73674d5140 100755 --- a/desktop/toolkit/qt5/qt5-translations/pspec.xml +++ b/desktop/toolkit/qt5/qt5-translations/pspec.xml @@ -35,6 +35,13 @@ + + 2022-08-24 + 5.15.5 + Version bump. + Mustafa Cinasal + muscnsl@gmail.com + 2022-07-05 5.15.5 diff --git a/desktop/toolkit/qt5/qt5-wayland/files/qt_kde.patch b/desktop/toolkit/qt5/qt5-wayland/files/qt_kde.patch index e2eef408cf..8ab86e7b3a 100644 --- a/desktop/toolkit/qt5/qt5-wayland/files/qt_kde.patch +++ b/desktop/toolkit/qt5/qt5-wayland/files/qt_kde.patch @@ -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> 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> 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 + #include + ++#include ++ + #include + #include + +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 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 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(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(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 + + 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()); diff --git a/desktop/toolkit/qt5/qt5-wayland/pspec.xml b/desktop/toolkit/qt5/qt5-wayland/pspec.xml index 0162a25f55..bbd41fc2d8 100755 --- a/desktop/toolkit/qt5/qt5-wayland/pspec.xml +++ b/desktop/toolkit/qt5/qt5-wayland/pspec.xml @@ -85,6 +85,13 @@ + + 2022-08-24 + 5.15.5 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + 2022-07-05 5.15.5