Merge remote-tracking branch 'origin/5.10' into dev
Conflicts: src/client/qwaylandwindow.cpp src/client/qwaylandwindow_p.h src/compositor/compositor_api/qwaylandpointer.cpp Change-Id: Icbc22a1ae3cdd9cde438742817d07fccf97f647b
This commit is contained in:
commit
bd668a31d6
@ -359,7 +359,7 @@ void QWaylandIntegration::initializeServerBufferIntegration()
|
|||||||
disableHardwareIntegration = disableHardwareIntegration || !mDisplay->hardwareIntegration();
|
disableHardwareIntegration = disableHardwareIntegration || !mDisplay->hardwareIntegration();
|
||||||
if (disableHardwareIntegration) {
|
if (disableHardwareIntegration) {
|
||||||
QByteArray serverBufferIntegrationName = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
|
QByteArray serverBufferIntegrationName = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
|
||||||
QString targetKey = QString::fromLocal8Bit(serverBufferIntegrationName);
|
targetKey = QString::fromLocal8Bit(serverBufferIntegrationName);
|
||||||
} else {
|
} else {
|
||||||
targetKey = mDisplay->hardwareIntegration()->serverBufferIntegration();
|
targetKey = mDisplay->hardwareIntegration()->serverBufferIntegration();
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,12 @@ QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
|
|||||||
return static_cast<QWaylandScreen *>(platformScreen);
|
return static_cast<QWaylandScreen *>(platformScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWaylandScreen *QWaylandScreen::fromWlOutput(::wl_output *output)
|
||||||
|
{
|
||||||
|
auto wlOutput = static_cast<QtWayland::wl_output *>(wl_output_get_user_data(output));
|
||||||
|
return static_cast<QWaylandScreen *>(wlOutput);
|
||||||
|
}
|
||||||
|
|
||||||
void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
|
void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
|
||||||
{
|
{
|
||||||
if (!(flags & WL_OUTPUT_MODE_CURRENT))
|
if (!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||||
|
@ -102,6 +102,7 @@ public:
|
|||||||
::wl_output *output() { return object(); }
|
::wl_output *output() { return object(); }
|
||||||
|
|
||||||
static QWaylandScreen *waylandScreenFromWindow(QWindow *window);
|
static QWaylandScreen *waylandScreenFromWindow(QWindow *window);
|
||||||
|
static QWaylandScreen *fromWlOutput(::wl_output *output);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void output_mode(uint32_t flags, int width, int height, int refresh) override;
|
void output_mode(uint32_t flags, int width, int height, int refresh) override;
|
||||||
|
@ -69,6 +69,8 @@
|
|||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
|
#include <wayland-client-core.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QtWaylandClient {
|
namespace QtWaylandClient {
|
||||||
@ -78,15 +80,13 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = 0;
|
|||||||
QWaylandWindow::QWaylandWindow(QWindow *window)
|
QWaylandWindow::QWaylandWindow(QWindow *window)
|
||||||
: QObject()
|
: QObject()
|
||||||
, QPlatformWindow(window)
|
, QPlatformWindow(window)
|
||||||
, mScreen(QWaylandScreen::waylandScreenFromWindow(window))
|
, mDisplay(waylandScreen()->display())
|
||||||
, mDisplay(mScreen->display())
|
|
||||||
, mShellSurface(0)
|
, mShellSurface(0)
|
||||||
, mSubSurfaceWindow(0)
|
, mSubSurfaceWindow(0)
|
||||||
, mWindowDecoration(0)
|
, mWindowDecoration(0)
|
||||||
, mMouseEventsInContentArea(false)
|
, mMouseEventsInContentArea(false)
|
||||||
, mMousePressedInContentArea(Qt::NoButton)
|
, mMousePressedInContentArea(Qt::NoButton)
|
||||||
, mWaitingForFrameSync(false)
|
, mWaitingForFrameSync(false)
|
||||||
, mFrameCallback(nullptr)
|
|
||||||
, mRequestResizeSent(false)
|
, mRequestResizeSent(false)
|
||||||
, mCanResize(true)
|
, mCanResize(true)
|
||||||
, mResizeDirty(false)
|
, mResizeDirty(false)
|
||||||
@ -100,6 +100,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
|
|||||||
{
|
{
|
||||||
static WId id = 1;
|
static WId id = 1;
|
||||||
mWindowId = id++;
|
mWindowId = id++;
|
||||||
|
connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandWindow::handleScreenRemoved);
|
||||||
initializeWlSurface();
|
initializeWlSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,9 +350,31 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
|
|||||||
QWindowSystemInterface::handleExposeEvent(window(), rect);
|
QWindowSystemInterface::handleExposeEvent(window(), rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static QVector<QPointer<QWaylandWindow>> activePopups;
|
||||||
|
|
||||||
|
void QWaylandWindow::closePopups(QWaylandWindow *parent)
|
||||||
|
{
|
||||||
|
while (!activePopups.isEmpty()) {
|
||||||
|
auto popup = activePopups.takeLast();
|
||||||
|
if (popup.isNull())
|
||||||
|
continue;
|
||||||
|
if (popup.data() == parent)
|
||||||
|
return;
|
||||||
|
popup->reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
|
||||||
|
{
|
||||||
|
return mScreens.isEmpty() ? waylandScreen() : mScreens.first();
|
||||||
|
}
|
||||||
|
|
||||||
void QWaylandWindow::setVisible(bool visible)
|
void QWaylandWindow::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
if (window()->type() == Qt::Popup)
|
||||||
|
activePopups << this;
|
||||||
initWindow();
|
initWindow();
|
||||||
mDisplay->flushRequests();
|
mDisplay->flushRequests();
|
||||||
|
|
||||||
@ -365,6 +388,8 @@ void QWaylandWindow::setVisible(bool visible)
|
|||||||
// case 'this' will be deleted. When that happens, we must abort right away.
|
// case 'this' will be deleted. When that happens, we must abort right away.
|
||||||
QPointer<QWaylandWindow> deleteGuard(this);
|
QPointer<QWaylandWindow> deleteGuard(this);
|
||||||
QWindowSystemInterface::flushWindowSystemEvents();
|
QWindowSystemInterface::flushWindowSystemEvents();
|
||||||
|
if (!deleteGuard.isNull() && window()->type() == Qt::Popup)
|
||||||
|
closePopups(this);
|
||||||
if (!deleteGuard.isNull())
|
if (!deleteGuard.isNull())
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
@ -480,14 +505,63 @@ void QWaylandWindow::requestResize()
|
|||||||
QWindowSystemInterface::flushWindowSystemEvents();
|
QWindowSystemInterface::flushWindowSystemEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWaylandWindow::surface_enter(wl_output *output)
|
||||||
|
{
|
||||||
|
QWaylandScreen *oldScreen = calculateScreenFromSurfaceEvents();
|
||||||
|
auto addedScreen = QWaylandScreen::fromWlOutput(output);
|
||||||
|
|
||||||
|
if (mScreens.contains(addedScreen)) {
|
||||||
|
qWarning() << "Unexpected wl_surface.enter received for output with id:"
|
||||||
|
<< wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output))
|
||||||
|
<< "screen name:" << addedScreen->name() << "screen model:" << addedScreen->model();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mScreens.append(addedScreen);
|
||||||
|
|
||||||
|
QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
|
||||||
|
if (oldScreen != newScreen) //currently this will only happen if the first wl_surface.enter is for a non-primary screen
|
||||||
|
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWaylandWindow::surface_leave(wl_output *output)
|
||||||
|
{
|
||||||
|
QWaylandScreen *oldScreen = calculateScreenFromSurfaceEvents();
|
||||||
|
auto *removedScreen = QWaylandScreen::fromWlOutput(output);
|
||||||
|
bool wasRemoved = mScreens.removeOne(removedScreen);
|
||||||
|
if (!wasRemoved) {
|
||||||
|
qWarning() << "Unexpected wl_surface.leave received for output with id:"
|
||||||
|
<< wl_proxy_get_id(reinterpret_cast<wl_proxy *>(output))
|
||||||
|
<< "screen name:" << removedScreen->name() << "screen model:" << removedScreen->model();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
|
||||||
|
if (oldScreen != newScreen)
|
||||||
|
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWaylandWindow::handleScreenRemoved(QScreen *qScreen)
|
||||||
|
{
|
||||||
|
QWaylandScreen *oldScreen = calculateScreenFromSurfaceEvents();
|
||||||
|
bool wasRemoved = mScreens.removeOne(static_cast<QWaylandScreen *>(qScreen->handle()));
|
||||||
|
if (wasRemoved) {
|
||||||
|
QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents();
|
||||||
|
if (oldScreen != newScreen)
|
||||||
|
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
|
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
|
||||||
{
|
{
|
||||||
mFrameCallback = nullptr;
|
if (mFrameCallback) {
|
||||||
|
wl_callback_destroy(mFrameCallback);
|
||||||
|
mFrameCallback = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
auto callback = frame();
|
mFrameCallback = frame();
|
||||||
wl_callback_add_listener(callback, &QWaylandWindow::callbackListener, this);
|
wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
|
||||||
mFrameCallback = callback;
|
|
||||||
mWaitingForFrameSync = true;
|
mWaitingForFrameSync = true;
|
||||||
buffer->setBusy();
|
buffer->setBusy();
|
||||||
|
|
||||||
@ -530,8 +604,6 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uin
|
|||||||
QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
|
QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
|
||||||
|
|
||||||
self->mWaitingForFrameSync = false;
|
self->mWaitingForFrameSync = false;
|
||||||
wl_callback_destroy(callback);
|
|
||||||
self->mFrameCallback.testAndSetRelaxed(callback, nullptr);
|
|
||||||
if (self->mUpdateRequested) {
|
if (self->mUpdateRequested) {
|
||||||
QWindowPrivate *w = QWindowPrivate::get(self->window());
|
QWindowPrivate *w = QWindowPrivate::get(self->window());
|
||||||
self->mUpdateRequested = false;
|
self->mUpdateRequested = false;
|
||||||
@ -568,6 +640,11 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
|
|||||||
return mSubSurfaceWindow;
|
return mSubSurfaceWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWaylandScreen *QWaylandWindow::waylandScreen() const
|
||||||
|
{
|
||||||
|
return static_cast<QWaylandScreen *>(QPlatformWindow::screen());
|
||||||
|
}
|
||||||
|
|
||||||
void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
|
void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
|
||||||
{
|
{
|
||||||
if (mDisplay->compositorVersion() < 2)
|
if (mDisplay->compositorVersion() < 2)
|
||||||
@ -832,7 +909,7 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
|
|||||||
#if QT_CONFIG(cursor)
|
#if QT_CONFIG(cursor)
|
||||||
void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor)
|
void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor)
|
||||||
{
|
{
|
||||||
device->setCursor(cursor, mScreen);
|
device->setCursor(cursor, waylandScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
|
void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
|
|
||||||
#include <QtCore/QWaitCondition>
|
#include <QtCore/QWaitCondition>
|
||||||
#include <QtCore/QMutex>
|
#include <QtCore/QMutex>
|
||||||
#include <QtCore/QAtomicPointer>
|
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
|
|
||||||
@ -143,7 +142,7 @@ public:
|
|||||||
QWaylandDisplay *display() const { return mDisplay; }
|
QWaylandDisplay *display() const { return mDisplay; }
|
||||||
QWaylandShellSurface *shellSurface() const;
|
QWaylandShellSurface *shellSurface() const;
|
||||||
QWaylandSubSurface *subSurfaceWindow() const;
|
QWaylandSubSurface *subSurfaceWindow() const;
|
||||||
QWaylandScreen *waylandScreen() const { return mScreen; }
|
QWaylandScreen *waylandScreen() const;
|
||||||
|
|
||||||
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
|
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
|
||||||
void setOrientationMask(Qt::ScreenOrientations mask);
|
void setOrientationMask(Qt::ScreenOrientations mask);
|
||||||
@ -210,7 +209,10 @@ public slots:
|
|||||||
void requestResize();
|
void requestResize();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QWaylandScreen *mScreen;
|
void surface_enter(struct ::wl_output *output) override;
|
||||||
|
void surface_leave(struct ::wl_output *output) override;
|
||||||
|
|
||||||
|
QVector<QWaylandScreen *> mScreens; //As seen by wl_surface.enter/leave events. Chronological order.
|
||||||
QWaylandDisplay *mDisplay;
|
QWaylandDisplay *mDisplay;
|
||||||
QWaylandShellSurface *mShellSurface;
|
QWaylandShellSurface *mShellSurface;
|
||||||
QWaylandSubSurface *mSubSurfaceWindow;
|
QWaylandSubSurface *mSubSurfaceWindow;
|
||||||
@ -222,7 +224,7 @@ protected:
|
|||||||
|
|
||||||
WId mWindowId;
|
WId mWindowId;
|
||||||
bool mWaitingForFrameSync;
|
bool mWaitingForFrameSync;
|
||||||
QAtomicPointer<struct wl_callback> mFrameCallback;
|
struct ::wl_callback *mFrameCallback = nullptr;
|
||||||
QWaitCondition mFrameSyncWait;
|
QWaitCondition mFrameSyncWait;
|
||||||
|
|
||||||
QMutex mResizeLock;
|
QMutex mResizeLock;
|
||||||
@ -245,6 +247,9 @@ protected:
|
|||||||
|
|
||||||
QWaylandShmBackingStore *mBackingStore;
|
QWaylandShmBackingStore *mBackingStore;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleScreenRemoved(QScreen *qScreen);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool setWindowStateInternal(Qt::WindowStates flags);
|
bool setWindowStateInternal(Qt::WindowStates flags);
|
||||||
void setGeometry_helper(const QRect &rect);
|
void setGeometry_helper(const QRect &rect);
|
||||||
@ -254,6 +259,8 @@ private:
|
|||||||
bool shouldCreateSubSurface() const;
|
bool shouldCreateSubSurface() const;
|
||||||
void reset(bool sendDestroyEvent = true);
|
void reset(bool sendDestroyEvent = true);
|
||||||
void sendExposeEvent(const QRect &rect);
|
void sendExposeEvent(const QRect &rect);
|
||||||
|
static void closePopups(QWaylandWindow *parent);
|
||||||
|
QWaylandScreen *calculateScreenFromSurfaceEvents() const;
|
||||||
|
|
||||||
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ private slots:
|
|||||||
void backingStore();
|
void backingStore();
|
||||||
void touchDrag();
|
void touchDrag();
|
||||||
void mouseDrag();
|
void mouseDrag();
|
||||||
|
void dontCrashOnMultipleCommits();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MockCompositor *compositor;
|
MockCompositor *compositor;
|
||||||
@ -333,6 +334,32 @@ void tst_WaylandClient::mouseDrag()
|
|||||||
QTRY_VERIFY(window.dragStarted);
|
QTRY_VERIFY(window.dragStarted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_WaylandClient::dontCrashOnMultipleCommits()
|
||||||
|
{
|
||||||
|
auto window = new TestWindow();
|
||||||
|
window->show();
|
||||||
|
|
||||||
|
QRect rect(QPoint(), window->size());
|
||||||
|
|
||||||
|
QBackingStore backingStore(window);
|
||||||
|
backingStore.resize(rect.size());
|
||||||
|
backingStore.beginPaint(rect);
|
||||||
|
QPainter p(backingStore.paintDevice());
|
||||||
|
p.fillRect(rect, Qt::magenta);
|
||||||
|
p.end();
|
||||||
|
backingStore.endPaint();
|
||||||
|
|
||||||
|
backingStore.flush(rect);
|
||||||
|
backingStore.flush(rect);
|
||||||
|
backingStore.flush(rect);
|
||||||
|
|
||||||
|
compositor->processWaylandEvents();
|
||||||
|
|
||||||
|
delete window;
|
||||||
|
|
||||||
|
QTRY_VERIFY(!compositor->surface());
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
setenv("XDG_RUNTIME_DIR", ".", 1);
|
setenv("XDG_RUNTIME_DIR", ".", 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user