2020-03-15 15:19:28 +00:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
2014-11-07 08:08:29 +00:00
|
|
|
|
2020-03-15 15:19:28 +00:00
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
|
|
*/
|
2023-10-06 09:11:35 +00:00
|
|
|
#include "wayland/compositor.h"
|
|
|
|
#include "wayland/display.h"
|
|
|
|
#include "wayland/output.h"
|
|
|
|
#include "wayland/seat.h"
|
|
|
|
#include "wayland/xdgshell.h"
|
2014-11-07 08:08:29 +00:00
|
|
|
|
2022-08-25 08:02:48 +00:00
|
|
|
#include "fakeoutput.h"
|
|
|
|
|
2014-11-07 10:48:32 +00:00
|
|
|
#include <QFile>
|
2021-08-29 05:11:06 +00:00
|
|
|
#include <QGuiApplication>
|
2018-11-06 06:22:36 +00:00
|
|
|
#include <private/qeventdispatcher_glib_p.h>
|
2014-11-07 10:48:32 +00:00
|
|
|
|
|
|
|
#include <iostream>
|
2024-01-11 15:58:52 +00:00
|
|
|
#include <sys/select.h>
|
2021-08-29 05:11:06 +00:00
|
|
|
#include <unistd.h>
|
2014-11-07 10:48:32 +00:00
|
|
|
|
|
|
|
static int startXServer()
|
|
|
|
{
|
|
|
|
const QByteArray process = QByteArrayLiteral("Xwayland");
|
|
|
|
int pipeFds[2];
|
|
|
|
if (pipe(pipeFds) != 0) {
|
2021-08-29 05:11:06 +00:00
|
|
|
std::cerr << "FATAL ERROR failed to create pipe to start X Server " << process.constData() << std::endl;
|
2014-11-07 10:48:32 +00:00
|
|
|
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]);
|
2017-01-16 08:44:16 +00:00
|
|
|
execlp(process.constData(), process.constData(), "-displayfd", fdbuf, (char *)nullptr);
|
2014-11-07 10:48:32 +00:00
|
|
|
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(":"));
|
2021-08-29 05:11:06 +00:00
|
|
|
displayNumber.remove(displayNumber.size() - 1, 1);
|
2014-11-07 10:48:32 +00:00
|
|
|
std::cout << "X-Server started on display " << displayNumber.constData() << std::endl;
|
|
|
|
|
|
|
|
setenv("DISPLAY", displayNumber.constData(), true);
|
|
|
|
|
|
|
|
// close our pipe
|
|
|
|
close(pipe);
|
|
|
|
}
|
2014-11-07 08:08:29 +00:00
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2023-09-13 17:59:29 +00:00
|
|
|
using namespace KWin;
|
2014-11-07 08:08:29 +00:00
|
|
|
|
2015-02-18 08:43:04 +00:00
|
|
|
// set our own event dispatcher to be able to dispatch events before the event loop is started
|
|
|
|
QAbstractEventDispatcher *eventDispatcher = new QEventDispatcherGlib();
|
|
|
|
QCoreApplication::setEventDispatcher(eventDispatcher);
|
|
|
|
|
2014-11-07 10:48:32 +00:00
|
|
|
// first create the Server and setup with minimum to get an XWayland connected
|
2023-09-13 17:59:29 +00:00
|
|
|
KWin::Display display;
|
2014-11-07 08:08:29 +00:00
|
|
|
display.start();
|
2015-02-18 08:43:04 +00:00
|
|
|
display.createShm();
|
2020-12-09 20:13:19 +00:00
|
|
|
new CompositorInterface(&display, &display);
|
|
|
|
new XdgShellInterface(&display, &display);
|
2022-08-25 08:02:48 +00:00
|
|
|
|
|
|
|
auto outputHandle = std::make_unique<FakeOutput>();
|
|
|
|
outputHandle->setMode(QSize(1024, 768), 60000);
|
|
|
|
outputHandle->setPhysicalSize(QSize(10, 10));
|
|
|
|
|
2022-10-15 11:52:22 +00:00
|
|
|
auto outputInterface = std::make_unique<OutputInterface>(&display, outputHandle.get());
|
2014-11-07 10:48:32 +00:00
|
|
|
|
|
|
|
// starts XWayland by forking and opening a pipe
|
|
|
|
const int pipe = startXServer();
|
|
|
|
if (pipe == -1) {
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-02-16 13:30:01 +00:00
|
|
|
fd_set rfds;
|
|
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
do {
|
2015-02-18 08:43:04 +00:00
|
|
|
eventDispatcher->processEvents(QEventLoop::WaitForMoreEvents);
|
2015-02-16 13:30:01 +00:00
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_SET(pipe, &rfds);
|
2017-01-16 08:44:16 +00:00
|
|
|
} while (select(pipe + 1, &rfds, nullptr, nullptr, &tv) == 0);
|
2014-11-07 10:48:32 +00:00
|
|
|
|
|
|
|
// now Xwayland is ready and we can read the pipe to get the display
|
|
|
|
readDisplayFromPipe(pipe);
|
|
|
|
|
|
|
|
QGuiApplication app(argc, argv);
|
|
|
|
|
2020-12-09 20:13:19 +00:00
|
|
|
SeatInterface *seat = new SeatInterface(&display);
|
2014-11-07 08:08:29 +00:00
|
|
|
seat->setName(QStringLiteral("testSeat0"));
|
|
|
|
|
|
|
|
return app.exec();
|
|
|
|
}
|