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>
This commit is contained in:
parent
f45244946c
commit
d62c5761e8
102
src/3rdparty/wayland/protocols/fractional-scale-v1.xml
vendored
Normal file
102
src/3rdparty/wayland/protocols/fractional-scale-v1.xml
vendored
Normal file
@ -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>
|
@ -318,5 +318,22 @@
|
|||||||
"License": "MIT License",
|
"License": "MIT License",
|
||||||
"LicenseFile": "MIT_LICENSE.txt",
|
"LicenseFile": "MIT_LICENSE.txt",
|
||||||
"Copyright": "Copyright © 2015-2016 Red Hat Inc."
|
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -32,6 +32,7 @@ qt_internal_add_module(WaylandClient
|
|||||||
qwaylanddecorationplugin.cpp qwaylanddecorationplugin_p.h
|
qwaylanddecorationplugin.cpp qwaylanddecorationplugin_p.h
|
||||||
qwaylanddisplay.cpp qwaylanddisplay_p.h
|
qwaylanddisplay.cpp qwaylanddisplay_p.h
|
||||||
qwaylandextendedsurface.cpp qwaylandextendedsurface_p.h
|
qwaylandextendedsurface.cpp qwaylandextendedsurface_p.h
|
||||||
|
qwaylandfractionalscale.cpp qwaylandfractionalscale_p.h
|
||||||
qwaylandinputcontext.cpp qwaylandinputcontext_p.h
|
qwaylandinputcontext.cpp qwaylandinputcontext_p.h
|
||||||
qwaylandtextinputv1.cpp qwaylandtextinputv1_p.h
|
qwaylandtextinputv1.cpp qwaylandtextinputv1_p.h
|
||||||
qwaylandtextinputv2.cpp qwaylandtextinputv2_p.h
|
qwaylandtextinputv2.cpp qwaylandtextinputv2_p.h
|
||||||
@ -50,6 +51,7 @@ qt_internal_add_module(WaylandClient
|
|||||||
qwaylandsubsurface.cpp qwaylandsubsurface_p.h
|
qwaylandsubsurface.cpp qwaylandsubsurface_p.h
|
||||||
qwaylandsurface.cpp qwaylandsurface_p.h
|
qwaylandsurface.cpp qwaylandsurface_p.h
|
||||||
qwaylandtouch.cpp qwaylandtouch_p.h
|
qwaylandtouch.cpp qwaylandtouch_p.h
|
||||||
|
qwaylandviewport.cpp qwaylandviewport_p.h
|
||||||
qwaylandwindow.cpp qwaylandwindow_p.h
|
qwaylandwindow.cpp qwaylandwindow_p.h
|
||||||
qwaylandwindowmanagerintegration.cpp qwaylandwindowmanagerintegration_p.h
|
qwaylandwindowmanagerintegration.cpp qwaylandwindowmanagerintegration_p.h
|
||||||
shellintegration/qwaylandclientshellapi_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/wayland.xml
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/protocol/wp-primary-selection-unstable-v1.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/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-key-unstable-v1.xml
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-text-input-method-unstable-v1.xml
|
${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-text-input-method-unstable-v1.xml
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-windowmanager.xml
|
${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-windowmanager.xml
|
||||||
|
@ -50,6 +50,8 @@
|
|||||||
#include <QtWaylandClient/private/qwayland-text-input-unstable-v4-wip.h>
|
#include <QtWaylandClient/private/qwayland-text-input-unstable-v4-wip.h>
|
||||||
#include <QtWaylandClient/private/qwayland-wp-primary-selection-unstable-v1.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-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>
|
#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());
|
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
|
QWaylandShellIntegration *QWaylandDisplay::shellIntegration() const
|
||||||
{
|
{
|
||||||
return mWaylandIntegration->shellIntegration();
|
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));
|
mXdgOutputManager.reset(new QWaylandXdgOutputManagerV1(this, id, version));
|
||||||
for (auto *screen : std::as_const(mWaitingScreens))
|
for (auto *screen : std::as_const(mWaitingScreens))
|
||||||
screen->initXdgOutput(xdgOutputManager());
|
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));
|
mGlobals.append(RegistryGlobal(id, interface, version, registry));
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct wl_cursor_image;
|
struct wl_cursor_image;
|
||||||
|
struct wp_viewport;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -50,6 +51,8 @@ namespace QtWayland {
|
|||||||
class zwp_text_input_manager_v2;
|
class zwp_text_input_manager_v2;
|
||||||
class zwp_text_input_manager_v4;
|
class zwp_text_input_manager_v4;
|
||||||
class qt_text_input_method_manager_v1;
|
class qt_text_input_method_manager_v1;
|
||||||
|
class wp_viewporter;
|
||||||
|
class wp_fractional_scale_manager_v1;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace QtWaylandClient {
|
namespace QtWaylandClient {
|
||||||
@ -110,6 +113,7 @@ public:
|
|||||||
struct wl_surface *createSurface(void *handle);
|
struct wl_surface *createSurface(void *handle);
|
||||||
struct ::wl_region *createRegion(const QRegion &qregion);
|
struct ::wl_region *createRegion(const QRegion &qregion);
|
||||||
struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
|
struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
|
||||||
|
struct ::wp_viewport *createViewport(QWaylandWindow *window);
|
||||||
|
|
||||||
QWaylandShellIntegration *shellIntegration() const;
|
QWaylandShellIntegration *shellIntegration() const;
|
||||||
QWaylandClientBufferIntegration *clientBufferIntegration() const;
|
QWaylandClientBufferIntegration *clientBufferIntegration() const;
|
||||||
@ -146,6 +150,8 @@ public:
|
|||||||
QtWayland::zwp_text_input_manager_v4 *textInputManagerv4() const { return mTextInputManagerv4.data(); }
|
QtWayland::zwp_text_input_manager_v4 *textInputManagerv4() const { return mTextInputManagerv4.data(); }
|
||||||
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
|
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
|
||||||
QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.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 {
|
struct RegistryGlobal {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -265,6 +271,8 @@ private:
|
|||||||
QScopedPointer<QtWayland::zwp_text_input_manager_v4> mTextInputManagerv4;
|
QScopedPointer<QtWayland::zwp_text_input_manager_v4> mTextInputManagerv4;
|
||||||
QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
|
QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
|
||||||
QScopedPointer<QWaylandXdgOutputManagerV1> mXdgOutputManager;
|
QScopedPointer<QWaylandXdgOutputManagerV1> mXdgOutputManager;
|
||||||
|
QScopedPointer<QtWayland::wp_viewporter> mViewporter;
|
||||||
|
QScopedPointer<QtWayland::wp_fractional_scale_manager_v1> mFractionalScaleManager;
|
||||||
int mFd = -1;
|
int mFd = -1;
|
||||||
int mWritableNotificationFd = -1;
|
int mWritableNotificationFd = -1;
|
||||||
QList<RegistryGlobal> mGlobals;
|
QList<RegistryGlobal> mGlobals;
|
||||||
|
36
src/plugins/platforms/wayland/qwaylandfractionalscale.cpp
Normal file
36
src/plugins/platforms/wayland/qwaylandfractionalscale.cpp
Normal file
@ -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
|
50
src/plugins/platforms/wayland/qwaylandfractionalscale_p.h
Normal file
50
src/plugins/platforms/wayland/qwaylandfractionalscale_p.h
Normal file
@ -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
|
35
src/plugins/platforms/wayland/qwaylandviewport.cpp
Normal file
35
src/plugins/platforms/wayland/qwaylandviewport.cpp
Normal file
@ -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
|
42
src/plugins/platforms/wayland/qwaylandviewport_p.h
Normal file
42
src/plugins/platforms/wayland/qwaylandviewport_p.h
Normal file
@ -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
|
@ -7,6 +7,7 @@
|
|||||||
#include "qwaylanddisplay_p.h"
|
#include "qwaylanddisplay_p.h"
|
||||||
#include "qwaylandsurface_p.h"
|
#include "qwaylandsurface_p.h"
|
||||||
#include "qwaylandinputdevice_p.h"
|
#include "qwaylandinputdevice_p.h"
|
||||||
|
#include "qwaylandfractionalscale_p.h"
|
||||||
#include "qwaylandscreen_p.h"
|
#include "qwaylandscreen_p.h"
|
||||||
#include "qwaylandshellsurface_p.h"
|
#include "qwaylandshellsurface_p.h"
|
||||||
#include "qwaylandsubsurface_p.h"
|
#include "qwaylandsubsurface_p.h"
|
||||||
@ -16,6 +17,7 @@
|
|||||||
#include "qwaylanddecorationfactory_p.h"
|
#include "qwaylanddecorationfactory_p.h"
|
||||||
#include "qwaylandshmbackingstore_p.h"
|
#include "qwaylandshmbackingstore_p.h"
|
||||||
#include "qwaylandshellintegration_p.h"
|
#include "qwaylandshellintegration_p.h"
|
||||||
|
#include "qwaylandviewport_p.h"
|
||||||
|
|
||||||
#include <QtCore/QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
@ -29,6 +31,8 @@
|
|||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
#include <QtWaylandClient/private/qwayland-fractional-scale-v1.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QtWaylandClient {
|
namespace QtWaylandClient {
|
||||||
@ -91,6 +95,26 @@ void QWaylandWindow::initWindow()
|
|||||||
initializeWlSurface();
|
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()) {
|
if (shouldCreateSubSurface()) {
|
||||||
Q_ASSERT(!mSubSurfaceWindow);
|
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
|
// 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()
|
// 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.
|
// to inform the compositor that high-resolution buffers will be provided.
|
||||||
if (mSurface->version() >= 3)
|
if (mViewport)
|
||||||
mSurface->set_buffer_scale(mScale);
|
updateViewport();
|
||||||
|
else if (mSurface->version() >= 3)
|
||||||
|
mSurface->set_buffer_scale(std::ceil(scale()));
|
||||||
|
|
||||||
setWindowFlags(window()->flags());
|
setWindowFlags(window()->flags());
|
||||||
QRect geometry = windowGeometry();
|
QRect geometry = windowGeometry();
|
||||||
@ -220,6 +250,8 @@ void QWaylandWindow::reset()
|
|||||||
mShellSurface = nullptr;
|
mShellSurface = nullptr;
|
||||||
delete mSubSurfaceWindow;
|
delete mSubSurfaceWindow;
|
||||||
mSubSurfaceWindow = nullptr;
|
mSubSurfaceWindow = nullptr;
|
||||||
|
mViewport.reset();
|
||||||
|
mFractionalScale.reset();
|
||||||
|
|
||||||
if (mSurface) {
|
if (mSurface) {
|
||||||
emit wlSurfaceDestroyed();
|
emit wlSurfaceDestroyed();
|
||||||
@ -322,6 +354,8 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect)
|
|||||||
QPlatformWindow::setGeometry(QRect(rect.x(), rect.y(),
|
QPlatformWindow::setGeometry(QRect(rect.x(), rect.y(),
|
||||||
qBound(minimum.width(), rect.width(), maximum.width()),
|
qBound(minimum.width(), rect.width(), maximum.width()),
|
||||||
qBound(minimum.height(), rect.height(), maximum.height())));
|
qBound(minimum.height(), rect.height(), maximum.height())));
|
||||||
|
if (mViewport)
|
||||||
|
updateViewport();
|
||||||
|
|
||||||
if (mSubSurfaceWindow) {
|
if (mSubSurfaceWindow) {
|
||||||
QMargins m = static_cast<QWaylandWindow *>(QPlatformWindow::parent())->clientSideMargins();
|
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()));
|
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)
|
void QWaylandWindow::setGeometryFromApplyConfigure(const QPoint &globalPosition, const QSize &sizeWithMargins)
|
||||||
{
|
{
|
||||||
QMargins margins = clientSideMargins();
|
QMargins margins = clientSideMargins();
|
||||||
@ -1242,6 +1282,7 @@ void QWaylandWindow::handleScreensChanged()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
|
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
|
||||||
|
|
||||||
mLastReportedScreen = newScreen;
|
mLastReportedScreen = newScreen;
|
||||||
if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
|
if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup
|
||||||
&& window()->type() != Qt::ToolTip
|
&& window()->type() != Qt::ToolTip
|
||||||
@ -1251,11 +1292,19 @@ void QWaylandWindow::handleScreensChanged()
|
|||||||
setGeometry(geometry);
|
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) {
|
if (scale != mScale) {
|
||||||
mScale = scale;
|
mScale = scale;
|
||||||
if (mSurface && mSurface->version() >= 3)
|
if (mSurface) {
|
||||||
mSurface->set_buffer_scale(mScale);
|
if (mViewport)
|
||||||
|
updateViewport();
|
||||||
|
else if (mSurface->version() >= 3)
|
||||||
|
mSurface->set_buffer_scale(std::ceil(mScale));
|
||||||
|
}
|
||||||
ensureSize();
|
ensureSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1558,4 +1607,4 @@ void QWaylandWindow::closeChildPopups() {
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#include "moc_qwaylandwindow_p.cpp"
|
#include "qwaylandwindow.moc"
|
||||||
|
@ -53,6 +53,8 @@ class QWaylandPointerEvent;
|
|||||||
class QWaylandPointerGestureSwipeEvent;
|
class QWaylandPointerGestureSwipeEvent;
|
||||||
class QWaylandPointerGesturePinchEvent;
|
class QWaylandPointerGesturePinchEvent;
|
||||||
class QWaylandSurface;
|
class QWaylandSurface;
|
||||||
|
class QWaylandFractionalScale;
|
||||||
|
class QWaylandViewport;
|
||||||
|
|
||||||
class Q_WAYLANDCLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow
|
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
|
// mSurface can be written by the main thread. Other threads should claim a read lock for access
|
||||||
mutable QReadWriteLock mSurfaceLock;
|
mutable QReadWriteLock mSurfaceLock;
|
||||||
QScopedPointer<QWaylandSurface> mSurface;
|
QScopedPointer<QWaylandSurface> mSurface;
|
||||||
|
QScopedPointer<QWaylandFractionalScale> mFractionalScale;
|
||||||
|
QScopedPointer<QWaylandViewport> mViewport;
|
||||||
|
|
||||||
QWaylandShellSurface *mShellSurface = nullptr;
|
QWaylandShellSurface *mShellSurface = nullptr;
|
||||||
QWaylandSubSurface *mSubSurfaceWindow = nullptr;
|
QWaylandSubSurface *mSubSurfaceWindow = nullptr;
|
||||||
@ -284,7 +288,7 @@ protected:
|
|||||||
|
|
||||||
bool mSentInitialResize = false;
|
bool mSentInitialResize = false;
|
||||||
QPoint mOffset;
|
QPoint mOffset;
|
||||||
int mScale = 1;
|
qreal mScale = 1;
|
||||||
QPlatformScreen *mLastReportedScreen = nullptr;
|
QPlatformScreen *mLastReportedScreen = nullptr;
|
||||||
|
|
||||||
QIcon mWindowIcon;
|
QIcon mWindowIcon;
|
||||||
@ -314,6 +318,7 @@ private:
|
|||||||
QPlatformScreen *calculateScreenFromSurfaceEvents() const;
|
QPlatformScreen *calculateScreenFromSurfaceEvents() const;
|
||||||
void setOpaqueArea(const QRegion &opaqueArea);
|
void setOpaqueArea(const QRegion &opaqueArea);
|
||||||
bool isOpaque() const;
|
bool isOpaque() const;
|
||||||
|
void updateViewport();
|
||||||
|
|
||||||
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
||||||
void handleScreensChanged();
|
void handleScreensChanged();
|
||||||
|
@ -25,8 +25,10 @@ if (NOT WEBOS)
|
|||||||
add_subdirectory(xdgdecorationv1)
|
add_subdirectory(xdgdecorationv1)
|
||||||
add_subdirectory(xdgoutput)
|
add_subdirectory(xdgoutput)
|
||||||
add_subdirectory(xdgshell)
|
add_subdirectory(xdgshell)
|
||||||
|
add_subdirectory(scaling)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(multithreaded)
|
add_subdirectory(multithreaded)
|
||||||
|
|
||||||
if(QT_FEATURE_im)
|
if(QT_FEATURE_im)
|
||||||
add_subdirectory(inputcontext)
|
add_subdirectory(inputcontext)
|
||||||
endif()
|
endif()
|
||||||
|
10
tests/auto/wayland/scaling/CMakeLists.txt
Normal file
10
tests/auto/wayland/scaling/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#####################################################################
|
||||||
|
## tst_scaling Test:
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
qt_internal_add_test(tst_scaling
|
||||||
|
SOURCES
|
||||||
|
tst_scaling.cpp
|
||||||
|
PUBLIC_LIBRARIES
|
||||||
|
SharedClientTest
|
||||||
|
)
|
135
tests/auto/wayland/scaling/tst_scaling.cpp
Normal file
135
tests/auto/wayland/scaling/tst_scaling.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 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 "mockcompositor.h"
|
||||||
|
#include <QtOpenGL/QOpenGLWindow>
|
||||||
|
#include <QtGui/QRasterWindow>
|
||||||
|
#include <QtGui/qpa/qplatformnativeinterface.h>
|
||||||
|
#include <QtWaylandClient/private/wayland-wayland-client-protocol.h>
|
||||||
|
#include <QtWaylandClient/private/qwaylandwindow_p.h>
|
||||||
|
|
||||||
|
using namespace MockCompositor;
|
||||||
|
|
||||||
|
class tst_scaling : public QObject, private DefaultCompositor
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private slots:
|
||||||
|
void init();
|
||||||
|
void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); }
|
||||||
|
void scaledWindow();
|
||||||
|
void roundingPolicy_data();
|
||||||
|
void roundingPolicy();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_scaling::init()
|
||||||
|
{
|
||||||
|
setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_scaling::scaledWindow()
|
||||||
|
{
|
||||||
|
QRasterWindow window;
|
||||||
|
window.resize(100, 100);
|
||||||
|
window.show();
|
||||||
|
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||||
|
|
||||||
|
QSignalSpy configureSpy(exec([=] { return xdgSurface(); }), &XdgSurface::configureCommitted);
|
||||||
|
QSignalSpy surfaceCommitSpy(exec([=] { return surface(); }), &Surface::commit);
|
||||||
|
|
||||||
|
const QSize configureSize(100, 100);
|
||||||
|
|
||||||
|
exec([=] {
|
||||||
|
QVERIFY(fractionalScale());
|
||||||
|
fractionalScale()->send_preferred_scale(1.5 * 120);
|
||||||
|
xdgToplevel()->sendCompleteConfigure(configureSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
QTRY_COMPARE(configureSpy.count(), 1);
|
||||||
|
QCOMPARE(window.devicePixelRatio(), 1.5);
|
||||||
|
|
||||||
|
exec([=] {
|
||||||
|
Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
|
||||||
|
QVERIFY(buffer);
|
||||||
|
QCOMPARE(buffer->size(), QSize(150, 150));
|
||||||
|
Viewport *vp = viewport();
|
||||||
|
QVERIFY(vp);
|
||||||
|
QCOMPARE(vp->m_destination, QSize(100, 100));
|
||||||
|
});
|
||||||
|
|
||||||
|
// resize the window
|
||||||
|
window.resize(200,200);
|
||||||
|
QCOMPARE(window.size(), QSize(200,200));
|
||||||
|
|
||||||
|
QVERIFY(surfaceCommitSpy.wait());
|
||||||
|
exec([=] {
|
||||||
|
Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
|
||||||
|
QVERIFY(buffer);
|
||||||
|
QCOMPARE(buffer->size(), QSize(300, 300));
|
||||||
|
Viewport *vp = viewport();
|
||||||
|
QVERIFY(vp);
|
||||||
|
QCOMPARE(vp->m_destination, QSize(200, 200));
|
||||||
|
});
|
||||||
|
|
||||||
|
// dynamic scale change
|
||||||
|
exec([=] {
|
||||||
|
QVERIFY(fractionalScale());
|
||||||
|
fractionalScale()->send_preferred_scale(2.5 * 120);
|
||||||
|
});
|
||||||
|
QTRY_COMPARE(window.devicePixelRatio(), 2.5);
|
||||||
|
QCOMPARE(window.size(), QSize(200,200));
|
||||||
|
|
||||||
|
QVERIFY(surfaceCommitSpy.wait());
|
||||||
|
exec([=] {
|
||||||
|
Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
|
||||||
|
QVERIFY(buffer);
|
||||||
|
QCOMPARE(buffer->size(), QSize(500, 500));
|
||||||
|
Viewport *vp = viewport();
|
||||||
|
QVERIFY(vp);
|
||||||
|
QCOMPARE(vp->m_destination, QSize(200, 200));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_scaling::roundingPolicy_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QSize>("windowSize");
|
||||||
|
QTest::addColumn<qreal>("scale");
|
||||||
|
QTest::addColumn<QSize>("expectedBufferSize");
|
||||||
|
|
||||||
|
QTest::newRow("1.125 - round down") << QSize(10, 10) << 1.125 << QSize(11,11);
|
||||||
|
QTest::newRow("1.25 - round up") << QSize(10, 10) << 1.25 << QSize(13,13);
|
||||||
|
QTest::newRow("1.5 - don't round") << QSize(10, 10) << 1.5 << QSize(15,15);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_scaling::roundingPolicy()
|
||||||
|
{
|
||||||
|
QFETCH(QSize, windowSize);
|
||||||
|
QFETCH(qreal, scale);
|
||||||
|
QFETCH(QSize, expectedBufferSize);
|
||||||
|
|
||||||
|
|
||||||
|
QRasterWindow window;
|
||||||
|
window.resize(windowSize);
|
||||||
|
window.show();
|
||||||
|
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
|
||||||
|
|
||||||
|
QSignalSpy surfaceCommitSpy(exec([=] { return surface(); }), &Surface::commit);
|
||||||
|
|
||||||
|
exec([=] {
|
||||||
|
QVERIFY(fractionalScale());
|
||||||
|
fractionalScale()->send_preferred_scale(scale * 120);
|
||||||
|
xdgToplevel()->sendCompleteConfigure();
|
||||||
|
});
|
||||||
|
|
||||||
|
QVERIFY(surfaceCommitSpy.wait());
|
||||||
|
|
||||||
|
exec([=] {
|
||||||
|
Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer;
|
||||||
|
QVERIFY(buffer);
|
||||||
|
QCOMPARE(buffer->size(), expectedBufferSize);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QCOMPOSITOR_TEST_MAIN(tst_scaling)
|
||||||
|
#include "tst_scaling.moc"
|
@ -11,9 +11,11 @@ qt_manual_moc(moc_files
|
|||||||
corecompositor.h
|
corecompositor.h
|
||||||
datadevice.h
|
datadevice.h
|
||||||
fullscreenshellv1.h
|
fullscreenshellv1.h
|
||||||
|
fractionalscalev1.h
|
||||||
iviapplication.h
|
iviapplication.h
|
||||||
textinput.h
|
textinput.h
|
||||||
qttextinput.h
|
qttextinput.h
|
||||||
|
viewport.h
|
||||||
xdgoutputv1.h
|
xdgoutputv1.h
|
||||||
xdgshell.h
|
xdgshell.h
|
||||||
)
|
)
|
||||||
@ -24,12 +26,14 @@ add_library(SharedClientTest
|
|||||||
coreprotocol.cpp coreprotocol.h
|
coreprotocol.cpp coreprotocol.h
|
||||||
datadevice.cpp datadevice.h
|
datadevice.cpp datadevice.h
|
||||||
fullscreenshellv1.cpp fullscreenshellv1.h
|
fullscreenshellv1.cpp fullscreenshellv1.h
|
||||||
|
fractionalscalev1.cpp fractionalscalev1.h
|
||||||
iviapplication.cpp iviapplication.h
|
iviapplication.cpp iviapplication.h
|
||||||
mockcompositor.cpp mockcompositor.h
|
mockcompositor.cpp mockcompositor.h
|
||||||
textinput.cpp textinput.h
|
textinput.cpp textinput.h
|
||||||
qttextinput.cpp qttextinput.h
|
qttextinput.cpp qttextinput.h
|
||||||
xdgoutputv1.cpp xdgoutputv1.h
|
xdgoutputv1.cpp xdgoutputv1.h
|
||||||
xdgshell.cpp xdgshell.h
|
xdgshell.cpp xdgshell.h
|
||||||
|
viewport.cpp viewport.h
|
||||||
${moc_files}
|
${moc_files}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,6 +45,8 @@ qt6_generate_wayland_protocol_server_sources(SharedClientTest
|
|||||||
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/tablet-unstable-v2.xml
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/tablet-unstable-v2.xml
|
||||||
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/text-input-unstable-v2.xml
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/text-input-unstable-v2.xml
|
||||||
${PROJECT_SOURCE_DIR}/src/extensions/qt-text-input-method-unstable-v1.xml
|
${PROJECT_SOURCE_DIR}/src/extensions/qt-text-input-method-unstable-v1.xml
|
||||||
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/fractional-scale-v1.xml
|
||||||
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/viewporter.xml
|
||||||
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/wayland.xml
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/wayland.xml
|
||||||
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-decoration-unstable-v1.xml
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-decoration-unstable-v1.xml
|
||||||
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-output-unstable-v1.xml
|
${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-output-unstable-v1.xml
|
||||||
|
40
tests/auto/wayland/shared/fractionalscalev1.cpp
Normal file
40
tests/auto/wayland/shared/fractionalscalev1.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// 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 "fractionalscalev1.h"
|
||||||
|
|
||||||
|
namespace MockCompositor {
|
||||||
|
|
||||||
|
FractionalScaleManager::FractionalScaleManager(CoreCompositor *compositor, int version)
|
||||||
|
: QtWaylandServer::wp_fractional_scale_manager_v1(compositor->m_display, version)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FractionalScaleManager::wp_fractional_scale_manager_v1_get_fractional_scale(Resource *resource, uint32_t id, wl_resource *surface)
|
||||||
|
{
|
||||||
|
auto *s = fromResource<Surface>(surface);
|
||||||
|
auto *scaler = new FractionalScale(s, resource->client(), id, resource->version());
|
||||||
|
connect(scaler, &QObject::destroyed, this, [this, scaler]() {
|
||||||
|
m_fractionalScales.removeOne(scaler);
|
||||||
|
});
|
||||||
|
m_fractionalScales << scaler;
|
||||||
|
}
|
||||||
|
|
||||||
|
FractionalScale::FractionalScale(Surface *surface, wl_client *client, int id, int version)
|
||||||
|
: QtWaylandServer::wp_fractional_scale_v1(client, id, version)
|
||||||
|
, m_surface(surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FractionalScale::wp_fractional_scale_v1_destroy_resource(Resource *resource)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FractionalScale::wp_fractional_scale_v1_destroy(Resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy(resource->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
tests/auto/wayland/shared/fractionalscalev1.h
Normal file
39
tests/auto/wayland/shared/fractionalscalev1.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#ifndef MOCKCOMPOSITOR_FRACTIONALSCALE_H
|
||||||
|
#define MOCKCOMPOSITOR_FRACTIONALSCALE_H
|
||||||
|
|
||||||
|
#include "coreprotocol.h"
|
||||||
|
#include <qwayland-server-fractional-scale-v1.h>
|
||||||
|
|
||||||
|
namespace MockCompositor {
|
||||||
|
|
||||||
|
class FractionalScale;
|
||||||
|
|
||||||
|
class FractionalScaleManager : public Global, public QtWaylandServer::wp_fractional_scale_manager_v1
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FractionalScaleManager(CoreCompositor *compositor, int version = 1);
|
||||||
|
QList<FractionalScale *> m_fractionalScales;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void wp_fractional_scale_manager_v1_get_fractional_scale(Resource *resource, uint32_t id, wl_resource *surface) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FractionalScale : public QObject, public QtWaylandServer::wp_fractional_scale_v1
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FractionalScale(Surface *surface, wl_client *client, int id, int version);
|
||||||
|
Surface *m_surface;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void wp_fractional_scale_v1_destroy_resource(Resource *resource) override;
|
||||||
|
void wp_fractional_scale_v1_destroy(Resource *resource) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -21,6 +21,9 @@ DefaultCompositor::DefaultCompositor(CompositorType t)
|
|||||||
add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch);
|
add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch);
|
||||||
add<WlShell>();
|
add<WlShell>();
|
||||||
add<XdgWmBase>();
|
add<XdgWmBase>();
|
||||||
|
add<FractionalScaleManager>();
|
||||||
|
add<Viewporter>();
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case CompositorType::Default:
|
case CompositorType::Default:
|
||||||
add<Shm>();
|
add<Shm>();
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "fullscreenshellv1.h"
|
#include "fullscreenshellv1.h"
|
||||||
#include "iviapplication.h"
|
#include "iviapplication.h"
|
||||||
#include "xdgshell.h"
|
#include "xdgshell.h"
|
||||||
|
#include "viewport.h"
|
||||||
|
#include "fractionalscalev1.h"
|
||||||
|
|
||||||
#include <QtGui/QGuiApplication>
|
#include <QtGui/QGuiApplication>
|
||||||
|
|
||||||
@ -46,6 +48,8 @@ public:
|
|||||||
Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; }
|
Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; }
|
||||||
FullScreenShellV1 *fullScreenShellV1() {return get<FullScreenShellV1>();};
|
FullScreenShellV1 *fullScreenShellV1() {return get<FullScreenShellV1>();};
|
||||||
IviSurface *iviSurface(int i = 0) { return get<IviApplication>()->m_iviSurfaces.value(i, nullptr); }
|
IviSurface *iviSurface(int i = 0) { return get<IviApplication>()->m_iviSurfaces.value(i, nullptr); }
|
||||||
|
FractionalScale *fractionalScale(int i = 0) {return get<FractionalScaleManager>()->m_fractionalScales.value(i, nullptr); }
|
||||||
|
Viewport *viewport(int i = 0) {return get<Viewporter>()->m_viewports.value(i, nullptr); }
|
||||||
|
|
||||||
uint sendXdgShellPing();
|
uint sendXdgShellPing();
|
||||||
void xdgPingAndWaitForPong();
|
void xdgPingAndWaitForPong();
|
||||||
|
58
tests/auto/wayland/shared/viewport.cpp
Normal file
58
tests/auto/wayland/shared/viewport.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// 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 "viewport.h"
|
||||||
|
|
||||||
|
namespace MockCompositor {
|
||||||
|
|
||||||
|
Viewporter::Viewporter(CoreCompositor *compositor, int version)
|
||||||
|
: QtWaylandServer::wp_viewporter(compositor->m_display, version)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewporter::wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface)
|
||||||
|
{
|
||||||
|
auto *s = fromResource<Surface>(surface);
|
||||||
|
auto *viewport = new Viewport(s, resource->client(), id, resource->version());
|
||||||
|
connect(viewport, &QObject::destroyed, this, [this, viewport]() {
|
||||||
|
m_viewports.removeOne(viewport);
|
||||||
|
});
|
||||||
|
m_viewports << viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewport::Viewport(Surface *surface, wl_client *client, int id, int version)
|
||||||
|
: QtWaylandServer::wp_viewport(client, id, version)
|
||||||
|
, m_surface(surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
m_source = QRectF(wl_fixed_to_double(x),
|
||||||
|
wl_fixed_to_double(y),
|
||||||
|
wl_fixed_to_double(width),
|
||||||
|
wl_fixed_to_double(height));
|
||||||
|
Q_EMIT sourceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
|
||||||
|
m_destination = QSize(width, height);
|
||||||
|
Q_EMIT destinationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::wp_viewport_destroy_resource(Resource *resource)
|
||||||
|
{
|
||||||
|
Q_UNUSED(resource)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::wp_viewport_destroy(Resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy(resource->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
tests/auto/wayland/shared/viewport.h
Normal file
50
tests/auto/wayland/shared/viewport.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org>
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#ifndef MOCKCOMPOSITOR_VIEWPORT_H
|
||||||
|
#define MOCKCOMPOSITOR_VIEWPORT_H
|
||||||
|
|
||||||
|
#include "coreprotocol.h"
|
||||||
|
#include <qwayland-server-viewporter.h>
|
||||||
|
|
||||||
|
namespace MockCompositor {
|
||||||
|
|
||||||
|
class Viewport;
|
||||||
|
|
||||||
|
class Viewporter : public Global, public QtWaylandServer::wp_viewporter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Viewporter(CoreCompositor *compositor, int version = 1);
|
||||||
|
QList<Viewport *> m_viewports;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Viewport : public QObject, public QtWaylandServer::wp_viewport
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Viewport(Surface *surface, wl_client *client, int id, int version);
|
||||||
|
|
||||||
|
QRectF m_source;
|
||||||
|
QSize m_destination;
|
||||||
|
|
||||||
|
Surface* m_surface;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void sourceChanged();
|
||||||
|
void destinationChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override;
|
||||||
|
void wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height) override;
|
||||||
|
|
||||||
|
void wp_viewport_destroy_resource(Resource *resource) override;
|
||||||
|
void wp_viewport_destroy(Resource *resource) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user