[kwin_wayland] Add config option to start an X Server
KWin_Wayland still needs an X-Server. To simplify the development setup the required X-Server can be started through a command line argument together with KWin. Unfortunately the command line arguments processing needs to be done by hand as QCommandLineParser only allows processing after QApplication is created which requires the started X Server. The nested X-Server is started by forking the application and using execlp to load the binary. In addition a pipe is created to allow the X-Server to write the display number to once it's ready to connect and by that KWin is ready to create the QApplication.
This commit is contained in:
parent
f373aa1ce5
commit
65c17d32cc
1 changed files with 102 additions and 0 deletions
102
main_wayland.cpp
102
main_wayland.cpp
|
@ -34,6 +34,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue