diff --git a/main_wayland.cpp b/main_wayland.cpp
index 8223fc68af..eaccfa53f6 100644
--- a/main_wayland.cpp
+++ b/main_wayland.cpp
@@ -34,6 +34,8 @@ along with this program. If not, see .
#include
#endif // HAVE_UNISTD_H
+#include
+
namespace KWin
{
@@ -95,11 +97,102 @@ void ApplicationWayland::performStartup()
notifyKSplash();
}
+/**
+ * Starts the X-Server with binary name @p process on @p display.
+ * The new process is started by forking into it.
+ **/
+static void startXServer(const QByteArray &process, const QByteArray &display)
+{
+ int pipeFds[2];
+ if (pipe(pipeFds) != 0) {
+ std::cerr << "FATAL ERROR failed to create pipe to start X Server "
+ << process.constData()
+ << " with arguments "
+ << display.constData()
+ << std::endl;
+ exit(1);
+ }
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ // child process - should be turned into X-Server
+ // writes to pipe, closes read side
+ close(pipeFds[0]);
+ char fdbuf[16];
+ sprintf(fdbuf, "%d", pipeFds[1]);
+ execlp(process.constData(), process.constData(), "-displayfd", fdbuf, display.constData(), (char *)0);
+ close(pipeFds[1]);
+ exit(20);
+ }
+ // parent process - this is KWin
+ // reads from pipe, closes write side
+ close(pipeFds[1]);
+
+ QFile readPipe;
+ if (!readPipe.open(pipeFds[0], QIODevice::ReadOnly)) {
+ std::cerr << "FATAL ERROR failed to open pipe to start X Server "
+ << process.constData()
+ << " with arguments "
+ << display.constData()
+ << std::endl;
+ exit(1);
+ }
+ QByteArray displayNumber = readPipe.readLine();
+
+ displayNumber.prepend(QByteArray(":"));
+ displayNumber.remove(displayNumber.size() -1, 1);
+ std::cout << "X-Server started on display " << displayNumber.constData();
+
+ setenv("DISPLAY", displayNumber.constData(), true);
+
+ // close our pipe
+ close(pipeFds[0]);
+}
+
} // namespace
extern "C"
KWIN_EXPORT int kdemain(int argc, char * argv[])
{
+ // process command line arguments to figure out whether we have to start an X-Server
+ bool startXephyr = false;
+ bool startXvfb = false;
+ bool startXwayland = false;
+ QByteArray xDisplay;
+ QByteArray xServer;
+ for (int i = 1; i < argc; ++i) {
+ QByteArray arg = argv[i];
+ if (arg == "-x" || arg == "--start-X-Server") {
+ if (++i < argc) {
+ xServer = argv[i];
+ }
+ startXephyr = (xServer == QStringLiteral("xephyr"));
+ startXvfb = (xServer == QStringLiteral("xvfb"));
+ startXwayland = (xServer == QStringLiteral("xwayland"));
+ if (!startXephyr && !startXvfb && !startXwayland) {
+ fprintf(stderr, "%s: FATAL ERROR unknown X-Server %s specified to start\n",
+ argv[0], qPrintable(xServer));
+ exit(1);
+ }
+ continue;
+ }
+ if (arg == "--display") {
+ if (++i < argc) {
+ xDisplay = argv[i];
+ }
+ }
+ }
+
+ if (startXephyr) {
+ KWin::startXServer(QByteArrayLiteral("Xephyr"), xDisplay);
+ }
+ if (startXvfb) {
+ KWin::startXServer(QByteArrayLiteral("Xvfb"), xDisplay);
+ }
+ if (startXwayland) {
+ KWin::startXServer(QByteArrayLiteral("Xwayland"), xDisplay);
+ }
+
KWin::Application::setupMalloc();
KWin::Application::setupLocalizedString();
KWin::Application::setupLoggingCategoryFilters();
@@ -119,8 +212,17 @@ KWIN_EXPORT int kdemain(int argc, char * argv[])
KWin::Application::createAboutData();
+ QCommandLineOption startXServerOption(QStringList({QStringLiteral("x"), QStringLiteral("x-server")}),
+ i18n("Start a nested X Server."),
+ QStringLiteral("xephyr|xvfb|xwayland"));
+ QCommandLineOption x11DisplayOption(QStringLiteral("display"),
+ i18n("The X11 Display to connect to, required if option x-server is used."),
+ QStringLiteral("display"));
+
QCommandLineParser parser;
a.setupCommandLine(&parser);
+ parser.addOption(startXServerOption);
+ parser.addOption(x11DisplayOption);
parser.process(a);
a.processCommandLine(&parser);