diff options
author | David Edmundson <davidedmundson@kde.org> | 2022-03-23 15:35:50 +0000 |
---|---|---|
committer | David Edmundson <davidedmundson@kde.org> | 2022-12-07 20:36:40 +0000 |
commit | 23d3fc712cdf7fc0a4ff837082de9ba773e8605c (patch) | |
tree | 5b4866d8c3c0b7eb524a8f70050b3c2868b6ba01 /src | |
parent | 5bae5debdf94f6bbec61f4ff50ecbf3c1231e0e3 (diff) | |
download | qtwayland-23d3fc712cdf7fc0a4ff837082de9ba773e8605c.tar.gz |
Implement fractional_scale_v1 and wp_viewport
This allows compositors to hint a non-integer scale to use on a window
which we can hook to Qt's existing fractional scaling support.
The viewport is used to communicate the relationship between buffer size
and logical size to the compositor. It is a non-integer alternative to
wl_buffer_scale
Change-Id: I1a850f1bcd40e8d04e241e18a538b11f18bc671c
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/3rdparty/protocol/fractional-scale-v1.xml | 102 | ||||
-rw-r--r-- | src/3rdparty/protocol/qt_attribution.json | 17 | ||||
-rw-r--r-- | src/client/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/client/qwaylanddisplay.cpp | 17 | ||||
-rw-r--r-- | src/client/qwaylanddisplay_p.h | 8 | ||||
-rw-r--r-- | src/client/qwaylandfractionalscale.cpp | 36 | ||||
-rw-r--r-- | src/client/qwaylandfractionalscale_p.h | 50 | ||||
-rw-r--r-- | src/client/qwaylandviewport.cpp | 35 | ||||
-rw-r--r-- | src/client/qwaylandviewport_p.h | 42 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 61 | ||||
-rw-r--r-- | src/client/qwaylandwindow_p.h | 7 |
11 files changed, 372 insertions, 7 deletions
diff --git a/src/3rdparty/protocol/fractional-scale-v1.xml b/src/3rdparty/protocol/fractional-scale-v1.xml new file mode 100644 index 00000000..350bfc01 --- /dev/null +++ b/src/3rdparty/protocol/fractional-scale-v1.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="fractional_scale_v1"> + <copyright> + Copyright © 2022 Kenny Levinsen + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> + + <description summary="Protocol for requesting fractional surface scales"> + This protocol allows a compositor to suggest for surfaces to render at + fractional scales. + + A client can submit scaled content by utilizing wp_viewport. This is done by + creating a wp_viewport object for the surface and setting the destination + rectangle to the surface size before the scale factor is applied. + + The buffer size is calculated by multiplying the surface size by the + intended scale. + + The wl_surface buffer scale should remain set to 1. + + If a surface has a surface-local size of 100 px by 50 px and wishes to + submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should + be used and the wp_viewport destination rectangle should be 100 px by 50 px. + + For toplevel surfaces, the size is rounded halfway away from zero. The + rounding algorithm for subsurface position and size is not defined. + </description> + + <interface name="wp_fractional_scale_manager_v1" version="1"> + <description summary="fractional surface scale information"> + A global interface for requesting surfaces to use fractional scales. + </description> + + <request name="destroy" type="destructor"> + <description summary="unbind the fractional surface scale interface"> + Informs the server that the client will not be using this protocol + object anymore. This does not affect any other objects, + wp_fractional_scale_v1 objects included. + </description> + </request> + + <enum name="error"> + <entry name="fractional_scale_exists" value="0" + summary="the surface already has a fractional_scale object associated"/> + </enum> + + <request name="get_fractional_scale"> + <description summary="extend surface interface for scale information"> + Create an add-on object for the the wl_surface to let the compositor + request fractional scales. If the given wl_surface already has a + wp_fractional_scale_v1 object associated, the fractional_scale_exists + protocol error is raised. + </description> + <arg name="id" type="new_id" interface="wp_fractional_scale_v1" + summary="the new surface scale info interface id"/> + <arg name="surface" type="object" interface="wl_surface" + summary="the surface"/> + </request> + </interface> + + <interface name="wp_fractional_scale_v1" version="1"> + <description summary="fractional scale interface to a wl_surface"> + An additional interface to a wl_surface object which allows the compositor + to inform the client of the preferred scale. + </description> + + <request name="destroy" type="destructor"> + <description summary="remove surface scale information for surface"> + Destroy the fractional scale object. When this object is destroyed, + preferred_scale events will no longer be sent. + </description> + </request> + + <event name="preferred_scale"> + <description summary="notify of new preferred scale"> + Notification of a new preferred scale for this surface that the + compositor suggests that the client should use. + + The sent scale is the numerator of a fraction with a denominator of 120. + </description> + <arg name="scale" type="uint" summary="the new preferred scale"/> + </event> + </interface> +</protocol> diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json index 7b81d551..e30cb1b6 100644 --- a/src/3rdparty/protocol/qt_attribution.json +++ b/src/3rdparty/protocol/qt_attribution.json @@ -318,5 +318,22 @@ "License": "MIT License", "LicenseFile": "MIT_LICENSE.txt", "Copyright": "Copyright © 2015-2016 Red Hat Inc." + }, + + { + "Id": "fractional-scale-v1", + "Name": "Wayland Fractional Scale Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland platform plugin", + "Files": "fractional-scale-v1.xml", + + "Description": "Send a preferred scale to different clients", + "Homepage": "https://wayland.freedesktop.org", + "Version": "1", + "DownloadLocation": "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/raw/1.31/unstable/fractional-scale/fractional-scale-v1.xml", + "LicenseId": "MIT", + "License": "MIT License", + "LicenseFile": "MIT_LICENSE.txt", + "Copyright": "Copyright © 2022 Kenny Levinsen" } ] diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 820c9ead..47312010 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -32,6 +32,7 @@ qt_internal_add_module(WaylandClient qwaylanddecorationplugin.cpp qwaylanddecorationplugin_p.h qwaylanddisplay.cpp qwaylanddisplay_p.h qwaylandextendedsurface.cpp qwaylandextendedsurface_p.h + qwaylandfractionalscale.cpp qwaylandfractionalscale_p.h qwaylandinputcontext.cpp qwaylandinputcontext_p.h qwaylandtextinputv1.cpp qwaylandtextinputv1_p.h qwaylandtextinputv2.cpp qwaylandtextinputv2_p.h @@ -50,6 +51,7 @@ qt_internal_add_module(WaylandClient qwaylandsubsurface.cpp qwaylandsubsurface_p.h qwaylandsurface.cpp qwaylandsurface_p.h qwaylandtouch.cpp qwaylandtouch_p.h + qwaylandviewport.cpp qwaylandviewport_p.h qwaylandwindow.cpp qwaylandwindow_p.h qwaylandwindowmanagerintegration.cpp qwaylandwindowmanagerintegration_p.h shellintegration/qwaylandclientshellapi_p.h @@ -88,6 +90,8 @@ qt6_generate_wayland_protocol_client_sources(WaylandClient ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/wayland.xml ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/wp-primary-selection-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/xdg-output-unstable-v1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/fractional-scale-v1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/viewporter.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-key-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-text-input-method-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-windowmanager.xml diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 18eb71c3..52ea6492 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -50,6 +50,8 @@ #include <QtWaylandClient/private/qwayland-text-input-unstable-v4-wip.h> #include <QtWaylandClient/private/qwayland-wp-primary-selection-unstable-v1.h> #include <QtWaylandClient/private/qwayland-qt-text-input-method-unstable-v1.h> +#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h> +#include <QtWaylandClient/private/qwayland-viewporter.h> #include <QtCore/private/qcore_unix_p.h> @@ -294,6 +296,17 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion) return mSubCompositor->get_subsurface(window->wlSurface(), parent->wlSurface()); } +::wp_viewport *QWaylandDisplay::createViewport(QWaylandWindow *window) +{ + if (!mViewporter) { + qCWarning(lcQpaWayland) << "Can't create wp_viewport, not supported by the compositor."; + return nullptr; + } + + Q_ASSERT(window->wlSurface()); + return mViewporter->get_viewport(window->wlSurface()); +} + QWaylandShellIntegration *QWaylandDisplay::shellIntegration() const { return mWaylandIntegration->shellIntegration(); @@ -597,6 +610,10 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin mXdgOutputManager.reset(new QWaylandXdgOutputManagerV1(this, id, version)); for (auto *screen : std::as_const(mWaitingScreens)) screen->initXdgOutput(xdgOutputManager()); + } else if (interface == QLatin1String(QtWayland::wp_fractional_scale_manager_v1::interface()->name)) { + mFractionalScaleManager.reset(new QtWayland::wp_fractional_scale_manager_v1(registry, id, 1)); + } else if (interface == QLatin1String("wp_viewporter")) { + mViewporter.reset(new QtWayland::wp_viewporter(registry, id, qMin(1u, version))); } mGlobals.append(RegistryGlobal(id, interface, version, registry)); diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 473016f1..640f33b8 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -36,6 +36,7 @@ #endif struct wl_cursor_image; +struct wp_viewport; QT_BEGIN_NAMESPACE @@ -50,6 +51,8 @@ namespace QtWayland { class zwp_text_input_manager_v2; class zwp_text_input_manager_v4; class qt_text_input_method_manager_v1; + class wp_viewporter; + class wp_fractional_scale_manager_v1; } namespace QtWaylandClient { @@ -110,6 +113,7 @@ public: struct wl_surface *createSurface(void *handle); struct ::wl_region *createRegion(const QRegion &qregion); struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent); + struct ::wp_viewport *createViewport(QWaylandWindow *window); QWaylandShellIntegration *shellIntegration() const; QWaylandClientBufferIntegration *clientBufferIntegration() const; @@ -146,6 +150,8 @@ public: QtWayland::zwp_text_input_manager_v4 *textInputManagerv4() const { return mTextInputManagerv4.data(); } QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); } QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.data(); } + QtWayland::wp_fractional_scale_manager_v1 *fractionalScaleManager() const { return mFractionalScaleManager.data(); } + QtWayland::wp_viewporter *viewporter() const { return mViewporter.data(); } struct RegistryGlobal { uint32_t id; @@ -265,6 +271,8 @@ private: QScopedPointer<QtWayland::zwp_text_input_manager_v4> mTextInputManagerv4; QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration; QScopedPointer<QWaylandXdgOutputManagerV1> mXdgOutputManager; + QScopedPointer<QtWayland::wp_viewporter> mViewporter; + QScopedPointer<QtWayland::wp_fractional_scale_manager_v1> mFractionalScaleManager; int mFd = -1; int mWritableNotificationFd = -1; QList<RegistryGlobal> mGlobals; diff --git a/src/client/qwaylandfractionalscale.cpp b/src/client/qwaylandfractionalscale.cpp new file mode 100644 index 00000000..324a0b72 --- /dev/null +++ b/src/client/qwaylandfractionalscale.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwaylandfractionalscale_p.h" + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +QWaylandFractionalScale::QWaylandFractionalScale(struct ::wp_fractional_scale_v1 *object) + : QtWayland::wp_fractional_scale_v1(object) +{} + + +QWaylandFractionalScale::~QWaylandFractionalScale() +{ + destroy(); +} + +qreal QWaylandFractionalScale::preferredScale() const +{ + return mPreferredScale; +} + +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(); + } +} + +} + +QT_END_NAMESPACE diff --git a/src/client/qwaylandfractionalscale_p.h b/src/client/qwaylandfractionalscale_p.h new file mode 100644 index 00000000..0483eb33 --- /dev/null +++ b/src/client/qwaylandfractionalscale_p.h @@ -0,0 +1,50 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWAYLANDFRACTIONALSCALE_P_H +#define QWAYLANDFRACTIONALSCALE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h> +#include <QtWaylandClient/qtwaylandclientglobal.h> + +#include <QObject> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +class QWaylandFractionalScale : public QObject, public QtWayland::wp_fractional_scale_v1 +{ + Q_OBJECT +public: + explicit QWaylandFractionalScale(struct ::wp_fractional_scale_v1 *object); + ~QWaylandFractionalScale(); + + qreal preferredScale() const; + +Q_SIGNALS: + void preferredScaleChanged(); + +protected: + void wp_fractional_scale_v1_preferred_scale(uint scale) override; + +private: + qreal mPreferredScale = 1.0; +}; + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/client/qwaylandviewport.cpp b/src/client/qwaylandviewport.cpp new file mode 100644 index 00000000..3252718c --- /dev/null +++ b/src/client/qwaylandviewport.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwaylandviewport_p.h" + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +QWaylandViewport::QWaylandViewport(::wp_viewport *viewport) + : QtWayland::wp_viewport(viewport) +{ +} + +QWaylandViewport::~QWaylandViewport() +{ + destroy(); +} + +void QWaylandViewport::setSource(const QRectF &source) +{ + set_source(wl_fixed_from_double(source.x()), + wl_fixed_from_double(source.y()), + wl_fixed_from_double(source.width()), + wl_fixed_from_double(source.height())); +} + +void QWaylandViewport::setDestination(const QSize &destination) +{ + set_destination(destination.width(), destination.height()); +} + +} + +QT_END_NAMESPACE diff --git a/src/client/qwaylandviewport_p.h b/src/client/qwaylandviewport_p.h new file mode 100644 index 00000000..e1dfeb3a --- /dev/null +++ b/src/client/qwaylandviewport_p.h @@ -0,0 +1,42 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWAYLANDVIEWPORT_P_H +#define QWAYLANDVIEWPORT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandClient/private/qwayland-viewporter.h> +#include <QtWaylandClient/qtwaylandclientglobal.h> + +#include <QRect> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +class QWaylandViewport : public QtWayland::wp_viewport +{ +public: + explicit QWaylandViewport(::wp_viewport *viewport); + ~QWaylandViewport() override; + + void setSource(const QRectF &source); + void setDestination(const QSize &destination); + +}; + +} + +QT_END_NAMESPACE + +#endif // QWAYLANDVIEWPORT_P_H diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index f4d49c84..56b9af28 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -7,6 +7,7 @@ #include "qwaylanddisplay_p.h" #include "qwaylandsurface_p.h" #include "qwaylandinputdevice_p.h" +#include "qwaylandfractionalscale_p.h" #include "qwaylandscreen_p.h" #include "qwaylandshellsurface_p.h" #include "qwaylandsubsurface_p.h" @@ -16,6 +17,7 @@ #include "qwaylanddecorationfactory_p.h" #include "qwaylandshmbackingstore_p.h" #include "qwaylandshellintegration_p.h" +#include "qwaylandviewport_p.h" #include <QtCore/QFileInfo> #include <QtCore/QPointer> @@ -29,6 +31,8 @@ #include <QtCore/QDebug> #include <QtCore/QThread> +#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h> + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -91,6 +95,26 @@ void QWaylandWindow::initWindow() initializeWlSurface(); } + if (mDisplay->fractionalScaleManager() && qApp->highDpiScaleFactorRoundingPolicy() == Qt::HighDpiScaleFactorRoundingPolicy::PassThrough) { + mFractionalScale.reset(new QWaylandFractionalScale(mDisplay->fractionalScaleManager()->get_fractional_scale(mSurface->object()))); + + mScale = mFractionalScale->preferredScale(); + connect(mFractionalScale.data(), &QWaylandFractionalScale::preferredScaleChanged, this, [this]() { + if (mScale == mFractionalScale->preferredScale()) { + return; + } + mScale = mFractionalScale->preferredScale(); + ensureSize(); + if (mViewport) + updateViewport(); + if (isExposed()) { + // redraw at the new DPR + window()->requestUpdate(); + sendExposeEvent(QRect(QPoint(), geometry().size())); + } + }); + } + if (shouldCreateSubSurface()) { Q_ASSERT(!mSubSurfaceWindow); @@ -146,11 +170,17 @@ void QWaylandWindow::initWindow() } } + if (display()->viewporter() && !window()->flags().testFlag(Qt::BypassWindowManagerHint)) { + mViewport.reset(new QWaylandViewport(display()->createViewport(this))); + } + // Enable high-dpi rendering. Scale() returns the screen scale factor and will // typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale() // to inform the compositor that high-resolution buffers will be provided. - if (mSurface->version() >= 3) - mSurface->set_buffer_scale(mScale); + if (mViewport) + updateViewport(); + else if (mSurface->version() >= 3) + mSurface->set_buffer_scale(std::ceil(scale())); setWindowFlags(window()->flags()); QRect geometry = windowGeometry(); @@ -220,6 +250,8 @@ void QWaylandWindow::reset() mShellSurface = nullptr; delete mSubSurfaceWindow; mSubSurfaceWindow = nullptr; + mViewport.reset(); + mFractionalScale.reset(); if (mSurface) { emit wlSurfaceDestroyed(); @@ -322,6 +354,8 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect) QPlatformWindow::setGeometry(QRect(rect.x(), rect.y(), qBound(minimum.width(), rect.width(), maximum.width()), qBound(minimum.height(), rect.height(), maximum.height()))); + if (mViewport) + updateViewport(); if (mSubSurfaceWindow) { QMargins m = static_cast<QWaylandWindow *>(QPlatformWindow::parent())->clientSideMargins(); @@ -370,6 +404,12 @@ void QWaylandWindow::setGeometry(const QRect &r) setOpaqueArea(QRect(QPoint(0, 0), rect.size())); } +void QWaylandWindow::updateViewport() +{ + if (!surfaceSize().isEmpty()) + mViewport->setDestination(surfaceSize()); +} + void QWaylandWindow::setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins) { QMargins margins = clientSideMargins(); @@ -1242,6 +1282,7 @@ void QWaylandWindow::handleScreensChanged() return; QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); + mLastReportedScreen = newScreen; if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup && window()->type() != Qt::ToolTip @@ -1251,11 +1292,19 @@ void QWaylandWindow::handleScreensChanged() setGeometry(geometry); } - int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale(); + if (mFractionalScale) + return; + + int scale = mLastReportedScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(mLastReportedScreen)->scale(); + if (scale != mScale) { mScale = scale; - if (mSurface && mSurface->version() >= 3) - mSurface->set_buffer_scale(mScale); + if (mSurface) { + if (mViewport) + updateViewport(); + else if (mSurface->version() >= 3) + mSurface->set_buffer_scale(std::ceil(mScale)); + } ensureSize(); } } @@ -1558,4 +1607,4 @@ void QWaylandWindow::closeChildPopups() { QT_END_NAMESPACE -#include "moc_qwaylandwindow_p.cpp" +#include "qwaylandwindow.moc" diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 0f8c5515..6531606a 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -53,6 +53,8 @@ class QWaylandPointerEvent; class QWaylandPointerGestureSwipeEvent; class QWaylandPointerGesturePinchEvent; class QWaylandSurface; +class QWaylandFractionalScale; +class QWaylandViewport; class Q_WAYLANDCLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow { @@ -233,6 +235,8 @@ protected: // mSurface can be written by the main thread. Other threads should claim a read lock for access mutable QReadWriteLock mSurfaceLock; QScopedPointer<QWaylandSurface> mSurface; + QScopedPointer<QWaylandFractionalScale> mFractionalScale; + QScopedPointer<QWaylandViewport> mViewport; QWaylandShellSurface *mShellSurface = nullptr; QWaylandSubSurface *mSubSurfaceWindow = nullptr; @@ -284,7 +288,7 @@ protected: bool mSentInitialResize = false; QPoint mOffset; - int mScale = 1; + qreal mScale = 1; QPlatformScreen *mLastReportedScreen = nullptr; QIcon mWindowIcon; @@ -314,6 +318,7 @@ private: QPlatformScreen *calculateScreenFromSurfaceEvents() const; void setOpaqueArea(const QRegion &opaqueArea); bool isOpaque() const; + void updateViewport(); void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e); void handleScreensChanged(); |