diff options
33 files changed, 283 insertions, 148 deletions
diff --git a/.qmake.conf b/.qmake.conf index 2c01c5d2a..4eca97a6c 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ DEFINES += QT_NO_FOREACH DEFINES += QT_NO_JAVA_STYLE_ITERATORS DEFINES += QT_NO_LINKED_LIST -MODULE_VERSION = 5.14.0 +MODULE_VERSION = 5.14.2 diff --git a/dist/changes-5.14.1 b/dist/changes-5.14.1 new file mode 100644 index 000000000..0da0c1ba6 --- /dev/null +++ b/dist/changes-5.14.1 @@ -0,0 +1,34 @@ +Qt 5.14.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* QPA plugin * +**************************************************************************** + + - Fixed a crash when re-showing a popup after hiding its parent. + - Fixed keyboard repeat rate being set inversely, so higher rates would + actually result in fewer characters per second, and vice versa. + - Fixed a performance issue due to animated cursors updating too often. + - Fixed a compile error. + +**************************************************************************** +* Compositor * +**************************************************************************** + + - Fixed the linux-dmabuf plugins not being built on some systems. diff --git a/dist/changes-5.14.2 b/dist/changes-5.14.2 new file mode 100644 index 000000000..68a005176 --- /dev/null +++ b/dist/changes-5.14.2 @@ -0,0 +1,20 @@ +Qt 5.14.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0 through 5.14.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + + - This release contains only minor code improvements. diff --git a/examples/wayland/texture-sharing/custom-compositor/main.cpp b/examples/wayland/texture-sharing/custom-compositor/main.cpp index a39c8c381..af3750247 100644 --- a/examples/wayland/texture-sharing/custom-compositor/main.cpp +++ b/examples/wayland/texture-sharing/custom-compositor/main.cpp @@ -63,6 +63,10 @@ #include "QtWaylandCompositor/private/qwltexturesharingextension_p.h" +#ifndef GL_RGBA8 +#define GL_RGBA8 0x8058 +#endif + class CustomSharingExtension : public QWaylandTextureSharingExtension { Q_OBJECT diff --git a/src/client/configure.json b/src/client/configure.json index e9e16324b..062139685 100644 --- a/src/client/configure.json +++ b/src/client/configure.json @@ -74,7 +74,7 @@ "label": "Linux dma-buf Buffer Sharing", "type": "compile", "test": "dmabuf_server_buffer", - "use": "egl" + "use": "egl drm" }, "vulkan-server-buffer": { "label": "Vulkan Buffer Sharing", diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp index 4356b23a0..1d3d88bea 100644 --- a/src/client/qwaylandcursor.cpp +++ b/src/client/qwaylandcursor.cpp @@ -219,7 +219,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape) return nullptr; } -::wl_cursor_image *QWaylandCursorTheme::cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation) +::wl_cursor *QWaylandCursorTheme::cursor(Qt::CursorShape shape) { struct wl_cursor *waylandCursor = nullptr; @@ -237,15 +237,7 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape) return nullptr; } - int frame = wl_cursor_frame(waylandCursor, millisecondsIntoAnimation); - ::wl_cursor_image *image = waylandCursor->images[frame]; - ::wl_buffer *buffer = wl_cursor_image_get_buffer(image); - if (!buffer) { - qCWarning(lcQpaWayland) << "Could not find buffer for cursor"; - return nullptr; - } - - return image; + return waylandCursor; } QWaylandCursor::QWaylandCursor(QWaylandDisplay *display) diff --git a/src/client/qwaylandcursor_p.h b/src/client/qwaylandcursor_p.h index a4605f3d2..751ffa68b 100644 --- a/src/client/qwaylandcursor_p.h +++ b/src/client/qwaylandcursor_p.h @@ -75,7 +75,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme public: static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName); ~QWaylandCursorTheme(); - ::wl_cursor_image *cursorImage(Qt::CursorShape shape, uint millisecondsIntoAnimation = 0); + ::wl_cursor *cursor(Qt::CursorShape shape); private: enum WaylandCursor { @@ -129,7 +129,6 @@ public: void setPos(const QPoint &pos) override; static QSharedPointer<QWaylandBuffer> cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor); - struct wl_cursor_image *cursorImage(Qt::CursorShape shape); private: QWaylandDisplay *mDisplay = nullptr; diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index a4098edd3..320e34040 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -88,7 +88,7 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p) // or the server didn't send an enter event first. return; } - mRepeatTimer.setInterval(mRepeatRate); + mRepeatTimer.setInterval(1000 / mRepeatRate); handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers, mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers, mRepeatKey.text, true); @@ -143,6 +143,12 @@ QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat) : mParent(seat) { +#if QT_CONFIG(cursor) + mCursor.frameTimer.setSingleShot(true); + mCursor.frameTimer.callOnTimeout([&]() { + cursorTimerCallback(); + }); +#endif } QWaylandInputDevice::Pointer::~Pointer() @@ -224,7 +230,7 @@ public: if (animated) { m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){ Q_UNUSED(time); - m_pointer->updateCursor(); + m_pointer->cursorFrameCallback(); })); } commit(); @@ -283,8 +289,8 @@ void QWaylandInputDevice::Pointer::updateCursorTheme() if (!mCursor.theme) return; // A warning has already been printed in loadCursorTheme - if (auto *arrow = mCursor.theme->cursorImage(Qt::ArrowCursor)) { - int arrowPixelSize = qMax(arrow->width, arrow->height); // Not all cursor themes are square + if (auto *arrow = mCursor.theme->cursor(Qt::ArrowCursor)) { + int arrowPixelSize = qMax(arrow->images[0]->width, arrow->images[0]->height); // Not all cursor themes are square while (scale > 1 && arrowPixelSize / scale < cursorSize()) --scale; } else { @@ -326,12 +332,26 @@ void QWaylandInputDevice::Pointer::updateCursor() // Set from shape using theme uint time = seat()->mCursor.animationTimer.elapsed(); - if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) { + + if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) { + uint duration = 0; + int frame = wl_cursor_frame_and_duration(waylandCursor, time, &duration); + ::wl_cursor_image *image = waylandCursor->images[frame]; + struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); + if (!buffer) { + qCWarning(lcQpaWayland) << "Could not find buffer for cursor" << shape; + return; + } int bufferScale = mCursor.themeBufferScale; QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale; QSize size = QSize(image->width, image->height) / bufferScale; - bool animated = image->delay > 0; + bool animated = duration > 0; + if (animated) { + mCursor.gotFrameCallback = false; + mCursor.gotTimerCallback = false; + mCursor.frameTimer.start(duration); + } getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated); return; } @@ -346,6 +366,22 @@ CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface() return mCursor.surface.get(); } +void QWaylandInputDevice::Pointer::cursorTimerCallback() +{ + mCursor.gotTimerCallback = true; + if (mCursor.gotFrameCallback) { + updateCursor(); + } +} + +void QWaylandInputDevice::Pointer::cursorFrameCallback() +{ + mCursor.gotFrameCallback = true; + if (mCursor.gotTimerCallback) { + updateCursor(); + } +} + #endif // QT_CONFIG(cursor) QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p) @@ -1351,7 +1387,7 @@ void QWaylandInputDevice::Touch::touch_cancel() void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition) { auto end = mTouch->mPendingTouchPoints.end(); - auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](auto tp){ return tp.id == id; }); + auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](const QWindowSystemInterface::TouchPoint &tp){ return tp.id == id; }); if (it == end) { it = mTouch->mPendingTouchPoints.insert(end, QWindowSystemInterface::TouchPoint()); it->id = id; diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h index 60d6f2c17..a567c57b4 100644 --- a/src/client/qwaylandinputdevice_p.h +++ b/src/client/qwaylandinputdevice_p.h @@ -286,6 +286,8 @@ public: int idealCursorScale() const; void updateCursorTheme(); void updateCursor(); + void cursorTimerCallback(); + void cursorFrameCallback(); CursorSurface *getOrCreateCursorSurface(); #endif QWaylandInputDevice *seat() const { return mParent; } @@ -325,6 +327,9 @@ public: QWaylandCursorTheme *theme = nullptr; int themeBufferScale = 0; QScopedPointer<CursorSurface> surface; + QTimer frameTimer; + bool gotFrameCallback = false; + bool gotTimerCallback = false; } mCursor; #endif QPointF mSurfacePos; diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 950486c0c..0df99d9fe 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -426,8 +426,7 @@ void QWaylandWindow::setVisible(bool visible) // QWaylandShmBackingStore::beginPaint(). } else { sendExposeEvent(QRect()); - if (window()->type() == Qt::Popup) - closePopups(this); + closePopups(this); reset(); } } diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 5b77a3be1..256aa42db 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -236,9 +236,12 @@ void QWaylandCompositorPrivate::init() QWaylandCompositorPrivate::~QWaylandCompositorPrivate() { - qDeleteAll(clients); + // Take copies, since the lists will get modified as elements are deleted + const auto clientsToDelete = clients; + qDeleteAll(clientsToDelete); - qDeleteAll(outputs); + const auto outputsToDelete = outputs; + qDeleteAll(outputsToDelete); #if QT_CONFIG(wayland_datadevice) delete data_device_manager; @@ -365,6 +368,9 @@ void QWaylandCompositorPrivate::initializeHardwareIntegration() loadClientBufferIntegration(); loadServerBufferIntegration(); + + if (client_buffer_integration) + client_buffer_integration->initializeHardware(display); #endif } @@ -394,32 +400,12 @@ void QWaylandCompositorPrivate::loadClientBufferIntegration() if (!targetKey.isEmpty()) { client_buffer_integration.reset(QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList())); if (client_buffer_integration) { - qCDebug(qLcWaylandCompositorHardwareIntegration) << "Loaded client buffer integration:" << targetKey; client_buffer_integration->setCompositor(q); - if (!client_buffer_integration->initializeHardware(display)) { - qCWarning(qLcWaylandCompositorHardwareIntegration) - << "Failed to initialize hardware for client buffer integration:" << targetKey; - client_buffer_integration.reset(); - } - } else { - qCWarning(qLcWaylandCompositorHardwareIntegration) - << "Failed to load client buffer integration:" << targetKey; + if (hw_integration) + hw_integration->setClientBufferIntegration(targetKey); } } - - if (!client_buffer_integration) { - qCWarning(qLcWaylandCompositorHardwareIntegration) - << "No client buffer integration was loaded, this means that clients will fall back" - << "to use CPU buffers (wl_shm) for transmitting buffers instead of using zero-copy" - << "GPU buffer handles. Expect serious performance impact with OpenGL clients due" - << "to potentially multiple copies between CPU and GPU memory per buffer.\n" - << "See the QtWayland readme for more info about how to build and configure Qt for" - << "your device."; - return; - } - - if (client_buffer_integration && hw_integration) - hw_integration->setClientBufferIntegration(targetKey); + //BUG: if there is no client buffer integration, bad things will happen when opengl is used #endif } diff --git a/src/compositor/configure.json b/src/compositor/configure.json index 46caceff5..0dbb33643 100644 --- a/src/compositor/configure.json +++ b/src/compositor/configure.json @@ -80,13 +80,13 @@ "label": "Linux dma-buf Buffer Sharing", "type": "compile", "test": "dmabuf_server_buffer", - "use": "egl" + "use": "egl drm" }, "dmabuf-client-buffer": { "label": "Linux Client dma-buf Buffer Sharing", "type": "compile", "test": "dmabuf_client_buffer", - "use": "egl" + "use": "egl drm" }, "vulkan-server-buffer": { "label": "Vulkan Buffer Sharing", diff --git a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc index a89e07d78..255f49a4d 100644 --- a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc +++ b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc @@ -39,7 +39,7 @@ \qml \QtMinorVersion import QtWayland.Compositor 1.\1 - \endcode + \endqml To link against the module, add this line to your \l qmake \c .pro file: diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri index 61ab043ea..06e3ef9ee 100644 --- a/src/compositor/extensions/extensions.pri +++ b/src/compositor/extensions/extensions.pri @@ -8,6 +8,7 @@ WAYLANDSERVERSOURCES += \ ../extensions/touch-extension.xml \ ../extensions/qt-key-unstable-v1.xml \ ../extensions/qt-windowmanager.xml \ + ../extensions/qt-texture-sharing-unstable-v1.xml \ ../3rdparty/protocol/text-input-unstable-v2.xml \ ../3rdparty/protocol/viewporter.xml \ ../3rdparty/protocol/scaler.xml \ @@ -96,9 +97,6 @@ qtHaveModule(quick) { extensions/qwaylandxdgshellintegration.cpp \ qtConfig(opengl) { - WAYLANDSERVERSOURCES += \ - ../extensions/qt-texture-sharing-unstable-v1.xml - HEADERS += \ extensions/qwltexturesharingextension_p.h diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h index 2e962273f..0195f3d4b 100644 --- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h +++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h @@ -64,7 +64,7 @@ public: void setCompositor(QWaylandCompositor *compositor) { m_compositor = compositor; } QWaylandCompositor *compositor() const { return m_compositor; } - virtual bool initializeHardware(struct ::wl_display *display) = 0; + virtual void initializeHardware(struct ::wl_display *display) = 0; virtual ClientBuffer *createBufferFor(struct ::wl_resource *buffer) = 0; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index 5bd2760d0..7679a5fb3 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -312,7 +312,7 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis // Create an EGL context for the decorations blitter. By using a dedicated context we don't need to make sure to not // change the context state and we also use OpenGL ES 2 API independently to what the app is using to draw. - QVector<EGLint> eglDecorationsContextAttrs = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE }; + QVector<EGLint> eglDecorationsContextAttrs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; m_decorationsContext = eglCreateContext(m_eglDisplay, m_config, m_context, eglDecorationsContextAttrs.constData()); if (m_decorationsContext == EGL_NO_CONTEXT) qWarning("QWaylandGLContext: Failed to create the decorations EGLContext. Decorations will not be drawn."); diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp index 8ddb4f951..de39ff1d2 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp @@ -67,48 +67,46 @@ BrcmEglIntegration::BrcmEglIntegration() { } -bool BrcmEglIntegration::initializeHardware(struct ::wl_display *display) +void BrcmEglIntegration::initializeHardware(struct ::wl_display *display) { Q_D(BrcmEglIntegration); QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - if (!nativeInterface) - return false; + if (nativeInterface) { + d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); + if (!d->egl_display) + qWarning("Failed to acquire EGL display from platform integration"); - d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); - if (!d->egl_display) - qWarning("Failed to acquire EGL display from platform integration"); + d->eglQueryGlobalImageBRCM = (PFNEGLQUERYGLOBALIMAGEBRCMPROC) eglGetProcAddress("eglQueryGlobalImageBRCM"); - d->eglQueryGlobalImageBRCM = (PFNEGLQUERYGLOBALIMAGEBRCMPROC) eglGetProcAddress("eglQueryGlobalImageBRCM"); + if (!d->eglQueryGlobalImageBRCM) { + qWarning("Failed to resolve eglQueryGlobalImageBRCM"); + return; + } - if (!d->eglQueryGlobalImageBRCM) { - qWarning("Failed to resolve eglQueryGlobalImageBRCM"); - return false; - } - - d->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + d->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - if (!d->glEGLImageTargetTexture2DOES) { - qWarning("Failed to resolve glEGLImageTargetTexture2DOES"); - return false; - } + if (!d->glEGLImageTargetTexture2DOES) { + qWarning("Failed to resolve glEGLImageTargetTexture2DOES"); + return; + } - d->eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); + d->eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); - if (!d->eglCreateImageKHR) { - qWarning("Failed to resolve eglCreateImageKHR"); - return false; - } + if (!d->eglCreateImageKHR) { + qWarning("Failed to resolve eglCreateImageKHR"); + return; + } - d->eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); + d->eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); - if (!d->eglDestroyImageKHR) { - qWarning("Failed to resolve eglDestroyImageKHR"); - return false; + if (!d->eglDestroyImageKHR) { + qWarning("Failed to resolve eglDestroyImageKHR"); + return; + } + d->valid = true; + init(display, 1); } - d->valid = true; - init(display, 1); - return true; } QtWayland::ClientBuffer *BrcmEglIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h index 4bc98e8c5..3728da7bc 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h @@ -47,7 +47,7 @@ class BrcmEglIntegration : public QtWayland::ClientBufferIntegration, public QtW public: BrcmEglIntegration(); - bool initializeHardware(struct ::wl_display *display) override; + void initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; protected: diff --git a/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri b/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri index 2df101092..41f483c48 100644 --- a/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri +++ b/src/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pri @@ -1,6 +1,6 @@ INCLUDEPATH += $$PWD -QMAKE_USE_PRIVATE += egl wayland-server +QMAKE_USE_PRIVATE += egl drm wayland-server SOURCES += \ $$PWD/dmabufserverbufferintegration.cpp diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri index a7630040e..4dbbae194 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linux-dmabuf-unstable-v1.pri @@ -1,6 +1,6 @@ INCLUDEPATH += $$PWD -QMAKE_USE_PRIVATE += egl wayland-server +QMAKE_USE_PRIVATE += egl drm wayland-server CONFIG += wayland-scanner WAYLANDSERVERSOURCES += $$PWD/../../../3rdparty/protocol/linux-dmabuf-unstable-v1.xml diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h index 8554721e1..56a710c3d 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h @@ -58,6 +58,12 @@ #define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED) #endif +// Copied from eglmesaext.h +#ifndef EGL_WL_bind_wayland_display +typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); +#endif + QT_BEGIN_NAMESPACE class QWaylandCompositor; diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp index 4f01f855e..101e29891 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp @@ -275,7 +275,7 @@ LinuxDmabufClientBufferIntegration::~LinuxDmabufClientBufferIntegration() m_importedBuffers.clear(); } -bool LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display *display) +void LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display *display) { m_linuxDmabuf.reset(new LinuxDmabuf(display, this)); @@ -286,40 +286,40 @@ bool LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display egl_query_dmabuf_formats_ext = reinterpret_cast<PFNEGLQUERYDMABUFFORMATSEXTPROC>(eglGetProcAddress("eglQueryDmaBufFormatsEXT")); if (!egl_query_dmabuf_modifiers_ext || !egl_query_dmabuf_formats_ext) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglQueryDmaBufModifiersEXT and eglQueryDmaBufFormatsEXT."; - return false; + return; } egl_bind_wayland_display = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL")); egl_unbind_wayland_display = reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL")); if ((!egl_bind_wayland_display || !egl_unbind_wayland_display) && !ignoreBindDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."; - return false; + return; } egl_create_image = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR")); egl_destroy_image = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR")); if (!egl_create_image || !egl_destroy_image) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR."; - return false; + return; } // initialize EGL display QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (!nativeInterface) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. No native platform interface available."; - return false; + return; } m_eglDisplay = nativeInterface->nativeResourceForIntegration("EglDisplay"); if (!m_eglDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not get EglDisplay for window."; - return false; + return; } const char *extensionString = eglQueryString(m_eglDisplay, EGL_EXTENSIONS); if (!extensionString || !strstr(extensionString, "EGL_EXT_image_dma_buf_import")) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. There is no EGL_EXT_image_dma_buf_import extension."; - return false; + return; } if (strstr(extensionString, "EGL_EXT_image_dma_buf_import_modifiers")) m_supportsDmabufModifiers = true; @@ -331,7 +331,7 @@ bool LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display qCWarning(qLcWaylandCompositorHardwareIntegration) << "Could not bind Wayland display. Ignoring."; } else { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not bind Wayland display."; - return false; + return; } } } @@ -342,7 +342,6 @@ bool LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display modifiers[format] = supportedDrmModifiers(format); } m_linuxDmabuf->setSupportedModifiers(modifiers); - return true; } QVector<uint32_t> LinuxDmabufClientBufferIntegration::supportedDrmFormats() diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h index 8909fa89f..cbbd4d9ba 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h @@ -67,7 +67,7 @@ public: LinuxDmabufClientBufferIntegration(); ~LinuxDmabufClientBufferIntegration() override; - bool initializeHardware(struct ::wl_display *display) override; + void initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *resource) override; bool importBuffer(wl_resource *resource, LinuxDmabufWlBuffer *linuxDmabufBuffer); void removeBuffer(wl_resource *resource); diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp index dd23f6f9c..a5ca47553 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp @@ -398,7 +398,7 @@ WaylandEglClientBufferIntegration::~WaylandEglClientBufferIntegration() } } -bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *display) +void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *display) { Q_D(WaylandEglClientBufferIntegration); @@ -408,21 +408,21 @@ bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di if (!nativeInterface) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. No native platform interface available."; - return false; + return; } d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); if (!d->egl_display) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not get EglDisplay for window."; - return false; + return; } const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS); if ((!extensionString || !strstr(extensionString, "EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension."; - return false; + return; } d->egl_bind_wayland_display = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL")); @@ -430,14 +430,14 @@ bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di if ((!d->egl_bind_wayland_display || !d->egl_unbind_wayland_display) && !ignoreBindDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."; - return false; + return; } d->egl_query_wayland_buffer = reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL_compat>(eglGetProcAddress("eglQueryWaylandBufferWL")); if (!d->egl_query_wayland_buffer) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL."; - return false; + return; } d->egl_create_image = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR")); @@ -445,7 +445,7 @@ bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di if (!d->egl_create_image || !d->egl_destroy_image) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR."; - return false; + return; } if (d->egl_bind_wayland_display && d->egl_unbind_wayland_display) { @@ -454,7 +454,7 @@ bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di if (!ignoreBindDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not bind Wayland display."; - return false; + return; } else { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Could not bind Wayland display. Ignoring."; } @@ -464,8 +464,6 @@ bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di d->funcs = new QEGLStreamConvenience; d->funcs->initialize(d->egl_display); - - return true; } QtWayland::ClientBuffer *WaylandEglClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h index 3b9959e2f..bbc0eafef 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h @@ -45,7 +45,7 @@ public: WaylandEglClientBufferIntegration(); ~WaylandEglClientBufferIntegration() override; - bool initializeHardware(struct ::wl_display *display) override; + void initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp index 6c031aa89..8285e18d4 100644 --- a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp @@ -298,7 +298,7 @@ void WaylandEglStreamClientBufferIntegration::attachEglStreamConsumer(struct ::w d->initEglStream(clientBuffer, wl_buffer); } -bool WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_display *display) +void WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_display *display) { Q_D(WaylandEglStreamClientBufferIntegration); @@ -307,32 +307,32 @@ bool WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_displ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (!nativeInterface) { qWarning("QtCompositor: Failed to initialize EGL display. No native platform interface available."); - return false; + return; } d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); if (!d->egl_display) { qWarning("QtCompositor: Failed to initialize EGL display. Could not get EglDisplay for window."); - return false; + return; } const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS); if ((!extensionString || !strstr(extensionString, "EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension."); - return false; + return; } d->egl_bind_wayland_display = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL")); d->egl_unbind_wayland_display = reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL")); if ((!d->egl_bind_wayland_display || !d->egl_unbind_wayland_display) && !ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."); - return false; + return; } d->egl_query_wayland_buffer = reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL_compat>(eglGetProcAddress("eglQueryWaylandBufferWL")); if (!d->egl_query_wayland_buffer) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL."); - return false; + return; } if (d->egl_bind_wayland_display && d->egl_unbind_wayland_display) { @@ -340,7 +340,7 @@ bool WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_displ if (!d->display_bound) { if (!ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. Could not bind Wayland display."); - return false; + return; } else { qWarning("QtCompositor: Could not bind Wayland display. Ignoring."); } @@ -351,12 +351,6 @@ bool WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_displ d->funcs = new QEGLStreamConvenience; d->funcs->initialize(d->egl_display); - if (!d->funcs->initialized) { - qWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize eglstreams API"; - return false; - } - - return true; } QtWayland::ClientBuffer *WaylandEglStreamClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h index 35d2c80d3..4c4cce257 100644 --- a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h @@ -44,7 +44,7 @@ public: WaylandEglStreamClientBufferIntegration(); ~WaylandEglStreamClientBufferIntegration() override; - bool initializeHardware(struct ::wl_display *display) override; + void initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp index 3c302c7f6..3cf51a8de 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp @@ -62,26 +62,20 @@ XCompositeEglClientBufferIntegration::XCompositeEglClientBufferIntegration() } -bool XCompositeEglClientBufferIntegration::initializeHardware(struct ::wl_display *) +void XCompositeEglClientBufferIntegration::initializeHardware(struct ::wl_display *) { QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (nativeInterface) { mDisplay = static_cast<Display *>(nativeInterface->nativeResourceForIntegration("Display")); - if (!mDisplay) { - qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not retrieve Display from platform integration"; - return false; - } + if (!mDisplay) + qFatal("could not retrieve Display from platform integration"); mEglDisplay = static_cast<EGLDisplay>(nativeInterface->nativeResourceForIntegration("EGLDisplay")); - if (!mEglDisplay) { - qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not retrieve EGLDisplay from platform integration"; - return false; - } + if (!mEglDisplay) + qFatal("could not retrieve EGLDisplay from platform integration"); } else { - qCWarning(qLcWaylandCompositorHardwareIntegration) << "Platform integration doesn't have native interface"; - return false; + qFatal("Platform integration doesn't have native interface"); } new XCompositeHandler(m_compositor, mDisplay); - return true; } QtWayland::ClientBuffer *XCompositeEglClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h index 2c3116df1..80ce88b5f 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h @@ -45,7 +45,7 @@ class XCompositeEglClientBufferIntegration : public QtWayland::ClientBufferInteg public: XCompositeEglClientBufferIntegration(); - bool initializeHardware(struct ::wl_display *display) override; + void initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; inline Display *xDisplay() const { return mDisplay; } inline EGLDisplay eglDisplay() const { return mEglDisplay; } diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp index db4390252..3c8fc9d04 100644 --- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp @@ -70,19 +70,16 @@ XCompositeGLXClientBufferIntegration::~XCompositeGLXClientBufferIntegration() delete mHandler; } -bool XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_display *) +void XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_display *) { qDebug() << "Initializing GLX integration"; QPlatformNativeInterface *nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); if (nativeInterface) { mDisplay = static_cast<Display *>(nativeInterface->nativeResourceForIntegration("Display")); - if (!mDisplay) { - qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not retrieve Display from platform integration"; - return false; - } + if (!mDisplay) + qFatal("could not retrieve Display from platform integration"); } else { - qCWarning(qLcWaylandCompositorHardwareIntegration) << "Platform integration doesn't have native interface"; - return false; + qFatal("Platform integration doesn't have native interface"); } mScreen = XDefaultScreen(mDisplay); @@ -93,8 +90,7 @@ bool XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_displa m_glxBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glContext->getProcAddress("glXBindTexImageEXT")); if (!m_glxBindTexImageEXT) { - qCWarning(qLcWaylandCompositorHardwareIntegration) << "Did not find glxBindTexImageExt, everything will FAIL!"; - return false; + qDebug() << "Did not find glxBindTexImageExt, everything will FAIL!"; } m_glxReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glContext->getProcAddress("glXReleaseTexImageEXT")); if (!m_glxReleaseTexImageEXT) { @@ -102,7 +98,6 @@ bool XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_displa } delete glContext; - return true; } QtWayland::ClientBuffer *XCompositeGLXClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h index 6763d5916..e783d41bf 100644 --- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h @@ -48,7 +48,7 @@ public: XCompositeGLXClientBufferIntegration(); ~XCompositeGLXClientBufferIntegration() override; - bool initializeHardware(struct ::wl_display *display) override; + void initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; inline Display *xDisplay() const { return mDisplay; } diff --git a/tests/auto/client/seatv5/tst_seatv5.cpp b/tests/auto/client/seatv5/tst_seatv5.cpp index 636f26081..e333082ec 100644 --- a/tests/auto/client/seatv5/tst_seatv5.cpp +++ b/tests/auto/client/seatv5/tst_seatv5.cpp @@ -71,6 +71,7 @@ private slots: void singleTapFloat(); void multiTouch(); void multiTouchUpAndMotionFrame(); + void tapAndMoveInSameFrame(); }; void tst_seatv5::bindsToSeat() @@ -586,5 +587,37 @@ void tst_seatv5::multiTouchUpAndMotionFrame() QVERIFY(window.m_events.empty()); } +void tst_seatv5::tapAndMoveInSameFrame() +{ + TouchWindow window; + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + exec([=] { + auto *t = touch(); + auto *c = client(); + + t->sendDown(xdgToplevel()->surface(), {32, 32}, 0); + t->sendMotion(c, {33, 33}, 0); + t->sendFrame(c); + + // Don't leave touch in a weird state + t->sendUp(c, 0); + t->sendFrame(c); + }); + + QTRY_VERIFY(!window.m_events.empty()); + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.type, QEvent::TouchBegin); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointPressed); + // Position isn't that important, we just want to make sure we actually get the pressed event + } + + // Make sure we eventually release + QTRY_VERIFY(!window.m_events.empty()); + QTRY_COMPARE(window.m_events.last().touchPoints.first().state(), Qt::TouchPointState::TouchPointReleased); +} + QCOMPOSITOR_TEST_MAIN(tst_seatv5) #include "tst_seatv5.moc" diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp index ac5c24988..2277bbb80 100644 --- a/tests/auto/client/xdgshell/tst_xdgshell.cpp +++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp @@ -46,6 +46,7 @@ private slots: void popup(); void tooltipOnPopup(); void switchPopups(); + void hidePopupParent(); void pongs(); void minMaxSize(); void windowGeometry(); @@ -219,8 +220,8 @@ void tst_xdgshell::popup() p->sendFrame(c); uint serial = p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); p->sendButton(c, BTN_LEFT, Pointer::button_state_released); - return serial; p->sendFrame(c); + return serial; }); QTRY_VERIFY(window.m_popup); @@ -429,6 +430,50 @@ void tst_xdgshell::switchPopups() QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); } +void tst_xdgshell::hidePopupParent() +{ + class Window : public QRasterWindow { + public: + void mousePressEvent(QMouseEvent *event) override + { + QRasterWindow::mousePressEvent(event); + m_popup.reset(new QRasterWindow); + m_popup->setTransientParent(this); + m_popup->setFlags(Qt::Popup); + m_popup->resize(100, 100); + m_popup->show(); + } + QScopedPointer<QRasterWindow> m_popup; + }; + 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(c, BTN_LEFT, Pointer::button_state_pressed); + p->sendButton(c, BTN_LEFT, Pointer::button_state_released); + p->sendFrame(c); + }); + QCOMPOSITOR_TRY_VERIFY(xdgPopup()); + exec([=] { + xdgPopup()->sendConfigure(QRect(100, 100, 100, 100)); + xdgPopup()->m_xdgSurface->sendConfigure(); + }); + QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); + + window.hide(); + QCOMPOSITOR_TRY_VERIFY(!xdgToplevel()); +} + void tst_xdgshell::pongs() { // Create and show a window to trigger shell integration initialzation, |