You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.3 KiB
112 lines
3.3 KiB
/* |
|
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
|
*/ |
|
#include "wayland/compositor.h" |
|
#include "wayland/display.h" |
|
#include "wayland/output.h" |
|
#include "wayland/seat.h" |
|
#include "wayland/xdgshell.h" |
|
|
|
#include "fakeoutput.h" |
|
|
|
#include <QFile> |
|
#include <QGuiApplication> |
|
#include <private/qeventdispatcher_glib_p.h> |
|
|
|
#include <iostream> |
|
#include <sys/select.h> |
|
#include <unistd.h> |
|
|
|
static int startXServer() |
|
{ |
|
const QByteArray process = QByteArrayLiteral("Xwayland"); |
|
int pipeFds[2]; |
|
if (pipe(pipeFds) != 0) { |
|
std::cerr << "FATAL ERROR failed to create pipe to start X Server " << process.constData() << std::endl; |
|
exit(1); |
|
} |
|
|
|
pid_t pid = fork(); |
|
if (pid == 0) { |
|
// child process - should be turned into Xwayland |
|
// writes to pipe, closes read side |
|
close(pipeFds[0]); |
|
char fdbuf[16]; |
|
sprintf(fdbuf, "%d", pipeFds[1]); |
|
execlp(process.constData(), process.constData(), "-displayfd", fdbuf, (char *)nullptr); |
|
close(pipeFds[1]); |
|
exit(20); |
|
} |
|
// parent process - this is the wayland server |
|
// reads from pipe, closes write side |
|
close(pipeFds[1]); |
|
return pipeFds[0]; |
|
} |
|
|
|
static void readDisplayFromPipe(int pipe) |
|
{ |
|
QFile readPipe; |
|
if (!readPipe.open(pipe, QIODevice::ReadOnly)) { |
|
std::cerr << "FATAL ERROR failed to open pipe to start X Server XWayland" << 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() << std::endl; |
|
|
|
setenv("DISPLAY", displayNumber.constData(), true); |
|
|
|
// close our pipe |
|
close(pipe); |
|
} |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
using namespace KWin; |
|
|
|
// set our own event dispatcher to be able to dispatch events before the event loop is started |
|
QAbstractEventDispatcher *eventDispatcher = new QEventDispatcherGlib(); |
|
QCoreApplication::setEventDispatcher(eventDispatcher); |
|
|
|
// first create the Server and setup with minimum to get an XWayland connected |
|
KWin::Display display; |
|
display.start(); |
|
display.createShm(); |
|
new CompositorInterface(&display, &display); |
|
new XdgShellInterface(&display, &display); |
|
|
|
auto outputHandle = std::make_unique<FakeOutput>(); |
|
outputHandle->setMode(QSize(1024, 768), 60000); |
|
outputHandle->setPhysicalSize(QSize(10, 10)); |
|
|
|
auto outputInterface = std::make_unique<OutputInterface>(&display, outputHandle.get()); |
|
|
|
// starts XWayland by forking and opening a pipe |
|
const int pipe = startXServer(); |
|
if (pipe == -1) { |
|
exit(1); |
|
} |
|
|
|
fd_set rfds; |
|
struct timeval tv; |
|
tv.tv_sec = 0; |
|
tv.tv_usec = 0; |
|
do { |
|
eventDispatcher->processEvents(QEventLoop::WaitForMoreEvents); |
|
FD_ZERO(&rfds); |
|
FD_SET(pipe, &rfds); |
|
} while (select(pipe + 1, &rfds, nullptr, nullptr, &tv) == 0); |
|
|
|
// now Xwayland is ready and we can read the pipe to get the display |
|
readDisplayFromPipe(pipe); |
|
|
|
QGuiApplication app(argc, argv); |
|
|
|
new SeatInterface(&display, QStringLiteral("testSeat0")); |
|
|
|
return app.exec(); |
|
}
|
|
|