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)
, 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<WaylandDisplay>();
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)

View file

@ -220,6 +220,14 @@ private:
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.
*
@ -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<WaylandDisplay> m_display;
std::unique_ptr<WaylandSeat> m_seat;
WaylandEglBackend *m_eglBackend = nullptr;

View file

@ -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);

View file

@ -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;

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;
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;

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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<KWin::VirtualBackend>());
break;
case BackendType::X11:
a.setSession(KWin::Session::create(KWin::Session::Type::Noop));
a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>());
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<KWin::Wayland::WaylandBackend>());
if (deviceIdentifier.isEmpty()) {
a.outputBackend()->setDeviceIdentifier(qgetenv("WAYLAND_DISPLAY"));
} else {
a.outputBackend()->setDeviceIdentifier(deviceIdentifier);
}
a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>(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::WaylandBackend>(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()) {