xwayland: Don't exit if failed to read DISPLAY

We want the compositor to survive even if something goes wrong when
starting Xwayland.
remotes/origin/work/xdg-shell-maximize-one-dimensional
Vlad Zahorodnii 6 years ago
parent 8697bcd7e9
commit c0da7faa6f
  1. 77
      xwl/xwayland.cpp
  2. 5
      xwl/xwayland.h

@ -39,25 +39,23 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <iostream>
static void readDisplay(int pipe) static QByteArray readDisplay(int pipe)
{ {
QByteArray displayName;
QFile readPipe; QFile readPipe;
if (!readPipe.open(pipe, QIODevice::ReadOnly)) { if (!readPipe.open(pipe, QIODevice::ReadOnly)) {
qCWarning(KWIN_XWL) << "Failed to open X11 display name pipe:" << readPipe.errorString(); 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 our pipe
close(pipe); close(pipe);
return displayName;
} }
namespace KWin namespace KWin
@ -228,10 +226,9 @@ void Xwayland::uninstallSocketNotifier()
void Xwayland::handleXwaylandStarted() void Xwayland::handleXwaylandStarted()
{ {
QFutureWatcher<void> *watcher = new QFutureWatcher<void>(this); m_watcher = new QFutureWatcher<QByteArray>(this);
connect(watcher, &QFutureWatcher<void>::finished, this, &Xwayland::continueStartupWithX); connect(m_watcher, &QFutureWatcher<QByteArray>::finished, this, &Xwayland::handleXwaylandReady);
connect(watcher, &QFutureWatcher<void>::finished, watcher, &QFutureWatcher<void>::deleteLater); m_watcher->setFuture(QtConcurrent::run(readDisplay, m_displayFileDescriptor));
watcher->setFuture(QtConcurrent::run(readDisplay, m_displayFileDescriptor));
} }
void Xwayland::handleXwaylandFinished(int exitCode, QProcess::ExitStatus exitStatus) void Xwayland::handleXwaylandFinished(int exitCode, QProcess::ExitStatus exitStatus)
@ -299,6 +296,36 @@ void Xwayland::handleXwaylandError(QProcess::ProcessError error)
emit errorOccurred(); 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() bool Xwayland::createX11Connection()
{ {
xcb_connection_t *connection = xcb_connect_to_fd(m_xcbConnectionFd, nullptr); xcb_connection_t *connection = xcb_connect_to_fd(m_xcbConnectionFd, nullptr);
@ -352,28 +379,6 @@ void Xwayland::destroyX11Connection()
emit m_app->x11ConnectionChanged(); 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) DragEventReply Xwayland::dragMoveFilter(Toplevel *target, const QPoint &pos)
{ {
DataBridge *bridge = DataBridge::self(); DataBridge *bridge = DataBridge::self();

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

Loading…
Cancel
Save