diff --git a/autotests/integration/internal_window.cpp b/autotests/integration/internal_window.cpp
index 0830452087..bacdc2030a 100644
--- a/autotests/integration/internal_window.cpp
+++ b/autotests/integration/internal_window.cpp
@@ -33,6 +33,8 @@ along with this program. If not, see .
#include
#include
+#include
+
#include
using namespace KWayland::Client;
@@ -64,6 +66,7 @@ private Q_SLOTS:
void testModifierClickUnrestrictedMove();
void testModifierScroll();
void testPopup();
+ void testScale();
};
class HelperWindow : public QRasterWindow
@@ -687,6 +690,29 @@ void InternalWindowTest::testPopup()
QCOMPARE(internalClient->isPopupWindow(), true);
}
+void InternalWindowTest::testScale()
+{
+ QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection,
+ Q_ARG(int, 2),
+ Q_ARG(QVector, QVector({QRect(0,0,1280, 1024), QRect(1280/2, 0, 1280, 1024)})),
+ Q_ARG(QVector, QVector({2,2})));
+
+ QSignalSpy clientAddedSpy(waylandServer(), &WaylandServer::shellClientAdded);
+ QVERIFY(clientAddedSpy.isValid());
+ HelperWindow win;
+ win.setGeometry(0, 0, 100, 100);
+ win.setFlags(win.flags() | Qt::Popup);
+ win.show();
+ QCOMPARE(win.devicePixelRatio(), 2.0);
+ QVERIFY(clientAddedSpy.wait());
+ QCOMPARE(clientAddedSpy.count(), 1);
+ auto internalClient = clientAddedSpy.first().first().value();
+ QCOMPARE(internalClient->surface()->scale(), 2);
+
+ QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
+}
+
+
}
WAYLANDTEST_MAIN(KWin::InternalWindowTest)
diff --git a/autotests/integration/kwin_wayland_test.h b/autotests/integration/kwin_wayland_test.h
index 4c7b183c3d..6d62e0a7c6 100644
--- a/autotests/integration/kwin_wayland_test.h
+++ b/autotests/integration/kwin_wayland_test.h
@@ -207,9 +207,9 @@ int main(int argc, char *argv[]) \
}
#ifdef NO_XWAYLAND
-#define WAYLANDTEST_MAIN(TestObject) WAYLANDTEST_MAIN_HELPER(TestObject, QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling), KWin::Application::OperationModeWaylandOnly)
+#define WAYLANDTEST_MAIN(TestObject) WAYLANDTEST_MAIN_HELPER(TestObject, QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps), KWin::Application::OperationModeWaylandOnly)
#else
-#define WAYLANDTEST_MAIN(TestObject) WAYLANDTEST_MAIN_HELPER(TestObject, QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling), KWin::Application::OperationModeXwayland)
+#define WAYLANDTEST_MAIN(TestObject) WAYLANDTEST_MAIN_HELPER(TestObject, QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps), KWin::Application::OperationModeXwayland)
#endif
#endif
diff --git a/main_wayland.cpp b/main_wayland.cpp
index f2cd475179..cd8a98c9f9 100644
--- a/main_wayland.cpp
+++ b/main_wayland.cpp
@@ -553,7 +553,7 @@ int main(int argc, char * argv[])
qunsetenv("QT_DEVICE_PIXEL_RATIO");
qputenv("QT_IM_MODULE", "qtvirtualkeyboard");
qputenv("QSG_RENDER_LOOP", "basic");
- QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
+ QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
KWin::ApplicationWayland a(argc, argv);
a.setupTranslator();
// reset QT_QPA_PLATFORM to a sane value for any processes started from KWin
diff --git a/plugins/qpa/backingstore.cpp b/plugins/qpa/backingstore.cpp
index 2ffe084cb8..a2f4fd2ac4 100644
--- a/plugins/qpa/backingstore.cpp
+++ b/plugins/qpa/backingstore.cpp
@@ -47,6 +47,7 @@ BackingStore::BackingStore(QWindow *w, KWayland::Client::ShmPool *shm)
}
const QSize size = m_backBuffer.size();
m_backBuffer = QImage(b->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
+ m_backBuffer.setDevicePixelRatio(scale());
}
);
}
@@ -61,7 +62,7 @@ QPaintDevice *BackingStore::paintDevice()
void BackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents)
- m_size = size;
+ m_size = size * scale();
if (!m_buffer) {
return;
}
@@ -73,13 +74,15 @@ void BackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &o
{
Q_UNUSED(region)
Q_UNUSED(offset)
- auto s = static_cast(window->handle())->surface();
+
+ auto w = static_cast(window->handle());
+ auto s = w->surface();
if (!s) {
return;
}
s->attachBuffer(m_buffer);
// TODO: proper damage region
- s->damage(QRect(QPoint(0, 0), m_backBuffer.size()));
+ s->damage(QRect(QPoint(0, 0), m_backBuffer.size() / scale()));
s->commit(KWayland::Client::Surface::CommitFlag::None);
waylandServer()->internalClientConection()->flush();
waylandServer()->dispatch();
@@ -108,6 +111,7 @@ void BackingStore::beginPaint(const QRegion&)
auto b = m_buffer.toStrongRef();
b->setUsed(true);
m_backBuffer = QImage(b->address(), m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied);
+ m_backBuffer.setDevicePixelRatio(scale());
if (oldBuffer) {
b->copy(oldBuffer->address());
} else {
@@ -115,5 +119,10 @@ void BackingStore::beginPaint(const QRegion&)
}
}
+int BackingStore::scale() const
+{
+ return static_cast(window()->handle())->scale();
+}
+
}
}
diff --git a/plugins/qpa/backingstore.h b/plugins/qpa/backingstore.h
index 0e00de6357..53c25a7788 100644
--- a/plugins/qpa/backingstore.h
+++ b/plugins/qpa/backingstore.h
@@ -48,6 +48,7 @@ public:
void beginPaint(const QRegion &) override;
private:
+ int scale() const;
KWayland::Client::ShmPool *m_shm;
QWeakPointer m_buffer;
QImage m_backBuffer;
diff --git a/plugins/qpa/window.cpp b/plugins/qpa/window.cpp
index 37ce0e7254..04deadbe8b 100644
--- a/plugins/qpa/window.cpp
+++ b/plugins/qpa/window.cpp
@@ -20,6 +20,7 @@ along with this program. If not, see .
#define WL_EGL_PLATFORM 1
#include "integration.h"
#include "window.h"
+#include "screens.h"
#include "../../shell_client.h"
#include "../../wayland_server.h"
#include
@@ -44,7 +45,10 @@ Window::Window(QWindow *window, KWayland::Client::Surface *surface, KWayland::Cl
, m_shellSurface(shellSurface)
, m_windowId(++s_windowId)
, m_integration(integration)
+ , m_scale(screens()->maxScale())
{
+ m_surface->setScale(m_scale);
+
QObject::connect(m_surface, &QObject::destroyed, window, [this] { m_surface = nullptr;});
QObject::connect(m_shellSurface, &QObject::destroyed, window, [this] { m_shellSurface = nullptr;});
waylandServer()->internalClientConection()->flush();
@@ -94,14 +98,17 @@ void Window::setGeometry(const QRect &rect)
if (rect.height() != oldRect.height()) {
emit window()->heightChanged(rect.height());
}
+
+ const QSize nativeSize = rect.size() * m_scale;
+
if (m_contentFBO) {
- if (m_contentFBO->width() != geometry().width() || m_contentFBO->height() != geometry().height()) {
+ if (m_contentFBO->size() != nativeSize) {
m_resized = true;
}
}
#if HAVE_WAYLAND_EGL
if (m_eglWaylandWindow) {
- wl_egl_window_resize(m_eglWaylandWindow, geometry().width(), geometry().height(), 0, 0);
+ wl_egl_window_resize(m_eglWaylandWindow, nativeSize.width(), nativeSize.height(), 0, 0);
}
#endif
QWindowSystemInterface::handleGeometryChange(window(), geometry());
@@ -124,7 +131,7 @@ void Window::unmap()
void Window::createEglSurface(EGLDisplay dpy, EGLConfig config)
{
#if HAVE_WAYLAND_EGL
- const QSize size = window()->size();
+ const QSize size = window()->size() * m_scale;
m_eglWaylandWindow = wl_egl_window_create(*m_surface, size.width(), size.height());
if (!m_eglWaylandWindow) {
return;
@@ -158,7 +165,8 @@ void Window::createFBO()
if (m_contentFBO && r.size().isEmpty()) {
return;
}
- m_contentFBO.reset(new QOpenGLFramebufferObject(r.width(), r.height(), QOpenGLFramebufferObject::CombinedDepthStencil));
+ const QSize nativeSize = r.size() * m_scale;
+ m_contentFBO.reset(new QOpenGLFramebufferObject(nativeSize.width(), nativeSize.height(), QOpenGLFramebufferObject::CombinedDepthStencil));
if (!m_contentFBO->isValid()) {
qCWarning(KWIN_QPA) << "Content FBO is not valid";
}
@@ -174,5 +182,15 @@ ShellClient *Window::shellClient()
return m_shellClient;
}
+int Window::scale() const
+{
+ return m_scale;
+}
+
+qreal Window::devicePixelRatio() const
+{
+ return m_scale;
+}
+
}
}
diff --git a/plugins/qpa/window.h b/plugins/qpa/window.h
index e8caedc6e0..bc334c359c 100644
--- a/plugins/qpa/window.h
+++ b/plugins/qpa/window.h
@@ -74,6 +74,9 @@ public:
}
void createEglSurface(EGLDisplay dpy, EGLConfig config);
+ int scale() const;
+ qreal devicePixelRatio() const override;
+
void bindContentFBO();
const QSharedPointer &contentFBO() const {
return m_contentFBO;
@@ -96,6 +99,7 @@ private:
#endif
quint32 m_windowId;
const Integration *m_integration;
+ int m_scale = 1;
};
}
diff --git a/shell_client.cpp b/shell_client.cpp
index 4255d6394d..810aa2fc71 100644
--- a/shell_client.cpp
+++ b/shell_client.cpp
@@ -510,9 +510,7 @@ void ShellClient::setInternalFramebufferObject(const QSharedPointersize();
+ m_clientSize = fbo->size() / surface()->scale();
markAsMapped();
doSetGeometry(QRect(geom.topLeft(), m_clientSize));
Toplevel::setInternalFramebufferObject(fbo);