summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Edmundson <davidedmundson@kde.org>2022-03-23 15:35:50 +0000
committerDavid Edmundson <davidedmundson@kde.org>2022-12-07 20:36:40 +0000
commit23d3fc712cdf7fc0a4ff837082de9ba773e8605c (patch)
tree5b4866d8c3c0b7eb524a8f70050b3c2868b6ba01 /src
parent5bae5debdf94f6bbec61f4ff50ecbf3c1231e0e3 (diff)
downloadqtwayland-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.xml102
-rw-r--r--src/3rdparty/protocol/qt_attribution.json17
-rw-r--r--src/client/CMakeLists.txt4
-rw-r--r--src/client/qwaylanddisplay.cpp17
-rw-r--r--src/client/qwaylanddisplay_p.h8
-rw-r--r--src/client/qwaylandfractionalscale.cpp36
-rw-r--r--src/client/qwaylandfractionalscale_p.h50
-rw-r--r--src/client/qwaylandviewport.cpp35
-rw-r--r--src/client/qwaylandviewport_p.h42
-rw-r--r--src/client/qwaylandwindow.cpp61
-rw-r--r--src/client/qwaylandwindow_p.h7
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();