From 528abfb00aca494c0ddcfa9221d36694a8fb1ca2 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 16 Nov 2022 22:42:02 +0200 Subject: [PATCH] backends/{x11,wayland}: Rework passing initial configuration to windowed backends Currently, OutputBackend stores the initial state for windowed backends. It's messy because the backends can have different needs. Instead, make windowed backends take an Options struct with all possible options. --- src/backends/wayland/wayland_backend.cpp | 17 +++---- src/backends/wayland/wayland_backend.h | 13 ++++- src/backends/wayland/wayland_output.cpp | 4 +- src/backends/wayland/wayland_output.h | 2 +- .../x11/windowed/x11_windowed_backend.cpp | 13 +++-- .../x11/windowed/x11_windowed_backend.h | 11 ++++- .../x11/windowed/x11_windowed_output.cpp | 4 +- .../x11/windowed/x11_windowed_output.h | 2 +- src/main_wayland.cpp | 47 ++++++++++--------- 9 files changed, 66 insertions(+), 47 deletions(-) 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()) {