xwayland: Don't exit if failed to read DISPLAY

We want the compositor to survive even if something goes wrong when
starting Xwayland.
master
Vlad Zahorodnii 2020-09-08 12:35:47 +03:00
parent 8697bcd7e9
commit c0da7faa6f
2 changed files with 45 additions and 37 deletions

View File

@ -39,25 +39,23 @@
#include <sys/socket.h>
#include <cerrno>
#include <cstring>
#include <iostream>
static void readDisplay(int pipe)
static QByteArray readDisplay(int pipe)
{
QByteArray displayName;
QFile readPipe;
if (!readPipe.open(pipe, QIODevice::ReadOnly)) {
qCWarning(KWIN_XWL) << "Failed to open X11 display name pipe:" << readPipe.errorString();
exit(1);
} else {
displayName = readPipe.readLine();
displayName.prepend(QByteArrayLiteral(":"));
displayName.remove(displayName.size() - 1, 1);
}
QByteArray displayNumber = readPipe.readLine();
displayNumber.prepend(QByteArray(":"));
displayNumber.remove(displayNumber.size() -1, 1);
std::cout << "X-Server started on display " << displayNumber.constData() << std::endl;
setenv("DISPLAY", displayNumber.constData(), true);
// close our pipe
close(pipe);
return displayName;
}
namespace KWin
@ -228,10 +226,9 @@ void Xwayland::uninstallSocketNotifier()
void Xwayland::handleXwaylandStarted()
{
QFutureWatcher<void> *watcher = new QFutureWatcher<void>(this);
connect(watcher, &QFutureWatcher<void>::finished, this, &Xwayland::continueStartupWithX);
connect(watcher, &QFutureWatcher<void>::finished, watcher, &QFutureWatcher<void>::deleteLater);
watcher->setFuture(QtConcurrent::run(readDisplay, m_displayFileDescriptor));
m_watcher = new QFutureWatcher<QByteArray>(this);
connect(m_watcher, &QFutureWatcher<QByteArray>::finished, this, &Xwayland::handleXwaylandReady);
m_watcher->setFuture(QtConcurrent::run(readDisplay, m_displayFileDescriptor));
}
void Xwayland::handleXwaylandFinished(int exitCode, QProcess::ExitStatus exitStatus)
@ -299,6 +296,36 @@ void Xwayland::handleXwaylandError(QProcess::ProcessError error)
emit errorOccurred();
}
void Xwayland::handleXwaylandReady()
{
m_displayName = m_watcher->result();
m_watcher->deleteLater();
m_watcher = nullptr;
if (!createX11Connection()) {
emit errorOccurred();
return;
}
qCInfo(KWIN_XWL) << "Xwayland server started on display" << m_displayName;
qputenv("DISPLAY", m_displayName);
// create selection owner for WM_S0 - magic X display number expected by XWayland
KSelectionOwner owner("WM_S0", kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
owner.claim(true);
DataBridge::create(this);
auto env = m_app->processStartupEnvironment();
env.insert(QStringLiteral("DISPLAY"), m_displayName);
m_app->setProcessStartupEnvironment(env);
emit started();
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
}
bool Xwayland::createX11Connection()
{
xcb_connection_t *connection = xcb_connect_to_fd(m_xcbConnectionFd, nullptr);
@ -352,28 +379,6 @@ void Xwayland::destroyX11Connection()
emit m_app->x11ConnectionChanged();
}
void Xwayland::continueStartupWithX()
{
if (!createX11Connection()) {
emit errorOccurred();
return;
}
// create selection owner for WM_S0 - magic X display number expected by XWayland
KSelectionOwner owner("WM_S0", kwinApp()->x11Connection(), kwinApp()->x11RootWindow());
owner.claim(true);
DataBridge::create(this);
auto env = m_app->processStartupEnvironment();
env.insert(QStringLiteral("DISPLAY"), QString::fromUtf8(qgetenv("DISPLAY")));
m_app->setProcessStartupEnvironment(env);
emit started();
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
}
DragEventReply Xwayland::dragMoveFilter(Toplevel *target, const QPoint &pos)
{
DataBridge *bridge = DataBridge::self();

View File

@ -12,6 +12,7 @@
#include "xwayland_interface.h"
#include <QFutureWatcher>
#include <QProcess>
#include <QSocketNotifier>
@ -85,6 +86,7 @@ private Q_SLOTS:
void handleXwaylandFinished(int exitCode, QProcess::ExitStatus exitStatus);
void handleXwaylandCrashed();
void handleXwaylandError(QProcess::ProcessError error);
void handleXwaylandReady();
private:
void installSocketNotifier();
@ -92,7 +94,6 @@ private:
bool createX11Connection();
void destroyX11Connection();
void continueStartupWithX();
DragEventReply dragMoveFilter(Toplevel *target, const QPoint &pos) override;
@ -101,6 +102,8 @@ private:
QProcess *m_xwaylandProcess = nullptr;
QSocketNotifier *m_socketNotifier = nullptr;
QTimer *m_resetCrashCountTimer = nullptr;
QByteArray m_displayName;
QFutureWatcher<QByteArray> *m_watcher = nullptr;
ApplicationWaylandAbstract *m_app;
int m_crashCount = 0;