diff --git a/src/backends/wayland/wayland_backend.cpp b/src/backends/wayland/wayland_backend.cpp index 72bc30092e..af1a7230e1 100644 --- a/src/backends/wayland/wayland_backend.cpp +++ b/src/backends/wayland/wayland_backend.cpp @@ -534,8 +534,9 @@ void WaylandSeat::destroyTouchDevice() } } -WaylandBackend::WaylandBackend(QObject *parent) +WaylandBackend::WaylandBackend(const WaylandBackendOptions &options, QObject *parent) : OutputBackend(parent) + , m_options(options) { #if HAVE_WAYLAND_EGL char const *drm_render_node = "/dev/dri/renderD128"; @@ -570,7 +571,7 @@ WaylandBackend::~WaylandBackend() bool WaylandBackend::initialize() { m_display = std::make_unique(); - if (!m_display->initialize(deviceIdentifier())) { + if (!m_display->initialize(m_options.socketName)) { return false; } @@ -613,9 +614,9 @@ void WaylandBackend::createOutputs() { // we need to multiply the initial window size with the scale in order to // create an output window of this size in the end - const QSize nativeSize = initialWindowSize() * initialOutputScale(); - for (int i = 0; i < initialOutputCount(); i++) { - WaylandOutput *output = createOutput(QStringLiteral("WL-%1").arg(i), nativeSize); + const QSize pixelSize = m_options.outputSize * m_options.outputScale; + for (int i = 0; i < m_options.outputCount; i++) { + WaylandOutput *output = createOutput(QStringLiteral("WL-%1").arg(i), pixelSize, m_options.outputScale); m_outputs << output; Q_EMIT outputAdded(output); output->updateEnabled(true); @@ -624,10 +625,10 @@ void WaylandBackend::createOutputs() Q_EMIT outputsQueried(); } -WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &size) +WaylandOutput *WaylandBackend::createOutput(const QString &name, const QSize &size, qreal scale) { WaylandOutput *waylandOutput = new WaylandOutput(name, this); - waylandOutput->init(size); + waylandOutput->init(size, scale); // Wait until the output window is configured by the host compositor. while (!waylandOutput->isReady()) { @@ -750,7 +751,7 @@ void WaylandBackend::clearDpmsFilter() Output *WaylandBackend::createVirtualOutput(const QString &name, const QSize &size, double scale) { - return createOutput(name, size * scale); + return createOutput(name, size * scale, scale); } void WaylandBackend::removeVirtualOutput(Output *output) diff --git a/src/backends/wayland/wayland_backend.h b/src/backends/wayland/wayland_backend.h index 80f92c0f7f..cf696ee627 100644 --- a/src/backends/wayland/wayland_backend.h +++ b/src/backends/wayland/wayland_backend.h @@ -220,6 +220,14 @@ private: std::unique_ptr m_touchDevice; }; +struct WaylandBackendOptions +{ + QString socketName; + int outputCount = 1; + qreal outputScale = 1; + QSize outputSize = QSize(1024, 768); +}; + /** * @brief Class encapsulating all Wayland data structures needed by the Egl backend. * @@ -231,7 +239,7 @@ class KWIN_EXPORT WaylandBackend : public OutputBackend Q_OBJECT public: - explicit WaylandBackend(QObject *parent = nullptr); + explicit WaylandBackend(const WaylandBackendOptions &options, QObject *parent = nullptr); ~WaylandBackend() override; bool initialize() override; @@ -288,8 +296,9 @@ Q_SIGNALS: private: void createOutputs(); void destroyOutputs(); - WaylandOutput *createOutput(const QString &name, const QSize &size); + WaylandOutput *createOutput(const QString &name, const QSize &size, qreal scale); + WaylandBackendOptions m_options; std::unique_ptr m_display; std::unique_ptr m_seat; WaylandEglBackend *m_eglBackend = nullptr; diff --git a/src/backends/wayland/wayland_output.cpp b/src/backends/wayland/wayland_output.cpp index 0a42b477ab..7d841898e0 100644 --- a/src/backends/wayland/wayland_output.cpp +++ b/src/backends/wayland/wayland_output.cpp @@ -103,7 +103,7 @@ RenderLoop *WaylandOutput::renderLoop() const return m_renderLoop.get(); } -void WaylandOutput::init(const QSize &pixelSize) +void WaylandOutput::init(const QSize &pixelSize, qreal scale) { m_renderLoop->setRefreshRate(s_refreshRate); @@ -112,7 +112,7 @@ void WaylandOutput::init(const QSize &pixelSize) State initialState; initialState.modes = {mode}; initialState.currentMode = mode; - initialState.scale = m_backend->initialOutputScale(); + initialState.scale = scale; setState(initialState); m_surface->commit(KWayland::Client::Surface::CommitFlag::None); diff --git a/src/backends/wayland/wayland_output.h b/src/backends/wayland/wayland_output.h index 932ca22054..4569fa9667 100644 --- a/src/backends/wayland/wayland_output.h +++ b/src/backends/wayland/wayland_output.h @@ -41,7 +41,7 @@ public: RenderLoop *renderLoop() const override; - void init(const QSize &pixelSize); + void init(const QSize &pixelSize, qreal scale); bool isReady() const; KWayland::Client::Surface *surface() const; diff --git a/src/backends/x11/windowed/x11_windowed_backend.cpp b/src/backends/x11/windowed/x11_windowed_backend.cpp index 9117ec4b0c..410562fa0b 100644 --- a/src/backends/x11/windowed/x11_windowed_backend.cpp +++ b/src/backends/x11/windowed/x11_windowed_backend.cpp @@ -153,7 +153,8 @@ void X11WindowedInputBackend::initialize() } } -X11WindowedBackend::X11WindowedBackend() +X11WindowedBackend::X11WindowedBackend(const X11WindowedBackendOptions &options) + : m_options(options) { } @@ -181,7 +182,7 @@ bool X11WindowedBackend::initialize() { int screen = 0; xcb_connection_t *c = nullptr; - Display *xDisplay = XOpenDisplay(deviceIdentifier().constData()); + Display *xDisplay = XOpenDisplay(m_options.display.toLatin1().constData()); if (xDisplay) { c = XGetXCBConnection(xDisplay); XSetEventQueueOwner(xDisplay, XCBOwnsEventQueue); @@ -268,12 +269,10 @@ void X11WindowedBackend::createOutputs() // we need to multiply the initial window size with the scale in order to // create an output window of this size in the end - const int pixelWidth = initialWindowSize().width() * initialOutputScale() + 0.5; - const int pixelHeight = initialWindowSize().height() * initialOutputScale() + 0.5; - - for (int i = 0; i < initialOutputCount(); ++i) { + const QSize pixelSize = m_options.outputSize * m_options.outputScale; + for (int i = 0; i < m_options.outputCount; ++i) { auto *output = new X11WindowedOutput(this); - output->init(QSize(pixelWidth, pixelHeight)); + output->init(pixelSize, m_options.outputScale); m_protocols = protocolsAtom; m_deleteWindowProtocol = deleteWindowAtom; diff --git a/src/backends/x11/windowed/x11_windowed_backend.h b/src/backends/x11/windowed/x11_windowed_backend.h index ac3a0d9a39..ed1898b751 100644 --- a/src/backends/x11/windowed/x11_windowed_backend.h +++ b/src/backends/x11/windowed/x11_windowed_backend.h @@ -81,12 +81,20 @@ private: X11WindowedBackend *m_backend; }; +struct X11WindowedBackendOptions +{ + QString display; + int outputCount = 1; + qreal outputScale = 1; + QSize outputSize = QSize(1024, 768); +}; + class KWIN_EXPORT X11WindowedBackend : public OutputBackend { Q_OBJECT public: - explicit X11WindowedBackend(); + explicit X11WindowedBackend(const X11WindowedBackendOptions &options); ~X11WindowedBackend() override; bool initialize() override; @@ -146,6 +154,7 @@ private: void initXInput(); X11WindowedOutput *findOutput(xcb_window_t window) const; + X11WindowedBackendOptions m_options; xcb_connection_t *m_connection = nullptr; xcb_screen_t *m_screen = nullptr; xcb_key_symbols_t *m_keySymbols = nullptr; diff --git a/src/backends/x11/windowed/x11_windowed_output.cpp b/src/backends/x11/windowed/x11_windowed_output.cpp index ef1a79bcf8..18253e1425 100644 --- a/src/backends/x11/windowed/x11_windowed_output.cpp +++ b/src/backends/x11/windowed/x11_windowed_output.cpp @@ -74,7 +74,7 @@ SoftwareVsyncMonitor *X11WindowedOutput::vsyncMonitor() const return m_vsyncMonitor.get(); } -void X11WindowedOutput::init(const QSize &pixelSize) +void X11WindowedOutput::init(const QSize &pixelSize, qreal scale) { const int refreshRate = 60000; // TODO: get refresh rate via randr m_renderLoop->setRefreshRate(refreshRate); @@ -85,7 +85,7 @@ void X11WindowedOutput::init(const QSize &pixelSize) State initialState; initialState.modes = {mode}; initialState.currentMode = mode; - initialState.scale = m_backend->initialOutputScale(); + initialState.scale = scale; setState(initialState); const uint32_t eventMask = XCB_EVENT_MASK_KEY_PRESS diff --git a/src/backends/x11/windowed/x11_windowed_output.h b/src/backends/x11/windowed/x11_windowed_output.h index df3e5f314b..1ad22b8927 100644 --- a/src/backends/x11/windowed/x11_windowed_output.h +++ b/src/backends/x11/windowed/x11_windowed_output.h @@ -38,7 +38,7 @@ public: RenderLoop *renderLoop() const override; SoftwareVsyncMonitor *vsyncMonitor() const; - void init(const QSize &pixelSize); + void init(const QSize &pixelSize, qreal scale); void resize(const QSize &pixelSize); xcb_window_t window() const diff --git a/src/main_wayland.cpp b/src/main_wayland.cpp index 9e39a5912b..c97b7a849f 100644 --- a/src/main_wayland.cpp +++ b/src/main_wayland.cpp @@ -450,7 +450,6 @@ int main(int argc, char *argv[]) BackendType backendType; QString pluginName; QSize initialWindowSize; - QByteArray deviceIdentifier; int outputCount = 1; qreal outputScale = 1; @@ -459,10 +458,8 @@ int main(int argc, char *argv[]) backendType = BackendType::Kms; } else if (parser.isSet(x11DisplayOption)) { backendType = BackendType::X11; - deviceIdentifier = parser.value(x11DisplayOption).toUtf8(); } else if (parser.isSet(waylandDisplayOption)) { backendType = BackendType::Wayland; - deviceIdentifier = parser.value(waylandDisplayOption).toUtf8(); } else if (parser.isSet(virtualFbOption)) { backendType = BackendType::Virtual; } else { @@ -560,31 +557,35 @@ int main(int argc, char *argv[]) a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); a.setOutputBackend(std::make_unique()); break; - case BackendType::X11: - a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); - a.setOutputBackend(std::make_unique()); - if (deviceIdentifier.isEmpty()) { - a.outputBackend()->setDeviceIdentifier(qgetenv("DISPLAY")); - } else { - a.outputBackend()->setDeviceIdentifier(deviceIdentifier); + case BackendType::X11: { + QString display = parser.value(x11DisplayOption); + if (display.isEmpty()) { + display = qgetenv("DISPLAY"); } - break; - case BackendType::Wayland: a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); - a.setOutputBackend(std::make_unique()); - if (deviceIdentifier.isEmpty()) { - a.outputBackend()->setDeviceIdentifier(qgetenv("WAYLAND_DISPLAY")); - } else { - a.outputBackend()->setDeviceIdentifier(deviceIdentifier); - } + a.setOutputBackend(std::make_unique(KWin::X11WindowedBackendOptions{ + .display = display, + .outputCount = outputCount, + .outputScale = outputScale, + .outputSize = initialWindowSize, + })); + break; + } + case BackendType::Wayland: { + QString socketName = parser.value(waylandDisplayOption); + if (socketName.isEmpty()) { + socketName = qgetenv("WAYLAND_DISPLAY"); + } + a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); + a.setOutputBackend(std::make_unique(KWin::Wayland::WaylandBackendOptions{ + .socketName = socketName, + .outputCount = outputCount, + .outputScale = outputScale, + .outputSize = initialWindowSize, + })); break; } - - if (initialWindowSize.isValid()) { - a.outputBackend()->setInitialWindowSize(initialWindowSize); } - a.outputBackend()->setInitialOutputScale(outputScale); - a.outputBackend()->setInitialOutputCount(outputCount); QObject::connect(&a, &KWin::Application::workspaceCreated, server, &KWin::WaylandServer::initWorkspace); if (!server->socketName().isEmpty()) {