diff options
author | JiDe Zhang <zhangjide@uniontech.com> | 2023-09-20 16:59:57 +0800 |
---|---|---|
committer | JiDe Zhang <zhangjide@uniontech.com> | 2023-11-02 19:03:07 +0800 |
commit | 67c470b1ede30ad85048b0b73b7e37cd12e26df5 (patch) | |
tree | 5cd74335fbce3a8e561368947881c85c67c5b9da /src/client | |
parent | 82006cb686ac87b40d6b5ce5ec04c7e24e6fc4e0 (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.cpp | 2 | ||||
-rw-r--r-- | src/client/qwaylandfractionalscale.cpp | 2 | ||||
-rw-r--r-- | src/client/qwaylandfractionalscale_p.h | 4 | ||||
-rw-r--r-- | src/client/qwaylandscreen.cpp | 55 | ||||
-rw-r--r-- | src/client/qwaylandscreen_p.h | 3 | ||||
-rw-r--r-- | src/client/qwaylandsurface.cpp | 16 | ||||
-rw-r--r-- | src/client/qwaylandsurface_p.h | 8 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 87 | ||||
-rw-r--r-- | src/client/qwaylandwindow_p.h | 4 |
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(); |