summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authorJiDe Zhang <zhangjide@uniontech.com>2023-09-20 16:59:57 +0800
committerJiDe Zhang <zhangjide@uniontech.com>2023-11-02 19:03:07 +0800
commit67c470b1ede30ad85048b0b73b7e37cd12e26df5 (patch)
tree5cd74335fbce3a8e561368947881c85c67c5b9da /src/client
parent82006cb686ac87b40d6b5ce5ec04c7e24e6fc4e0 (diff)
QWaylandSurface: client support wl_surface version 6
Add QWaylandWindow::updateScale() function to update the window's scale from QWaylandFractionalScale or QWaylandSurface::preferredBufferScale or QWaylandScreen::scale or QWaylandSurface::preferredBufferScale. Add QWaylandWindow::updateBufferTransform() function to update the window's buffer transform from QScreen::primaryOrientation or QWaylandSurface::preferredBufferTransform. Change-Id: I2742701e92c7403a89df97b7fa06b5b0de6917a7 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: David Edmundson <davidedmundson@kde.org>
Diffstat (limited to 'src/client')
-rw-r--r--src/client/qwaylanddisplay.cpp2
-rw-r--r--src/client/qwaylandfractionalscale.cpp2
-rw-r--r--src/client/qwaylandfractionalscale_p.h4
-rw-r--r--src/client/qwaylandscreen.cpp55
-rw-r--r--src/client/qwaylandscreen_p.h3
-rw-r--r--src/client/qwaylandsurface.cpp16
-rw-r--r--src/client/qwaylandsurface_p.h8
-rw-r--r--src/client/qwaylandwindow.cpp87
-rw-r--r--src/client/qwaylandwindow_p.h4
9 files changed, 131 insertions, 50 deletions
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index 1c399765e..e5a1ed647 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -618,7 +618,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
if (interface == QLatin1String(QtWayland::wl_output::interface()->name)) {
mWaitingScreens << mWaylandIntegration->createPlatformScreen(this, version, id);
} else if (interface == QLatin1String(QtWayland::wl_compositor::interface()->name)) {
- mCompositor.init(registry, id, qMin((int)version, 4));
+ mCompositor.init(registry, id, qMin((int)version, 6));
} else if (interface == QLatin1String(QWaylandShm::interface()->name)) {
mShm.reset(new QWaylandShm(this, version, id));
} else if (interface == QLatin1String(QWaylandInputDevice::interface()->name)) {
diff --git a/src/client/qwaylandfractionalscale.cpp b/src/client/qwaylandfractionalscale.cpp
index 34169670f..6cd933f47 100644
--- a/src/client/qwaylandfractionalscale.cpp
+++ b/src/client/qwaylandfractionalscale.cpp
@@ -22,7 +22,7 @@ void QWaylandFractionalScale::wp_fractional_scale_v1_preferred_scale(uint scale)
qreal preferredScale = scale / 120.0; // hardcoded denominator determined in the spec
if (preferredScale != mPreferredScale) {
mPreferredScale = preferredScale;
- Q_EMIT preferredScaleChanged(preferredScale);
+ Q_EMIT preferredScaleChanged();
}
}
diff --git a/src/client/qwaylandfractionalscale_p.h b/src/client/qwaylandfractionalscale_p.h
index c030e60dd..48e1fb487 100644
--- a/src/client/qwaylandfractionalscale_p.h
+++ b/src/client/qwaylandfractionalscale_p.h
@@ -33,8 +33,10 @@ public:
explicit QWaylandFractionalScale(struct ::wp_fractional_scale_v1 *object);
~QWaylandFractionalScale();
+ std::optional<qreal> preferredScale() const { return mPreferredScale; }
+
Q_SIGNALS:
- void preferredScaleChanged(qreal preferredScale);
+ void preferredScaleChanged();
protected:
void wp_fractional_scale_v1_preferred_scale(uint scale) override;
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index 7c4f1bdf2..64fd55c0c 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -205,6 +205,35 @@ QWaylandScreen *QWaylandScreen::fromWlOutput(::wl_output *output)
return nullptr;
}
+Qt::ScreenOrientation QWaylandScreen::toScreenOrientation(int wlTransform,
+ Qt::ScreenOrientation fallback) const
+{
+ auto orientation = fallback;
+ bool isPortrait = mGeometry.height() > mGeometry.width();
+ switch (wlTransform) {
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation;
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation;
+ break;
+ // Ignore these ones, at least for now
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ break;
+ }
+
+ return orientation;
+}
+
void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
{
if (!(flags & WL_OUTPUT_MODE_CURRENT))
@@ -257,29 +286,11 @@ void QWaylandScreen::output_done()
void QWaylandScreen::updateOutputProperties()
{
if (mTransform >= 0) {
- bool isPortrait = mGeometry.height() > mGeometry.width();
- switch (mTransform) {
- case WL_OUTPUT_TRANSFORM_NORMAL:
- m_orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation;
- break;
- case WL_OUTPUT_TRANSFORM_90:
- m_orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation;
- break;
- case WL_OUTPUT_TRANSFORM_180:
- m_orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation;
- break;
- case WL_OUTPUT_TRANSFORM_270:
- m_orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation;
- break;
- // Ignore these ones, at least for now
- case WL_OUTPUT_TRANSFORM_FLIPPED:
- case WL_OUTPUT_TRANSFORM_FLIPPED_90:
- case WL_OUTPUT_TRANSFORM_FLIPPED_180:
- case WL_OUTPUT_TRANSFORM_FLIPPED_270:
- break;
+ auto newOrientation = toScreenOrientation(mTransform, m_orientation);
+ if (m_orientation != newOrientation) {
+ m_orientation = newOrientation;
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
}
-
- QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
mTransform = -1;
}
diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h
index 4499f0eef..4bc2531f6 100644
--- a/src/client/qwaylandscreen_p.h
+++ b/src/client/qwaylandscreen_p.h
@@ -82,6 +82,9 @@ public:
static QWaylandScreen *waylandScreenFromWindow(QWindow *window);
static QWaylandScreen *fromWlOutput(::wl_output *output);
+ Qt::ScreenOrientation toScreenOrientation(int wlTransform,
+ Qt::ScreenOrientation fallback) const;
+
protected:
enum Event : uint {
XdgOutputDoneEvent = 0x1,
diff --git a/src/client/qwaylandsurface.cpp b/src/client/qwaylandsurface.cpp
index cd1a561ba..949d7b160 100644
--- a/src/client/qwaylandsurface.cpp
+++ b/src/client/qwaylandsurface.cpp
@@ -85,6 +85,22 @@ void QWaylandSurface::surface_leave(wl_output *output)
emit screensChanged();
}
+void QWaylandSurface::surface_preferred_buffer_scale(int32_t scale)
+{
+ if (m_preferredBufferScale == scale)
+ return;
+ m_preferredBufferScale = scale;
+ Q_EMIT preferredBufferScaleChanged();
+}
+
+void QWaylandSurface::surface_preferred_buffer_transform(uint32_t transform)
+{
+ if (m_preferredBufferTransform == transform)
+ return;
+ m_preferredBufferTransform = static_cast<wl_output_transform>(transform);
+ Q_EMIT preferredBufferTransformChanged();
+}
+
} // namespace QtWaylandClient
QT_END_NAMESPACE
diff --git a/src/client/qwaylandsurface_p.h b/src/client/qwaylandsurface_p.h
index 027c6ca4d..657f4ad43 100644
--- a/src/client/qwaylandsurface_p.h
+++ b/src/client/qwaylandsurface_p.h
@@ -36,11 +36,15 @@ public:
~QWaylandSurface() override;
QWaylandScreen *oldestEnteredScreen();
QWaylandWindow *waylandWindow() const { return m_window; }
+ std::optional<int32_t> preferredBufferScale() const { return m_preferredBufferScale; }
+ std::optional<wl_output_transform> preferredBufferTransform() const { return m_preferredBufferTransform; }
static QWaylandSurface *fromWlSurface(::wl_surface *surface);
signals:
void screensChanged();
+ void preferredBufferScaleChanged();
+ void preferredBufferTransformChanged();
private slots:
void handleScreenRemoved(QScreen *qScreen);
@@ -48,9 +52,13 @@ private slots:
protected:
void surface_enter(struct ::wl_output *output) override;
void surface_leave(struct ::wl_output *output) override;
+ void surface_preferred_buffer_scale(int32_t scale) override;
+ void surface_preferred_buffer_transform(uint32_t transform) override;
QList<QWaylandScreen *> m_screens; //As seen by wl_surface.enter/leave events. Chronological order.
QWaylandWindow *m_window = nullptr;
+ std::optional<int32_t> m_preferredBufferScale;
+ std::optional<wl_output_transform> m_preferredBufferTransform;
friend class QWaylandWindow; // TODO: shouldn't need to be friends
};
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 9991ade4f..87e75a5ad 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -105,11 +105,8 @@ void QWaylandWindow::initWindow()
if (mDisplay->fractionalScaleManager() && qApp->highDpiScaleFactorRoundingPolicy() == Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) {
mFractionalScale.reset(new QWaylandFractionalScale(mDisplay->fractionalScaleManager()->get_fractional_scale(mSurface->object())));
- connect(mFractionalScale.data(), &QWaylandFractionalScale::preferredScaleChanged, this, [this](qreal preferredScale) {
- preferredScale = std::max(1.0, preferredScale);
- Q_ASSERT(mViewport);
- setScale(preferredScale);
- });
+ connect(mFractionalScale.data(), &QWaylandFractionalScale::preferredScaleChanged,
+ this, &QWaylandWindow::updateScale);
}
if (shouldCreateSubSurface()) {
@@ -209,6 +206,10 @@ void QWaylandWindow::initializeWlSurface()
mSurface.reset(new QWaylandSurface(mDisplay));
connect(mSurface.data(), &QWaylandSurface::screensChanged,
this, &QWaylandWindow::handleScreensChanged);
+ connect(mSurface.data(), &QWaylandSurface::preferredBufferScaleChanged,
+ this, &QWaylandWindow::updateScale);
+ connect(mSurface.data(), &QWaylandSurface::preferredBufferTransformChanged,
+ this, &QWaylandWindow::updateBufferTransform);
mSurface->m_window = this;
}
emit wlSurfaceCreated();
@@ -942,30 +943,48 @@ QWaylandScreen *QWaylandWindow::waylandScreen() const
void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
{
+ mLastReportedContentOrientation = orientation;
+ updateBufferTransform();
+}
+
+void QWaylandWindow::updateBufferTransform()
+{
QReadLocker locker(&mSurfaceLock);
if (mSurface == nullptr || mSurface->version() < 2)
return;
wl_output_transform transform;
- bool isPortrait = window()->screen() && window()->screen()->primaryOrientation() == Qt::PortraitOrientation;
- switch (orientation) {
- case Qt::PrimaryOrientation:
- transform = WL_OUTPUT_TRANSFORM_NORMAL;
- break;
- case Qt::LandscapeOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_270 : WL_OUTPUT_TRANSFORM_NORMAL;
- break;
- case Qt::PortraitOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_90;
- break;
- case Qt::InvertedLandscapeOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_90 : WL_OUTPUT_TRANSFORM_180;
- break;
- case Qt::InvertedPortraitOrientation:
- transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
- break;
- default:
- Q_UNREACHABLE();
+ Qt::ScreenOrientation screenOrientation = Qt::PrimaryOrientation;
+
+ if (mSurface->version() >= 6) {
+ const auto transform = mSurface->preferredBufferTransform().value_or(WL_OUTPUT_TRANSFORM_NORMAL);
+ if (auto screen = waylandScreen())
+ screenOrientation = screen->toScreenOrientation(transform, Qt::PrimaryOrientation);
+ } else {
+ if (auto screen = window()->screen())
+ screenOrientation = screen->primaryOrientation();
+ }
+
+ const bool isPortrait = (screenOrientation == Qt::PortraitOrientation);
+
+ switch (mLastReportedContentOrientation) {
+ case Qt::PrimaryOrientation:
+ transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ break;
+ case Qt::LandscapeOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_270 : WL_OUTPUT_TRANSFORM_NORMAL;
+ break;
+ case Qt::PortraitOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_NORMAL : WL_OUTPUT_TRANSFORM_90;
+ break;
+ case Qt::InvertedLandscapeOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_90 : WL_OUTPUT_TRANSFORM_180;
+ break;
+ case Qt::InvertedPortraitOrientation:
+ transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270;
+ break;
+ default:
+ Q_UNREACHABLE();
}
mSurface->set_buffer_transform(transform);
}
@@ -1379,8 +1398,26 @@ void QWaylandWindow::handleScreensChanged()
setGeometry(geometry);
}
- if (mFractionalScale)
+ updateScale();
+ updateBufferTransform();
+}
+
+void QWaylandWindow::updateScale()
+{
+ if (mFractionalScale) {
+ auto preferredScale = mFractionalScale->preferredScale().value_or(1.0);
+ preferredScale = std::max(1.0, preferredScale);
+ Q_ASSERT(mViewport);
+ setScale(preferredScale);
+ return;
+ }
+
+ if (mSurface && mSurface->version() >= 6) {
+ auto preferredScale = mSurface->preferredBufferScale().value_or(1);
+ preferredScale = std::max(1, preferredScale);
+ setScale(preferredScale);
return;
+ }
int scale = mLastReportedScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(mLastReportedScreen)->scale();
setScale(scale);
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 7e0d3c57c..2e3f322fb 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -142,6 +142,7 @@ public:
QWaylandScreen *waylandScreen() const;
void handleContentOrientationChange(Qt::ScreenOrientation orientation) override;
+ void updateBufferTransform();
void setOrientationMask(Qt::ScreenOrientations mask);
ToplevelWindowTilingStates toplevelWindowTilingStates() const;
@@ -331,6 +332,8 @@ protected:
QPointer<QWaylandWindow> mTransientParent;
QList<QPointer<QWaylandWindow>> mChildPopups;
+ Qt::ScreenOrientation mLastReportedContentOrientation = Qt::PrimaryOrientation;
+
private slots:
void doApplyConfigureFromOtherThread();
@@ -348,6 +351,7 @@ private:
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
void handleScreensChanged();
+ void updateScale();
void setScale(qreal newScale);
void sendRecursiveExposeEvent();