19#include <QApplication>
20#include <QCommandLineParser>
33static int startXServer()
35 const QByteArray process = QByteArrayLiteral(
"Xwayland");
37 if (pipe(pipeFds) != 0) {
38 std::cerr <<
"FATAL ERROR failed to create pipe to start X Server " << process.constData() << std::endl;
48 sprintf(fdbuf,
"%d", pipeFds[1]);
49 execlp(process.constData(), process.constData(),
"-displayfd", fdbuf,
"-rootless", (
char *)
nullptr);
59static void readDisplayFromPipe(
int pipe)
62 if (!readPipe.open(pipe, QIODevice::ReadOnly)) {
63 std::cerr <<
"FATAL ERROR failed to open pipe to start X Server XWayland" << std::endl;
66 QByteArray displayNumber = readPipe.readLine();
68 displayNumber.prepend(QByteArray(
":"));
69 displayNumber.remove(displayNumber.size() - 1, 1);
70 std::cout <<
"X-Server started on display " << displayNumber.constData() << std::endl;
72 setenv(
"DISPLAY", displayNumber.constData(),
true);
87 void setSeat(
const QPointer<KWin::SeatInterface> &seat);
100 QList<KWin::XdgToplevelInterface *> m_stackingOrder;
101 QPointer<KWin::SeatInterface> m_seat;
107 setMouseTracking(
true);
114 using namespace KWin;
115 surface->
sendConfigure(QSize(), XdgToplevelInterface::States());
116 m_stackingOrder << surface;
117 connect(surface->
surface(), &SurfaceInterface::damaged,
this,
static_cast<void (
CompositorWindow::*)()
>(&CompositorWindow::update));
118 connect(surface, &XdgToplevelInterface::destroyed,
this, [surface,
this] {
119 m_stackingOrder.removeAll(surface);
126void CompositorWindow::updateFocus()
128 using namespace KWin;
129 if (!m_seat || m_stackingOrder.isEmpty()) {
132 auto it = std::find_if(m_stackingOrder.constBegin(), m_stackingOrder.constEnd(), [](
XdgToplevelInterface *toplevel) {
133 return toplevel->surface()->isMapped();
135 if (it == m_stackingOrder.constEnd()) {
138 m_seat->notifyPointerEnter((*it)->surface(), m_seat->pointerPos());
139 m_seat->setFocusedKeyboardSurface((*it)->surface());
149 QWidget::paintEvent(event);
151 for (
auto window : m_stackingOrder) {
153 if (!surface || !surface->
isMapped()) {
158 p.drawImage(QPoint(0, 0), *view.
image());
166 QWidget::keyPressEvent(event);
170 if (!m_seat->focusedKeyboardSurface()) {
173 m_seat->setTimestamp(std::chrono::milliseconds(event->timestamp()));
179 QWidget::keyReleaseEvent(event);
183 m_seat->setTimestamp(std::chrono::milliseconds(event->timestamp()));
189 QWidget::mouseMoveEvent(event);
190 if (!m_seat->focusedPointerSurface()) {
193 m_seat->setTimestamp(std::chrono::milliseconds(event->timestamp()));
194 m_seat->notifyPointerMotion(event->localPos().toPoint());
195 m_seat->notifyPointerFrame();
200 QWidget::mousePressEvent(event);
201 if (!m_seat->focusedPointerSurface()) {
202 if (!m_stackingOrder.isEmpty()) {
203 m_seat->notifyPointerEnter(m_stackingOrder.last()->surface(), event->globalPos());
206 m_seat->setTimestamp(std::chrono::milliseconds(event->timestamp()));
208 m_seat->notifyPointerFrame();
213 QWidget::mouseReleaseEvent(event);
214 m_seat->setTimestamp(std::chrono::milliseconds(event->timestamp()));
216 m_seat->notifyPointerFrame();
221 QWidget::wheelEvent(event);
222 m_seat->setTimestamp(std::chrono::milliseconds(event->timestamp()));
223 const QPoint &angle =
event->angleDelta() / (8 * 15);
224 if (angle.x() != 0) {
227 if (angle.y() != 0) {
230 m_seat->notifyPointerFrame();
235 using namespace KWin;
236 QApplication app(argc, argv);
238 QCommandLineParser parser;
239 parser.addHelpOption();
240 QCommandLineOption xwaylandOption(QStringList{QStringLiteral(
"x"), QStringLiteral(
"xwayland")}, QStringLiteral(
"Start a rootless Xwayland server"));
241 parser.addOption(xwaylandOption);
251 const QSize windowSize(1024, 768);
253 auto outputHandle = std::make_unique<FakeOutput>();
254 outputHandle->setPhysicalSize(QSize(269, 202));
255 outputHandle->setMode(windowSize, 60000);
257 auto outputInterface = std::make_unique<OutputInterface>(&display, outputHandle.get());
260 seat->setHasKeyboard(
true);
261 seat->setHasPointer(
true);
262 seat->setName(QStringLiteral(
"testSeat0"));
265 compositorWindow.
setSeat(seat);
266 compositorWindow.setMinimumSize(windowSize);
267 compositorWindow.setMaximumSize(windowSize);
268 compositorWindow.setGeometry(QRect(QPoint(0, 0), windowSize));
269 compositorWindow.show();
273 if (parser.isSet(xwaylandOption)) {
275 const int pipe = startXServer();
280 QThreadPool::globalInstance()->start([pipe] {
281 readDisplayFromPipe(pipe);
288#include "renderingservertest.moc"
CompositorWindow(QWidget *parent=nullptr)
void mousePressEvent(QMouseEvent *event) override
void mouseReleaseEvent(QMouseEvent *event) override
void setSeat(const QPointer< KWin::SeatInterface > &seat)
void keyReleaseEvent(QKeyEvent *event) override
virtual ~CompositorWindow()
void surfaceCreated(KWin::XdgToplevelInterface *surface)
void mouseMoveEvent(QMouseEvent *event) override
void wheelEvent(QWheelEvent *event) override
void keyPressEvent(QKeyEvent *event) override
void paintEvent(QPaintEvent *event) override
Represents the Global for wl_data_device_manager interface.
Class holding the Wayland server display loop.
Represents a Seat on the Wayland Display.
Resource representing a wl_surface.
GraphicsBuffer * buffer() const
void frameRendered(quint32 msec)
quint32 sendConfigure(const QSize &size, const States &states)
SurfaceInterface * surface() const