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.
This commit is contained in:
Vlad Zahorodnii 2022-11-16 22:42:02 +02:00
parent 69c9f19973
commit 528abfb00a
9 changed files with 66 additions and 47 deletions

View file

@ -534,8 +534,9 @@ void WaylandSeat::destroyTouchDevice()
} }
} }
WaylandBackend::WaylandBackend(QObject *parent) WaylandBackend::WaylandBackend(const WaylandBackendOptions &options, QObject *parent)
: OutputBackend(parent) : OutputBackend(parent)
, m_options(options)
{ {
#if HAVE_WAYLAND_EGL #if HAVE_WAYLAND_EGL
char const *drm_render_node = "/dev/dri/renderD128"; char const *drm_render_node = "/dev/dri/renderD128";
@ -570,7 +571,7 @@ WaylandBackend::~WaylandBackend()
bool WaylandBackend::initialize() bool WaylandBackend::initialize()
{ {
m_display = std::make_unique<WaylandDisplay>(); m_display = std::make_unique<WaylandDisplay>();
if (!m_display->initialize(deviceIdentifier())) { if (!m_display->initialize(m_options.socketName)) {
return false; return false;
} }
@ -613,9 +614,9 @@ void WaylandBackend::createOutputs()
{ {
// we need to multiply the initial window size with the scale in order to // we need to multiply the initial window size with the scale in order to
// create an output window of this size in the end // create an output window of this size in the end
const QSize nativeSize = initialWindowSize() * initialOutputScale(); const QSize pixelSize = m_options.outputSize * m_options.outputScale;
for (int i = 0; i < initialOutputCount(); i++) { for (int i = 0; i < m_options.outputCount; i++) {
WaylandOutput *output = createOutput(QStringLiteral("WL-%1").arg(i), nativeSize); WaylandOutput *output = createOutput(QStringLiteral("WL-%1").arg(i), pixelSize, m_options.outputScale);
m_outputs << output; m_outputs << output;
Q_EMIT outputAdded(output); Q_EMIT outputAdded(output);
output->updateEnabled(true); output->updateEnabled(true);
@ -624,10 +625,10 @@ void WaylandBackend::createOutputs()
Q_EMIT outputsQueried(); 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 *waylandOutput = new WaylandOutput(name, this);
waylandOutput->init(size); waylandOutput->init(size, scale);
// Wait until the output window is configured by the host compositor. // Wait until the output window is configured by the host compositor.
while (!waylandOutput->isReady()) { while (!waylandOutput->isReady()) {
@ -750,7 +751,7 @@ void WaylandBackend::clearDpmsFilter()
Output *WaylandBackend::createVirtualOutput(const QString &name, const QSize &size, double scale) 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) void WaylandBackend::removeVirtualOutput(Output *output)

View file

@ -220,6 +220,14 @@ private:
std::unique_ptr<WaylandInputDevice> m_touchDevice; std::unique_ptr<WaylandInputDevice> 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. * @brief Class encapsulating all Wayland data structures needed by the Egl backend.
* *
@ -231,7 +239,7 @@ class KWIN_EXPORT WaylandBackend : public OutputBackend
Q_OBJECT Q_OBJECT
public: public:
explicit WaylandBackend(QObject *parent = nullptr); explicit WaylandBackend(const WaylandBackendOptions &options, QObject *parent = nullptr);
~WaylandBackend() override; ~WaylandBackend() override;
bool initialize() override; bool initialize() override;
@ -288,8 +296,9 @@ Q_SIGNALS:
private: private:
void createOutputs(); void createOutputs();
void destroyOutputs(); 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<WaylandDisplay> m_display; std::unique_ptr<WaylandDisplay> m_display;
std::unique_ptr<WaylandSeat> m_seat; std::unique_ptr<WaylandSeat> m_seat;
WaylandEglBackend *m_eglBackend = nullptr; WaylandEglBackend *m_eglBackend = nullptr;

View file

@ -103,7 +103,7 @@ RenderLoop *WaylandOutput::renderLoop() const
return m_renderLoop.get(); return m_renderLoop.get();
} }
void WaylandOutput::init(const QSize &pixelSize) void WaylandOutput::init(const QSize &pixelSize, qreal scale)
{ {
m_renderLoop->setRefreshRate(s_refreshRate); m_renderLoop->setRefreshRate(s_refreshRate);
@ -112,7 +112,7 @@ void WaylandOutput::init(const QSize &pixelSize)
State initialState; State initialState;
initialState.modes = {mode}; initialState.modes = {mode};
initialState.currentMode = mode; initialState.currentMode = mode;
initialState.scale = m_backend->initialOutputScale(); initialState.scale = scale;
setState(initialState); setState(initialState);
m_surface->commit(KWayland::Client::Surface::CommitFlag::None); m_surface->commit(KWayland::Client::Surface::CommitFlag::None);

View file

@ -41,7 +41,7 @@ public:
RenderLoop *renderLoop() const override; RenderLoop *renderLoop() const override;
void init(const QSize &pixelSize); void init(const QSize &pixelSize, qreal scale);
bool isReady() const; bool isReady() const;
KWayland::Client::Surface *surface() const; KWayland::Client::Surface *surface() const;

View file

@ -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; int screen = 0;
xcb_connection_t *c = nullptr; xcb_connection_t *c = nullptr;
Display *xDisplay = XOpenDisplay(deviceIdentifier().constData()); Display *xDisplay = XOpenDisplay(m_options.display.toLatin1().constData());
if (xDisplay) { if (xDisplay) {
c = XGetXCBConnection(xDisplay); c = XGetXCBConnection(xDisplay);
XSetEventQueueOwner(xDisplay, XCBOwnsEventQueue); XSetEventQueueOwner(xDisplay, XCBOwnsEventQueue);
@ -268,12 +269,10 @@ void X11WindowedBackend::createOutputs()
// we need to multiply the initial window size with the scale in order to // we need to multiply the initial window size with the scale in order to
// create an output window of this size in the end // create an output window of this size in the end
const int pixelWidth = initialWindowSize().width() * initialOutputScale() + 0.5; const QSize pixelSize = m_options.outputSize * m_options.outputScale;
const int pixelHeight = initialWindowSize().height() * initialOutputScale() + 0.5; for (int i = 0; i < m_options.outputCount; ++i) {
for (int i = 0; i < initialOutputCount(); ++i) {
auto *output = new X11WindowedOutput(this); auto *output = new X11WindowedOutput(this);
output->init(QSize(pixelWidth, pixelHeight)); output->init(pixelSize, m_options.outputScale);
m_protocols = protocolsAtom; m_protocols = protocolsAtom;
m_deleteWindowProtocol = deleteWindowAtom; m_deleteWindowProtocol = deleteWindowAtom;

View file

@ -81,12 +81,20 @@ private:
X11WindowedBackend *m_backend; X11WindowedBackend *m_backend;
}; };
struct X11WindowedBackendOptions
{
QString display;
int outputCount = 1;
qreal outputScale = 1;
QSize outputSize = QSize(1024, 768);
};
class KWIN_EXPORT X11WindowedBackend : public OutputBackend class KWIN_EXPORT X11WindowedBackend : public OutputBackend
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit X11WindowedBackend(); explicit X11WindowedBackend(const X11WindowedBackendOptions &options);
~X11WindowedBackend() override; ~X11WindowedBackend() override;
bool initialize() override; bool initialize() override;
@ -146,6 +154,7 @@ private:
void initXInput(); void initXInput();
X11WindowedOutput *findOutput(xcb_window_t window) const; X11WindowedOutput *findOutput(xcb_window_t window) const;
X11WindowedBackendOptions m_options;
xcb_connection_t *m_connection = nullptr; xcb_connection_t *m_connection = nullptr;
xcb_screen_t *m_screen = nullptr; xcb_screen_t *m_screen = nullptr;
xcb_key_symbols_t *m_keySymbols = nullptr; xcb_key_symbols_t *m_keySymbols = nullptr;

View file

@ -74,7 +74,7 @@ SoftwareVsyncMonitor *X11WindowedOutput::vsyncMonitor() const
return m_vsyncMonitor.get(); 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 const int refreshRate = 60000; // TODO: get refresh rate via randr
m_renderLoop->setRefreshRate(refreshRate); m_renderLoop->setRefreshRate(refreshRate);
@ -85,7 +85,7 @@ void X11WindowedOutput::init(const QSize &pixelSize)
State initialState; State initialState;
initialState.modes = {mode}; initialState.modes = {mode};
initialState.currentMode = mode; initialState.currentMode = mode;
initialState.scale = m_backend->initialOutputScale(); initialState.scale = scale;
setState(initialState); setState(initialState);
const uint32_t eventMask = XCB_EVENT_MASK_KEY_PRESS const uint32_t eventMask = XCB_EVENT_MASK_KEY_PRESS

View file

@ -38,7 +38,7 @@ public:
RenderLoop *renderLoop() const override; RenderLoop *renderLoop() const override;
SoftwareVsyncMonitor *vsyncMonitor() const; SoftwareVsyncMonitor *vsyncMonitor() const;
void init(const QSize &pixelSize); void init(const QSize &pixelSize, qreal scale);
void resize(const QSize &pixelSize); void resize(const QSize &pixelSize);
xcb_window_t window() const xcb_window_t window() const

View file

@ -450,7 +450,6 @@ int main(int argc, char *argv[])
BackendType backendType; BackendType backendType;
QString pluginName; QString pluginName;
QSize initialWindowSize; QSize initialWindowSize;
QByteArray deviceIdentifier;
int outputCount = 1; int outputCount = 1;
qreal outputScale = 1; qreal outputScale = 1;
@ -459,10 +458,8 @@ int main(int argc, char *argv[])
backendType = BackendType::Kms; backendType = BackendType::Kms;
} else if (parser.isSet(x11DisplayOption)) { } else if (parser.isSet(x11DisplayOption)) {
backendType = BackendType::X11; backendType = BackendType::X11;
deviceIdentifier = parser.value(x11DisplayOption).toUtf8();
} else if (parser.isSet(waylandDisplayOption)) { } else if (parser.isSet(waylandDisplayOption)) {
backendType = BackendType::Wayland; backendType = BackendType::Wayland;
deviceIdentifier = parser.value(waylandDisplayOption).toUtf8();
} else if (parser.isSet(virtualFbOption)) { } else if (parser.isSet(virtualFbOption)) {
backendType = BackendType::Virtual; backendType = BackendType::Virtual;
} else { } else {
@ -560,31 +557,35 @@ int main(int argc, char *argv[])
a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); a.setSession(KWin::Session::create(KWin::Session::Type::Noop));
a.setOutputBackend(std::make_unique<KWin::VirtualBackend>()); a.setOutputBackend(std::make_unique<KWin::VirtualBackend>());
break; break;
case BackendType::X11: case BackendType::X11: {
a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); QString display = parser.value(x11DisplayOption);
a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>()); if (display.isEmpty()) {
if (deviceIdentifier.isEmpty()) { display = qgetenv("DISPLAY");
a.outputBackend()->setDeviceIdentifier(qgetenv("DISPLAY"));
} else {
a.outputBackend()->setDeviceIdentifier(deviceIdentifier);
} }
break;
case BackendType::Wayland:
a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); a.setSession(KWin::Session::create(KWin::Session::Type::Noop));
a.setOutputBackend(std::make_unique<KWin::Wayland::WaylandBackend>()); a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>(KWin::X11WindowedBackendOptions{
if (deviceIdentifier.isEmpty()) { .display = display,
a.outputBackend()->setDeviceIdentifier(qgetenv("WAYLAND_DISPLAY")); .outputCount = outputCount,
} else { .outputScale = outputScale,
a.outputBackend()->setDeviceIdentifier(deviceIdentifier); .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::WaylandBackend>(KWin::Wayland::WaylandBackendOptions{
.socketName = socketName,
.outputCount = outputCount,
.outputScale = outputScale,
.outputSize = initialWindowSize,
}));
break; 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); QObject::connect(&a, &KWin::Application::workspaceCreated, server, &KWin::WaylandServer::initWorkspace);
if (!server->socketName().isEmpty()) { if (!server->socketName().isEmpty()) {