79 if (!m_listenFds.isEmpty()) {
80 Q_ASSERT(!m_displayName.isEmpty());
83 if (!m_socket->isValid()) {
84 qFatal(
"Failed to establish X11 socket");
86 m_displayName = m_socket->name();
87 m_listenFds = m_socket->fileDescriptors();
90 for (
int socket : std::as_const(m_listenFds)) {
91 QSocketNotifier *notifier =
new QSocketNotifier(socket, QSocketNotifier::Read,
this);
92 connect(notifier, &QSocketNotifier::activated,
this, [
this]() {
93 if (!m_xwaylandProcess) {
98 notifier->setEnabled(
false);
102 notifier->setEnabled(m_enabled);
116 if (m_xwaylandProcess) {
119 QList<int> fdsToClose;
120 auto cleanup = qScopeGuard([&fdsToClose] {
121 for (
const int fd : std::as_const(fdsToClose)) {
127 if (pipe(pipeFds) != 0) {
128 qCWarning(KWIN_XWL,
"Failed to create pipe to start Xwayland: %s", strerror(errno));
132 fdsToClose << pipeFds[1];
135 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
136 qCWarning(KWIN_XWL,
"Failed to open socket for XCB connection: %s", strerror(errno));
142 qCWarning(KWIN_XWL,
"Failed to open socket for XCB connection: %s", strerror(errno));
148 if (waylandSocket == -1) {
149 qCWarning(KWIN_XWL,
"Failed to open socket for Xwayland server: %s", strerror(errno));
153 const int wlfd = dup(waylandSocket);
155 qCWarning(KWIN_XWL,
"Failed to open socket for Xwayland server: %s", strerror(errno));
160 m_xcbConnectionFd = sx[0];
162 QStringList arguments;
164 arguments << m_displayName;
166 if (!m_listenFds.isEmpty()) {
168 if (!m_xAuthority.isEmpty()) {
169 arguments << QStringLiteral(
"-auth") << m_xAuthority;
172 for (
int socket : std::as_const(m_listenFds)) {
173 int dupSocket = dup(socket);
174 fdsToClose << dupSocket;
175#if HAVE_XWAYLAND_LISTENFD
176 arguments << QStringLiteral(
"-listenfd") << QString::number(dupSocket);
178 arguments << QStringLiteral(
"-listen") << QString::number(dupSocket);
183 arguments << QStringLiteral(
"-displayfd") << QString::number(pipeFds[1]);
184 arguments << QStringLiteral(
"-rootless");
185 arguments << QStringLiteral(
"-wm") << QString::number(fd);
187 m_xwaylandProcess =
new QProcess(
this);
188 m_xwaylandProcess->setProcessChannelMode(QProcess::ForwardedErrorChannel);
189 m_xwaylandProcess->setProgram(QStringLiteral(
"Xwayland"));
190 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
191 env.insert(
"WAYLAND_SOCKET", QByteArray::number(wlfd));
192 if (qEnvironmentVariableIntValue(
"KWIN_XWAYLAND_DEBUG") == 1) {
193 env.insert(
"WAYLAND_DEBUG", QByteArrayLiteral(
"1"));
195 m_xwaylandProcess->setProcessEnvironment(env);
196 m_xwaylandProcess->setArguments(arguments);
197 connect(m_xwaylandProcess, &QProcess::errorOccurred,
this, &XwaylandLauncher::handleXwaylandError);
198 connect(m_xwaylandProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
199 this, &XwaylandLauncher::handleXwaylandFinished);
203 m_readyNotifier =
new QSocketNotifier(pipeFds[0], QSocketNotifier::Read,
this);
204 connect(m_readyNotifier, &QSocketNotifier::activated,
this, [
this]() {
205 maybeDestroyReadyNotifier();
209 m_xwaylandProcess->start();
266void XwaylandLauncher::handleXwaylandFinished(
int exitCode, QProcess::ExitStatus exitStatus)