diff --git a/main_wayland.cpp b/main_wayland.cpp --- a/main_wayland.cpp +++ b/main_wayland.cpp @@ -527,6 +527,12 @@ i18n("The height for windowed mode. Default height is 768."), QStringLiteral("height")); heightOption.setDefaultValue(QString::number(768)); + + QCommandLineOption scaleOption(QStringLiteral("scale"), + i18n("The scale for windowed mode. Default value is 1."), + QStringLiteral("scale")); + scaleOption.setDefaultValue(QString::number(1)); + QCommandLineOption outputCountOption(QStringLiteral("output-count"), i18n("The number of windows to open as outputs in windowed mode. Default value is 1"), QStringLiteral("height")); @@ -555,6 +561,7 @@ if (hasSizeOption) { parser.addOption(widthOption); parser.addOption(heightOption); + parser.addOption(scaleOption); } if (hasOutputCountOption) { parser.addOption(outputCountOption); @@ -633,6 +640,7 @@ QSize initialWindowSize; QByteArray deviceIdentifier; int outputCount = 1; + qreal outputScale = 1; #if HAVE_DRM if (hasDrmOption && parser.isSet(drmOption)) { @@ -652,6 +660,13 @@ std::cerr << "FATAL ERROR incorrect value for height" << std::endl; return 1; } + const qreal scale = parser.value(scaleOption).toDouble(&ok); + if (!ok || scale < 1) { + std::cerr << "FATAL ERROR incorrect value for scale" << std::endl; + return 1; + } + + outputScale = scale; initialWindowSize = QSize(width, height); } @@ -733,6 +748,7 @@ if (initialWindowSize.isValid()) { a.platform()->setInitialWindowSize(initialWindowSize); } + a.platform()->setInitialOutputScale(outputScale); a.platform()->setInitialOutputCount(outputCount); QObject::connect(&a, &KWin::Application::workspaceCreated, server, &KWin::WaylandServer::initWorkspace); diff --git a/platform.h b/platform.h --- a/platform.h +++ b/platform.h @@ -104,6 +104,14 @@ * Base implementation returns one QRect positioned at 0/0 with screenSize() as size. **/ virtual QVector screenGeometries() const; + + /** + * Implementing subclasses should provide all geometries in case the backend represents + * a basic screen and uses the BasicScreens. + * + * Base implementation returns a screen with a scale of 1. + **/ + virtual QVector screenScales() const; /** * Implement this method to receive configuration change requests through KWayland's * OutputManagement interface. @@ -268,6 +276,12 @@ void setInitialOutputCount(int count) { m_initialOutputCount = count; } + qreal initialOutputScale() const { + return m_initialOutputScale; + } + void setInitialOutputScale(qreal scale) { + m_initialOutputScale = scale; + } public Q_SLOTS: void pointerMotion(const QPointF &position, quint32 time); @@ -350,6 +364,7 @@ bool m_pointerWarping = false; bool m_outputsEnabled = true; int m_initialOutputCount = 1; + qreal m_initialOutputScale = 1; EGLDisplay m_eglDisplay; int m_hideCursorCounter = 0; }; diff --git a/platform.cpp b/platform.cpp --- a/platform.cpp +++ b/platform.cpp @@ -343,6 +343,11 @@ return QVector({QRect(QPoint(0, 0), screenSize())}); } +QVector Platform::screenScales() const +{ + return QVector({1}); +} + bool Platform::requiresCompositing() const { return true; diff --git a/plugins/platforms/x11/windowed/x11windowed_backend.h b/plugins/platforms/x11/windowed/x11windowed_backend.h --- a/plugins/platforms/x11/windowed/x11windowed_backend.h +++ b/plugins/platforms/x11/windowed/x11windowed_backend.h @@ -47,6 +47,7 @@ virtual ~X11WindowedBackend(); void init() override; QVector screenGeometries() const override; + QVector screenScales() const override; xcb_connection_t *connection() const { return m_connection; diff --git a/plugins/platforms/x11/windowed/x11windowed_backend.cpp b/plugins/platforms/x11/windowed/x11windowed_backend.cpp --- a/plugins/platforms/x11/windowed/x11windowed_backend.cpp +++ b/plugins/platforms/x11/windowed/x11windowed_backend.cpp @@ -472,4 +472,11 @@ return ret; } +QVector X11WindowedBackend::screenScales() const +{ + QVector ret; + ret.fill(initialOutputScale(), m_windows.count()); + return ret; +} + } diff --git a/screens.h b/screens.h --- a/screens.h +++ b/screens.h @@ -86,6 +86,11 @@ * @see size() **/ virtual QSize size(int screen) const = 0; + + /* + * The output scale for this display, for use by high DPI displays + */ + virtual qreal scale(int screen) const; /** * The bounding size of all screens combined. Overlapping areas * are not counted multiple times. @@ -164,11 +169,13 @@ QRect geometry(int screen) const override; int number(const QPoint &pos) const override; QSize size(int screen) const override; + qreal scale(int screen) const override; void updateCount() override; private: Platform *m_backend; QVector m_geometries; + QVector m_scales; }; inline diff --git a/screens.cpp b/screens.cpp --- a/screens.cpp +++ b/screens.cpp @@ -91,6 +91,13 @@ return 60.0f; } +qreal Screens::scale(int screen) const +{ + Q_UNUSED(screen) + qCWarning(KWIN_CORE, "%s::scale(qreal screen) is a stub, please reimplement it!", metaObject()->className()); + return 1; +} + void Screens::reconfigure() { if (!m_config) { @@ -213,9 +220,18 @@ return QSize(); } +qreal BasicScreens::scale(int screen) const +{ + if (screen < m_scales.count()) { + return m_scales.at(screen); + } + return 1; +} + void BasicScreens::updateCount() { m_geometries = m_backend->screenGeometries(); + m_scales = m_backend->screenScales(); setCount(m_geometries.count()); } diff --git a/wayland_server.cpp b/wayland_server.cpp --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -352,6 +352,7 @@ Q_ASSERT(s); for (int i = 0; i < s->count(); ++i) { OutputInterface *output = m_display->createOutput(m_display); + output->setScale(s->scale(i)); const QRect &geo = s->geometry(i); output->setGlobalPosition(geo.topLeft()); output->setPhysicalSize(geo.size() / 3.8);