summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.12.333
-rw-r--r--src/3rdparty/protocol/qt_attribution.json2
-rw-r--r--src/client/qwaylanddisplay.cpp51
-rw-r--r--src/client/qwaylanddisplay_p.h9
-rw-r--r--src/client/qwaylandwindow.cpp198
-rw-r--r--src/client/qwaylandwindow_p.h17
-rw-r--r--src/compositor/compositor_api/compositor_api.pri1
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandtouch.cpp19
-rw-r--r--src/compositor/compositor_api/qwaylandtouch_p.h2
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc4
-rw-r--r--src/compositor/extensions/qwaylandshell.cpp20
-rw-r--r--src/compositor/extensions/qwaylandshell.h12
-rw-r--r--src/compositor/extensions/qwaylandwlshell_p.h3
-rw-r--r--src/compositor/extensions/qwaylandxdgshell_p.h3
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv5_p.h3
-rw-r--r--src/compositor/extensions/qwaylandxdgshellv6_p.h3
-rw-r--r--src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp25
-rw-r--r--src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp2
-rw-r--r--src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp2
-rw-r--r--src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp3
-rw-r--r--src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp13
22 files changed, 349 insertions, 78 deletions
diff --git a/dist/changes-5.12.3 b/dist/changes-5.12.3
new file mode 100644
index 000000000..da95edbb1
--- /dev/null
+++ b/dist/changes-5.12.3
@@ -0,0 +1,33 @@
+Qt 5.12.3 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.2.
+
+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.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+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.
+
+****************************************************************************
+* Compositor *
+****************************************************************************
+
+ - Fixed a slightly unusual cleanup order that would lead to crashes in some
+ graphics drivers.
+
+****************************************************************************
+* QPA plugin *
+****************************************************************************
+
+ - Fixed a bug where the window decoration's damaged area didn't cover the
+ entire decoration. This meant some compositors would not redraw those
+ areas.
diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json
index 7881e6b0d..051bd3f95 100644
--- a/src/3rdparty/protocol/qt_attribution.json
+++ b/src/3rdparty/protocol/qt_attribution.json
@@ -110,7 +110,7 @@ Copyright © 2015, 2016 Jan Arne Petersen"
"Name": "Wayland EGLStream Controller Protocol",
"QDocModule": "qtwaylandcompositor",
"QtUsage": "Used in the Qt Wayland Compositor",
- "Files": "wayland-eglstream-controller.xml",
+ "Files": "wl-eglstream-controller.xml",
"Description": "Allows clients to request that the compositor creates its EGLStream.",
"Homepage": "https://github.com/NVIDIA/egl-wayland",
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index a2957e0dd..82003a308 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -68,6 +68,8 @@
#include <QtWaylandClient/private/qwayland-text-input-unstable-v2.h>
+#include <QtCore/private/qcore_unix_p.h>
+
#include <QtCore/QAbstractEventDispatcher>
#include <QtGui/private/qguiapplication_p.h>
@@ -88,13 +90,6 @@ struct wl_surface *QWaylandDisplay::createSurface(void *handle)
return surface;
}
-QWaylandShellSurface *QWaylandDisplay::createShellSurface(QWaylandWindow *window)
-{
- if (!mWaylandIntegration->shellIntegration())
- return nullptr;
- return mWaylandIntegration->shellIntegration()->createShellSurface(window);
-}
-
struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
{
struct ::wl_region *region = mCompositor.create_region();
@@ -108,12 +103,18 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
::wl_subsurface *QWaylandDisplay::createSubSurface(QWaylandWindow *window, QWaylandWindow *parent)
{
if (!mSubCompositor) {
+ qCWarning(lcQpaWayland) << "Can't create subsurface, not supported by the compositor.";
return nullptr;
}
return mSubCompositor->get_subsurface(window->object(), parent->object());
}
+QWaylandShellIntegration *QWaylandDisplay::shellIntegration() const
+{
+ return mWaylandIntegration->shellIntegration();
+}
+
QWaylandClientBufferIntegration * QWaylandDisplay::clientBufferIntegration() const
{
return mWaylandIntegration->clientBufferIntegration();
@@ -191,7 +192,6 @@ void QWaylandDisplay::flushRequests()
wl_display_flush(mDisplay);
}
-
void QWaylandDisplay::blockingReadEvents()
{
if (wl_display_dispatch(mDisplay) < 0) {
@@ -205,6 +205,41 @@ void QWaylandDisplay::exitWithError()
::exit(1);
}
+wl_event_queue *QWaylandDisplay::createEventQueue()
+{
+ return wl_display_create_queue(mDisplay);
+}
+
+void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bool ()> condition, int timeout)
+{
+ if (!condition())
+ return;
+
+ QElapsedTimer timer;
+ timer.start();
+ struct pollfd pFd = qt_make_pollfd(wl_display_get_fd(mDisplay), POLLIN);
+ while (timeout == -1 || timer.elapsed() < timeout) {
+ while (wl_display_prepare_read_queue(mDisplay, queue) != 0)
+ wl_display_dispatch_queue_pending(mDisplay, queue);
+
+ wl_display_flush(mDisplay);
+
+ const int remaining = qMax(timeout - timer.elapsed(), 0ll);
+ const int pollTimeout = timeout == -1 ? -1 : remaining;
+ if (qt_poll_msecs(&pFd, 1, pollTimeout) > 0)
+ wl_display_read_events(mDisplay);
+ else
+ wl_display_cancel_read(mDisplay);
+
+ if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0) {
+ checkError();
+ exitWithError();
+ }
+ if (!condition())
+ break;
+ }
+}
+
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
{
for (int i = 0; i < mScreens.size(); ++i) {
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 43ccc0a96..6bf6abd5d 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -94,7 +94,7 @@ class QWaylandQtKeyExtension;
class QWaylandWindow;
class QWaylandIntegration;
class QWaylandHardwareIntegration;
-class QWaylandShellSurface;
+class QWaylandShellIntegration;
class QWaylandCursorTheme;
typedef void (*RegistryListener)(void *data,
@@ -115,13 +115,13 @@ public:
QWaylandScreen *screenForOutput(struct wl_output *output) const;
struct wl_surface *createSurface(void *handle);
- QWaylandShellSurface *createShellSurface(QWaylandWindow *window);
struct ::wl_region *createRegion(const QRegion &qregion);
struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
+ QWaylandShellIntegration *shellIntegration() const;
QWaylandClientBufferIntegration *clientBufferIntegration() const;
-
QWaylandWindowManagerIntegration *windowManagerIntegration() const;
+
#if QT_CONFIG(cursor)
void setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image, qreal dpr);
void setCursor(const QSharedPointer<QWaylandBuffer> &buffer, const QPoint &hotSpot, qreal dpr);
@@ -182,6 +182,9 @@ public:
void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
void handleWindowDestroyed(QWaylandWindow *window);
+ wl_event_queue *createEventQueue();
+ void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
+
public slots:
void blockingReadEvents();
void flushRequests();
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index c46c49813..58e0fc585 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -50,6 +50,7 @@
#include "qwaylandnativeinterface_p.h"
#include "qwaylanddecorationfactory_p.h"
#include "qwaylandshmbackingstore_p.h"
+#include "qwaylandshellintegration_p.h"
#if QT_CONFIG(wayland_datadevice)
#include "qwaylanddatadevice_p.h"
@@ -66,6 +67,7 @@
#include <QtGui/private/qwindow_p.h>
#include <QtCore/QDebug>
+#include <QtCore/QThread>
#include <wayland-client.h>
@@ -80,6 +82,7 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
QWaylandWindow::QWaylandWindow(QWindow *window)
: QPlatformWindow(window)
, mDisplay(waylandScreen()->display())
+ , mFrameQueue(mDisplay->createEventQueue())
, mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP"))
{
static WId id = 1;
@@ -138,8 +141,9 @@ void QWaylandWindow::initWindow()
}
} else if (shouldCreateShellSurface()) {
Q_ASSERT(!mShellSurface);
+ Q_ASSERT(mDisplay->shellIntegration());
- mShellSurface = mDisplay->createShellSurface(this);
+ mShellSurface = mDisplay->shellIntegration()->createShellSurface(this);
if (mShellSurface) {
// Set initial surface title
setWindowTitle(window()->title());
@@ -211,6 +215,9 @@ void QWaylandWindow::initializeWlSurface()
bool QWaylandWindow::shouldCreateShellSurface() const
{
+ if (!mDisplay->shellIntegration())
+ return false;
+
if (shouldCreateSubSurface())
return false;
@@ -358,6 +365,8 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
{
if (!(mShellSurface && mShellSurface->handleExpose(rect)))
QWindowSystemInterface::handleExposeEvent(window(), rect);
+ else
+ qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
mLastExposeGeometry = rect;
}
@@ -537,18 +546,11 @@ void QWaylandWindow::handleScreenRemoved(QScreen *qScreen)
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
{
Q_ASSERT(!buffer->committed());
- if (mFrameCallback) {
- wl_callback_destroy(mFrameCallback);
- mFrameCallback = nullptr;
- }
-
if (buffer) {
- mFrameCallback = frame();
- wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
- mWaitingForFrameSync = true;
+ handleUpdate();
buffer->setBusy();
- attach(buffer->buffer(), x, y);
+ QtWayland::wl_surface::attach(buffer->buffer(), x, y);
} else {
QtWayland::wl_surface::attach(nullptr, 0, 0);
}
@@ -604,32 +606,61 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
}
const wl_callback_listener QWaylandWindow::callbackListener = {
- QWaylandWindow::frameCallback
+ [](void *data, wl_callback *callback, uint32_t time) {
+ Q_UNUSED(callback);
+ Q_UNUSED(time);
+ auto *window = static_cast<QWaylandWindow*>(data);
+ if (window->thread() != QThread::currentThread())
+ QMetaObject::invokeMethod(window, [=] { window->handleFrameCallback(); }, Qt::QueuedConnection);
+ else
+ window->handleFrameCallback();
+ }
};
-void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uint32_t time)
+void QWaylandWindow::handleFrameCallback()
{
- Q_UNUSED(time);
- Q_UNUSED(callback);
- QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
+ bool wasExposed = isExposed();
- self->mWaitingForFrameSync = false;
- if (self->mUpdateRequested) {
- self->mUpdateRequested = false;
- self->deliverUpdateRequest();
+ if (mFrameCallbackTimerId != -1) {
+ killTimer(mFrameCallbackTimerId);
+ mFrameCallbackTimerId = -1;
}
+
+ mWaitingForFrameCallback = false;
+ mFrameCallbackTimedOut = false;
+
+ if (!wasExposed && isExposed())
+ sendExposeEvent(QRect(QPoint(), geometry().size()));
+ if (wasExposed && hasPendingUpdateRequest())
+ deliverUpdateRequest();
}
QMutex QWaylandWindow::mFrameSyncMutex;
-void QWaylandWindow::waitForFrameSync()
+bool QWaylandWindow::waitForFrameSync(int timeout)
{
QMutexLocker locker(&mFrameSyncMutex);
- if (!mWaitingForFrameSync)
- return;
- mDisplay->flushRequests();
- while (mWaitingForFrameSync)
- mDisplay->blockingReadEvents();
+ if (!mWaitingForFrameCallback)
+ return true;
+
+ wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(mFrameCallback), mFrameQueue);
+ mDisplay->dispatchQueueWhile(mFrameQueue, [&]() { return mWaitingForFrameCallback; }, timeout);
+
+ if (mWaitingForFrameCallback) {
+ qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
+ mFrameCallbackTimedOut = true;
+ mWaitingForUpdate = false;
+ sendExposeEvent(QRect());
+ }
+
+ // Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread
+ if (mFrameCallbackTimerId != -1) {
+ int id = mFrameCallbackTimerId;
+ mFrameCallbackTimerId = -1;
+ QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
+ }
+
+ return !mWaitingForFrameCallback;
}
QMargins QWaylandWindow::frameMargins() const
@@ -958,9 +989,19 @@ void QWaylandWindow::unfocus()
bool QWaylandWindow::isExposed() const
{
+ if (!window()->isVisible())
+ return false;
+
+ if (mFrameCallbackTimedOut)
+ return false;
+
if (mShellSurface)
- return window()->isVisible() && mShellSurface->isExposed();
- return QPlatformWindow::isExposed();
+ return mShellSurface->isExposed();
+
+ if (mSubSurfaceWindow)
+ return mSubSurfaceWindow->parent()->isExposed();
+
+ return !(shouldCreateShellSurface() || shouldCreateSubSurface());
}
bool QWaylandWindow::isActive() const
@@ -1029,12 +1070,107 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa
return m_properties.value(name, defaultValue);
}
+void QWaylandWindow::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == mFallbackUpdateTimerId) {
+ killTimer(mFallbackUpdateTimerId);
+ mFallbackUpdateTimerId = -1;
+ qCDebug(lcWaylandBackingstore) << "mFallbackUpdateTimer timed out";
+
+ if (!isExposed()) {
+ qCDebug(lcWaylandBackingstore) << "Fallback update timer: Window not exposed,"
+ << "not delivering update request.";
+ return;
+ }
+
+ if (mWaitingForUpdate && hasPendingUpdateRequest() && !mWaitingForFrameCallback) {
+ qCWarning(lcWaylandBackingstore) << "Delivering update request through fallback timer,"
+ << "may not be in sync with display";
+ deliverUpdateRequest();
+ }
+ }
+
+ if (event->timerId() == mFrameCallbackTimerId) {
+ killTimer(mFrameCallbackTimerId);
+ mFrameCallbackTimerId = -1;
+ qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
+ mFrameCallbackTimedOut = true;
+ mWaitingForUpdate = false;
+ sendExposeEvent(QRect());
+ }
+}
+
void QWaylandWindow::requestUpdate()
{
- if (!mWaitingForFrameSync)
- QPlatformWindow::requestUpdate();
- else
- mUpdateRequested = true;
+ Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
+
+ // If we have a frame callback all is good and will be taken care of there
+ if (mWaitingForFrameCallback)
+ return;
+
+ // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
+ if (mWaitingForUpdate) {
+ // Ideally, we should just have returned here, but we're not guaranteed that the client
+ // will actually update, so start this timer to deliver another request update after a while
+ // *IF* the client doesn't update.
+ int fallbackTimeout = 100;
+ mFallbackUpdateTimerId = startTimer(fallbackTimeout);
+ return;
+ }
+
+ // Some applications (such as Qt Quick) depend on updates being delivered asynchronously,
+ // so use invokeMethod to delay the delivery a bit.
+ QMetaObject::invokeMethod(this, [this] {
+ // Things might have changed in the meantime
+ if (hasPendingUpdateRequest() && !mWaitingForUpdate && !mWaitingForFrameCallback)
+ deliverUpdateRequest();
+ }, Qt::QueuedConnection);
+}
+
+// Should be called whenever we commit a buffer (directly through wl_surface.commit or indirectly
+// with eglSwapBuffers) to know when it's time to commit the next one.
+// Can be called from the render thread (without locking anything) so make sure to not make races in this method.
+void QWaylandWindow::handleUpdate()
+{
+ // TODO: Should sync subsurfaces avoid requesting frame callbacks?
+
+ if (mFrameCallback) {
+ wl_callback_destroy(mFrameCallback);
+ mFrameCallback = nullptr;
+ }
+
+ if (mFallbackUpdateTimerId != -1) {
+ // Ideally, we would stop the fallback timer here, but since we're on another thread,
+ // it's not allowed. Instead we set mFallbackUpdateTimer to -1 here, so we'll just
+ // ignore it if it times out before it's cleaned up by the invokeMethod call.
+ int id = mFallbackUpdateTimerId;
+ mFallbackUpdateTimerId = -1;
+ QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
+ }
+
+ mFrameCallback = frame();
+ wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
+ mWaitingForFrameCallback = true;
+ mWaitingForUpdate = false;
+
+ // Stop current frame timer if any, can't use killTimer directly, see comment above.
+ if (mFrameCallbackTimerId != -1) {
+ int id = mFrameCallbackTimerId;
+ mFrameCallbackTimerId = -1;
+ QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
+ }
+
+ // Start a timer for handling the case when the compositor stops sending frame callbacks.
+ QMetaObject::invokeMethod(this, [=] { // Again; can't do it directly
+ if (mWaitingForFrameCallback)
+ mFrameCallbackTimerId = startTimer(100);
+ }, Qt::QueuedConnection);
+}
+
+void QWaylandWindow::deliverUpdateRequest()
+{
+ mWaitingForUpdate = true;
+ QPlatformWindow::deliverUpdateRequest();
}
void QWaylandWindow::addAttachOffset(const QPoint point)
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 56ebd3cc6..c47123dc9 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -120,7 +120,7 @@ public:
void handleExpose(const QRegion &region);
void commit(QWaylandBuffer *buffer, const QRegion &damage);
- void waitForFrameSync();
+ bool waitForFrameSync(int timeout);
QMargins frameMargins() const override;
@@ -191,7 +191,10 @@ public:
bool startSystemMove(const QPoint &pos) override;
+ void timerEvent(QTimerEvent *event) override;
void requestUpdate() override;
+ void handleUpdate();
+ void deliverUpdateRequest() override;
public slots:
void applyConfigure();
@@ -211,10 +214,17 @@ protected:
Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
WId mWindowId;
- bool mWaitingForFrameSync = false;
+ bool mWaitingForFrameCallback = false;
+ bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
+ int mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
struct ::wl_callback *mFrameCallback = nullptr;
+ struct ::wl_event_queue *mFrameQueue = nullptr;
QWaitCondition mFrameSyncWait;
+ // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
+ bool mWaitingForUpdate = false;
+ int mFallbackUpdateTimerId = -1; // Started when waiting for app to commit
+
QMutex mResizeLock;
bool mWaitingToApplyConfigure = false;
bool mCanResize = true;
@@ -253,11 +263,10 @@ private:
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
void handleScreenChanged();
- bool mUpdateRequested = false;
QRect mLastExposeGeometry;
static const wl_callback_listener callbackListener;
- static void frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time);
+ void handleFrameCallback();
static QMutex mFrameSyncMutex;
static QWaylandWindow *mMouseGrab;
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 3df061459..8dbe12ac1 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -17,6 +17,7 @@ HEADERS += \
compositor_api/qwaylandtouch.h \
compositor_api/qwaylandtouch_p.h \
compositor_api/qwaylandoutput.h \
+ compositor_api/qwaylandoutput_p.h \
compositor_api/qwaylandoutputmode.h \
compositor_api/qwaylandoutputmode_p.h \
compositor_api/qwaylandbufferref.h \
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index a0d69c52e..52ffb9166 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -243,8 +243,10 @@ QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
delete data_device_manager;
#endif
+#if QT_CONFIG(opengl)
// Some client buffer integrations need to clean up before the destroying the wl_display
client_buffer_integration.reset();
+#endif
wl_display_destroy(display);
}
diff --git a/src/compositor/compositor_api/qwaylandtouch.cpp b/src/compositor/compositor_api/qwaylandtouch.cpp
index 3e7298001..15746cb5f 100644
--- a/src/compositor/compositor_api/qwaylandtouch.cpp
+++ b/src/compositor/compositor_api/qwaylandtouch.cpp
@@ -98,6 +98,20 @@ void QWaylandTouchPrivate::sendMotion(QWaylandClient *client, uint32_t time, int
wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y()));
}
+int QWaylandTouchPrivate::toSequentialWaylandId(int touchId)
+{
+ const int waylandId = ids.indexOf(touchId);
+ if (waylandId != -1)
+ return waylandId;
+ const int availableId = ids.indexOf(-1);
+ if (availableId != -1) {
+ ids[availableId] = touchId;
+ return availableId;
+ }
+ ids.append(touchId);
+ return ids.length() - 1;
+}
+
/*!
* \class QWaylandTouch
* \inmodule QtWaylandCompositor
@@ -212,7 +226,10 @@ void QWaylandTouch::sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *ev
for (int i = 0; i < pointCount; ++i) {
const QTouchEvent::TouchPoint &tp(points.at(i));
// Convert the local pos in the compositor window to surface-relative.
- sendTouchPointEvent(surface, tp.id(), tp.pos(), tp.state());
+ const int id = d->toSequentialWaylandId(tp.id());
+ sendTouchPointEvent(surface, id, tp.pos(), tp.state());
+ if (tp.state() == Qt::TouchPointReleased)
+ d->ids[id] = -1;
}
sendFrameEvent(surface->client());
}
diff --git a/src/compositor/compositor_api/qwaylandtouch_p.h b/src/compositor/compositor_api/qwaylandtouch_p.h
index de1b748de..0b87f8475 100644
--- a/src/compositor/compositor_api/qwaylandtouch_p.h
+++ b/src/compositor/compositor_api/qwaylandtouch_p.h
@@ -80,8 +80,10 @@ public:
private:
void touch_release(Resource *resource) override;
+ int toSequentialWaylandId(int touchId);
QWaylandSeat *seat = nullptr;
+ QVarLengthArray<int, 10> ids;
};
QT_END_NAMESPACE
diff --git a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
index 1dadb7102..454fc3711 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-qmltypes.qdoc
@@ -26,7 +26,7 @@
****************************************************************************/
/*!
- \qmlmodule QtWayland.Compositor 1.1
+ \qmlmodule QtWayland.Compositor 1.3
\title Qt Wayland Compositor QML Types
\ingroup qmlmodules
\brief Provides QML types for writing custom Wayland display servers.
@@ -38,7 +38,7 @@
import statement:
\code
- import QtWayland.Compositor 1.1
+ import QtWayland.Compositor 1.3
\endcode
To link against the module, add this line to your \l qmake \c .pro file:
diff --git a/src/compositor/extensions/qwaylandshell.cpp b/src/compositor/extensions/qwaylandshell.cpp
index 12479186b..bb3b4675c 100644
--- a/src/compositor/extensions/qwaylandshell.cpp
+++ b/src/compositor/extensions/qwaylandshell.cpp
@@ -92,4 +92,24 @@ void QWaylandShell::setFocusPolicy(QWaylandShell::FocusPolicy focusPolicy)
emit focusPolicyChanged();
}
+QWaylandShell::QWaylandShell(QWaylandShellPrivate &dd)
+ : QWaylandCompositorExtension(dd)
+{
+}
+
+QWaylandShell::QWaylandShell(QWaylandObject *container, QWaylandShellPrivate &dd)
+ : QWaylandCompositorExtension(container, dd)
+{
+}
+
+QWaylandShell::QWaylandShell(QWaylandCompositorExtensionPrivate &dd)
+ : QWaylandShell(static_cast<QWaylandShellPrivate &>(dd))
+{
+}
+
+QWaylandShell::QWaylandShell(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd)
+ : QWaylandShell(container, static_cast<QWaylandShellPrivate &>(dd))
+{
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandshell.h b/src/compositor/extensions/qwaylandshell.h
index a86938214..6f494be55 100644
--- a/src/compositor/extensions/qwaylandshell.h
+++ b/src/compositor/extensions/qwaylandshell.h
@@ -68,8 +68,12 @@ Q_SIGNALS:
void focusPolicyChanged();
protected:
- QWaylandShell(QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(dd) {}
- QWaylandShell(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(container, dd) {}
+ explicit QWaylandShell(QWaylandShellPrivate &dd);
+ explicit QWaylandShell(QWaylandObject *container, QWaylandShellPrivate &dd);
+
+ //Qt 6: remove
+ Q_DECL_DEPRECATED QWaylandShell(QWaylandCompositorExtensionPrivate &dd);
+ Q_DECL_DEPRECATED QWaylandShell(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd);
};
template <typename T>
@@ -96,11 +100,11 @@ public:
}
protected:
- QWaylandShellTemplate(QWaylandCompositorExtensionPrivate &dd)
+ QWaylandShellTemplate(QWaylandShellPrivate &dd)
: QWaylandShell(dd)
{ }
- QWaylandShellTemplate(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd)
+ QWaylandShellTemplate(QWaylandObject *container, QWaylandShellPrivate &dd)
: QWaylandShell(container,dd)
{ }
};
diff --git a/src/compositor/extensions/qwaylandwlshell_p.h b/src/compositor/extensions/qwaylandwlshell_p.h
index e8d568fce..b2beca169 100644
--- a/src/compositor/extensions/qwaylandwlshell_p.h
+++ b/src/compositor/extensions/qwaylandwlshell_p.h
@@ -43,6 +43,7 @@
#include <QtWaylandCompositor/qtwaylandcompositorglobal.h>
#include <QtWaylandCompositor/qwaylandsurface.h>
#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwaylandshell_p.h>
#include <QtWaylandCompositor/QWaylandWlShellSurface>
#include <QtWaylandCompositor/QWaylandSeat>
@@ -67,7 +68,7 @@
QT_BEGIN_NAMESPACE
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellPrivate
- : public QWaylandCompositorExtensionPrivate
+ : public QWaylandShellPrivate
, public QtWaylandServer::wl_shell
{
Q_DECLARE_PUBLIC(QWaylandWlShell)
diff --git a/src/compositor/extensions/qwaylandxdgshell_p.h b/src/compositor/extensions/qwaylandxdgshell_p.h
index 9d1140fbd..3223abf3a 100644
--- a/src/compositor/extensions/qwaylandxdgshell_p.h
+++ b/src/compositor/extensions/qwaylandxdgshell_p.h
@@ -38,6 +38,7 @@
#define QWAYLANDXDGSHELL_P_H
#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwaylandshell_p.h>
#include <QtWaylandCompositor/private/qwayland-server-xdg-shell.h>
#include <QtWaylandCompositor/QWaylandXdgShell>
@@ -73,7 +74,7 @@ struct Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPositionerData {
};
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellPrivate
- : public QWaylandCompositorExtensionPrivate
+ : public QWaylandShellPrivate
, public QtWaylandServer::xdg_wm_base
{
Q_DECLARE_PUBLIC(QWaylandXdgShell)
diff --git a/src/compositor/extensions/qwaylandxdgshellv5_p.h b/src/compositor/extensions/qwaylandxdgshellv5_p.h
index 681c4537b..8f5af746b 100644
--- a/src/compositor/extensions/qwaylandxdgshellv5_p.h
+++ b/src/compositor/extensions/qwaylandxdgshellv5_p.h
@@ -41,6 +41,7 @@
#define QWAYLANDXDGSHELLV5_P_H
#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwaylandshell_p.h>
#include <QtWaylandCompositor/private/qwayland-server-xdg-shell-unstable-v5_p.h>
#include <QtWaylandCompositor/QWaylandXdgShellV5>
@@ -61,7 +62,7 @@
QT_BEGIN_NAMESPACE
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellV5Private
- : public QWaylandCompositorExtensionPrivate
+ : public QWaylandShellPrivate
, public QtWaylandServer::xdg_shell_v5
{
Q_DECLARE_PUBLIC(QWaylandXdgShellV5)
diff --git a/src/compositor/extensions/qwaylandxdgshellv6_p.h b/src/compositor/extensions/qwaylandxdgshellv6_p.h
index adc25cb71..457bc2201 100644
--- a/src/compositor/extensions/qwaylandxdgshellv6_p.h
+++ b/src/compositor/extensions/qwaylandxdgshellv6_p.h
@@ -38,6 +38,7 @@
#define QWAYLANDXDGSHELLV6_P_H
#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwaylandshell_p.h>
#include <QtWaylandCompositor/private/qwayland-server-xdg-shell-unstable-v6.h>
#include <QtWaylandCompositor/QWaylandXdgShellV6>
@@ -71,7 +72,7 @@ struct Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPositionerV6Data {
};
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellV6Private
- : public QWaylandCompositorExtensionPrivate
+ : public QWaylandShellPrivate
, public QtWaylandServer::zxdg_shell_v6
{
Q_DECLARE_PUBLIC(QWaylandXdgShellV6)
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
index c9bd83752..6b9776e9c 100644
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
@@ -316,7 +316,9 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis
mSupportNonBlockingSwap = false;
}
if (!mSupportNonBlockingSwap) {
- qWarning() << "Non-blocking swap buffers not supported. Subsurface rendering can be affected.";
+ qWarning(lcQpaWayland) << "Non-blocking swap buffers not supported."
+ << "Subsurface rendering can be affected."
+ << "It may also cause the event loop to freeze in some situations";
}
updateGLFormat();
@@ -556,20 +558,15 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
m_blitter->blit(window);
}
-
- QWaylandSubSurface *sub = window->subSurfaceWindow();
- if (sub) {
- QMutexLocker l(sub->syncMutex());
-
- int si = (sub->isSync() && mSupportNonBlockingSwap) ? 0 : m_format.swapInterval();
-
- eglSwapInterval(m_eglDisplay, si);
- eglSwapBuffers(m_eglDisplay, eglSurface);
- } else {
- eglSwapInterval(m_eglDisplay, m_format.swapInterval());
- eglSwapBuffers(m_eglDisplay, eglSurface);
+ int swapInterval = mSupportNonBlockingSwap ? 0 : m_format.swapInterval();
+ eglSwapInterval(m_eglDisplay, swapInterval);
+ if (swapInterval == 0 && m_format.swapInterval() > 0) {
+ // Emulating a blocking swap
+ glFlush(); // Flush before waiting so we can swap more quickly when the frame event arrives
+ window->waitForFrameSync(100);
}
-
+ window->handleUpdate();
+ eglSwapBuffers(m_eglDisplay, eglSurface);
window->setCanResize(true);
}
diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp
index c07ad5342..a6fead95c 100644
--- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp
+++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp
@@ -65,7 +65,7 @@ void QWaylandXCompositeEGLContext::swapBuffers(QPlatformSurface *surface)
QSize size = w->geometry().size();
w->commit(w->buffer(), QRegion(0, 0, size.width(), size.height()));
- w->waitForFrameSync();
+ w->waitForFrameSync(100);
}
EGLSurface QWaylandXCompositeEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
diff --git a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp
index 33ae2e038..351887416 100644
--- a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp
+++ b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp
@@ -93,7 +93,7 @@ void QWaylandXCompositeGLXContext::swapBuffers(QPlatformSurface *surface)
glXSwapBuffers(m_display, w->xWindow());
w->commit(w->buffer(), QRegion(0, 0, size.width(), size.height()));
- w->waitForFrameSync();
+ w->waitForFrameSync(100);
}
QFunctionPointer QWaylandXCompositeGLXContext::getProcAddress(const char *procName)
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
index 4cbafbd71..3eda43d7c 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5.cpp
@@ -71,6 +71,9 @@ QWaylandXdgSurfaceV5 *QWaylandXdgShellV5::createXdgSurface(QWaylandWindow *windo
QWaylandXdgPopupV5 *QWaylandXdgShellV5::createXdgPopup(QWaylandWindow *window, QWaylandInputDevice *inputDevice)
{
QWaylandWindow *parentWindow = m_popups.empty() ? window->transientParent() : m_popups.last();
+ if (!parentWindow)
+ return nullptr;
+
::wl_surface *parentSurface = parentWindow->object();
if (m_popupSerial == 0)
diff --git a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
index 12cc95b15..410f27001 100644
--- a/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
+++ b/src/plugins/shellintegration/xdg-shell-v5/qwaylandxdgshellv5integration.cpp
@@ -73,10 +73,15 @@ bool QWaylandXdgShellV5Integration::initialize(QWaylandDisplay *display)
QWaylandShellSurface *QWaylandXdgShellV5Integration::createShellSurface(QWaylandWindow *window)
{
QWaylandInputDevice *inputDevice = window->display()->lastInputDevice();
- if (window->window()->type() == Qt::WindowType::Popup && inputDevice)
- return m_xdgShell->createXdgPopup(window, inputDevice);
- else
- return m_xdgShell->createXdgSurface(window);
+ if (window->window()->type() == Qt::WindowType::Popup && inputDevice) {
+ if (auto *popup = m_xdgShell->createXdgPopup(window, inputDevice))
+ return popup;
+
+ qWarning(lcQpaWayland) << "Failed to create xdg-popup v5 for window" << window->window()
+ << "falling back to creating an xdg-surface";
+ }
+
+ return m_xdgShell->createXdgSurface(window);
}
void QWaylandXdgShellV5Integration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) {