summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-09-27 14:30:08 +0200
committerLiang Qi <liang.qi@qt.io>2017-09-27 15:10:13 +0200
commitef69b4d772304efcc3b9141900f4e76642d4873b (patch)
treebe32cebe5d78f424fba33808966982312998a277 /src/client
parent064feb4fd76e6adbfcafe449d6ae7f52834c538a (diff)
parentffee1b3fb8c8e76d9317547376c8f13b0e17b494 (diff)
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
Diffstat (limited to 'src/client')
-rw-r--r--src/client/qwaylandintegration.cpp2
-rw-r--r--src/client/qwaylandscreen.cpp6
-rw-r--r--src/client/qwaylandscreen_p.h1
-rw-r--r--src/client/qwaylandwindow.cpp97
-rw-r--r--src/client/qwaylandwindow_p.h15
5 files changed, 106 insertions, 15 deletions
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 03aedd6b6..34845c639 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -359,7 +359,7 @@ void QWaylandIntegration::initializeServerBufferIntegration()
disableHardwareIntegration = disableHardwareIntegration || !mDisplay->hardwareIntegration();
if (disableHardwareIntegration) {
QByteArray serverBufferIntegrationName = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
- QString targetKey = QString::fromLocal8Bit(serverBufferIntegrationName);
+ targetKey = QString::fromLocal8Bit(serverBufferIntegrationName);
} else {
targetKey = mDisplay->hardwareIntegration()->serverBufferIntegration();
}
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index 2f90be813..b6336f2e6 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -185,6 +185,12 @@ QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
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)
{
if (!(flags & WL_OUTPUT_MODE_CURRENT))
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index 526c94878..674e1a913 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -102,6 +102,7 @@ public:
::wl_output *output() { return object(); }
static QWaylandScreen *waylandScreenFromWindow(QWindow *window);
+ static QWaylandScreen *fromWlOutput(::wl_output *output);
private:
void output_mode(uint32_t flags, int width, int height, int refresh) override;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index cd846c0ba..6d50b0d72 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -69,6 +69,8 @@
#include <QtCore/QDebug>
+#include <wayland-client-core.h>
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -78,15 +80,13 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = 0;
QWaylandWindow::QWaylandWindow(QWindow *window)
: QObject()
, QPlatformWindow(window)
- , mScreen(QWaylandScreen::waylandScreenFromWindow(window))
- , mDisplay(mScreen->display())
+ , mDisplay(waylandScreen()->display())
, mShellSurface(0)
, mSubSurfaceWindow(0)
, mWindowDecoration(0)
, mMouseEventsInContentArea(false)
, mMousePressedInContentArea(Qt::NoButton)
, mWaitingForFrameSync(false)
- , mFrameCallback(nullptr)
, mRequestResizeSent(false)
, mCanResize(true)
, mResizeDirty(false)
@@ -100,6 +100,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
{
static WId id = 1;
mWindowId = id++;
+ connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandWindow::handleScreenRemoved);
initializeWlSurface();
}
@@ -349,9 +350,31 @@ void QWaylandWindow::sendExposeEvent(const QRect &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)
{
if (visible) {
+ if (window()->type() == Qt::Popup)
+ activePopups << this;
initWindow();
mDisplay->flushRequests();
@@ -365,6 +388,8 @@ void QWaylandWindow::setVisible(bool visible)
// case 'this' will be deleted. When that happens, we must abort right away.
QPointer<QWaylandWindow> deleteGuard(this);
QWindowSystemInterface::flushWindowSystemEvents();
+ if (!deleteGuard.isNull() && window()->type() == Qt::Popup)
+ closePopups(this);
if (!deleteGuard.isNull())
reset();
}
@@ -480,14 +505,63 @@ void QWaylandWindow::requestResize()
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)
{
- mFrameCallback = nullptr;
+ if (mFrameCallback) {
+ wl_callback_destroy(mFrameCallback);
+ mFrameCallback = nullptr;
+ }
if (buffer) {
- auto callback = frame();
- wl_callback_add_listener(callback, &QWaylandWindow::callbackListener, this);
- mFrameCallback = callback;
+ mFrameCallback = frame();
+ wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
mWaitingForFrameSync = true;
buffer->setBusy();
@@ -530,8 +604,6 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uin
QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
self->mWaitingForFrameSync = false;
- wl_callback_destroy(callback);
- self->mFrameCallback.testAndSetRelaxed(callback, nullptr);
if (self->mUpdateRequested) {
QWindowPrivate *w = QWindowPrivate::get(self->window());
self->mUpdateRequested = false;
@@ -568,6 +640,11 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
return mSubSurfaceWindow;
}
+QWaylandScreen *QWaylandWindow::waylandScreen() const
+{
+ return static_cast<QWaylandScreen *>(QPlatformWindow::screen());
+}
+
void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
{
if (mDisplay->compositorVersion() < 2)
@@ -832,7 +909,7 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
#if QT_CONFIG(cursor)
void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor)
{
- device->setCursor(cursor, mScreen);
+ device->setCursor(cursor, waylandScreen());
}
void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device)
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 6e07ff1c7..4cebcd7af 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -53,7 +53,6 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QMutex>
-#include <QtCore/QAtomicPointer>
#include <QtGui/QIcon>
#include <QtCore/QVariant>
@@ -143,7 +142,7 @@ public:
QWaylandDisplay *display() const { return mDisplay; }
QWaylandShellSurface *shellSurface() const;
QWaylandSubSurface *subSurfaceWindow() const;
- QWaylandScreen *waylandScreen() const { return mScreen; }
+ QWaylandScreen *waylandScreen() const;
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
void setOrientationMask(Qt::ScreenOrientations mask);
@@ -210,7 +209,10 @@ public slots:
void requestResize();
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;
QWaylandShellSurface *mShellSurface;
QWaylandSubSurface *mSubSurfaceWindow;
@@ -222,7 +224,7 @@ protected:
WId mWindowId;
bool mWaitingForFrameSync;
- QAtomicPointer<struct wl_callback> mFrameCallback;
+ struct ::wl_callback *mFrameCallback = nullptr;
QWaitCondition mFrameSyncWait;
QMutex mResizeLock;
@@ -245,6 +247,9 @@ protected:
QWaylandShmBackingStore *mBackingStore;
+private slots:
+ void handleScreenRemoved(QScreen *qScreen);
+
private:
bool setWindowStateInternal(Qt::WindowStates flags);
void setGeometry_helper(const QRect &rect);
@@ -254,6 +259,8 @@ private:
bool shouldCreateSubSurface() const;
void reset(bool sendDestroyEvent = true);
void sendExposeEvent(const QRect &rect);
+ static void closePopups(QWaylandWindow *parent);
+ QWaylandScreen *calculateScreenFromSurfaceEvents() const;
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);