KWayland

testserver.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "testserver.h"
7 #include "../../server/display.h"
8 #include "../../server/compositor_interface.h"
9 #include "../../server/datadevicemanager_interface.h"
10 #include "../../server/idle_interface.h"
11 #include "../../server/fakeinput_interface.h"
12 #include "../../server/seat_interface.h"
13 #include "../../server/shell_interface.h"
14 #include "../../server/surface_interface.h"
15 #include "../../server/subcompositor_interface.h"
16 
17 #include <QCoreApplication>
18 #include <QElapsedTimer>
19 #include <QProcess>
20 #include <QTimer>
21 // system
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 
26 using namespace KWayland::Server;
27 
28 TestServer::TestServer(QObject *parent)
29  : QObject(parent)
30  , m_repaintTimer(new QTimer(this))
31  , m_timeSinceStart(new QElapsedTimer)
32  , m_cursorPos(QPointF(0, 0))
33 {
34 }
35 
36 TestServer::~TestServer() = default;
37 
38 void TestServer::init()
39 {
40  Q_ASSERT(!m_display);
41  m_display = new Display(this);
42  m_display->start(Display::StartMode::ConnectClientsOnly);
43  m_display->createShm();
44  m_display->createCompositor()->create();
45  m_shell = m_display->createShell(m_display);
47  [this] (ShellSurfaceInterface *surface) {
48  m_shellSurfaces << surface;
49  // TODO: pass keyboard/pointer/touch focus on mapped
50  connect(surface, &QObject::destroyed, this,
51  [this, surface] {
52  m_shellSurfaces.removeOne(surface);
53  }
54  );
55  }
56  );
57 
58  m_shell->create();
59  m_seat = m_display->createSeat(m_display);
60  m_seat->setHasKeyboard(true);
61  m_seat->setHasPointer(true);
62  m_seat->setHasTouch(true);
63  m_seat->create();
64  m_display->createDataDeviceManager(m_display)->create();
65  m_display->createIdle(m_display)->create();
66  m_display->createSubCompositor(m_display)->create();
67  // output
68  auto output = m_display->createOutput(m_display);
69  const QSize size(1280, 1024);
70  output->setGlobalPosition(QPoint(0, 0));
71  output->setPhysicalSize(size / 3.8);
72  output->addMode(size);
73  output->create();
74 
75  auto fakeInput = m_display->createFakeInput(m_display);
76  fakeInput->create();
78  [this] (FakeInputDevice *device) {
79  device->setAuthentication(true);
81  [this] (const QSizeF &delta) {
82  m_seat->setTimestamp(m_timeSinceStart->elapsed());
83  m_cursorPos = m_cursorPos + QPointF(delta.width(), delta.height());
84  m_seat->setPointerPos(m_cursorPos);
85  }
86  );
88  [this] (quint32 button) {
89  m_seat->setTimestamp(m_timeSinceStart->elapsed());
90  m_seat->pointerButtonPressed(button);
91  }
92  );
94  [this] (quint32 button) {
95  m_seat->setTimestamp(m_timeSinceStart->elapsed());
96  m_seat->pointerButtonReleased(button);
97  }
98  );
100  [this] (Qt::Orientation orientation, qreal delta) {
101  m_seat->setTimestamp(m_timeSinceStart->elapsed());
102  m_seat->pointerAxis(orientation, delta);
103  }
104  );
106  [this] (quint32 id, const QPointF &pos) {
107  m_seat->setTimestamp(m_timeSinceStart->elapsed());
108  m_touchIdMapper.insert(id, m_seat->touchDown(pos));
109  }
110  );
112  [this] (quint32 id, const QPointF &pos) {
113  m_seat->setTimestamp(m_timeSinceStart->elapsed());
114  const auto it = m_touchIdMapper.constFind(id);
115  if (it != m_touchIdMapper.constEnd()) {
116  m_seat->touchMove(it.value(), pos);
117  }
118  }
119  );
121  [this] (quint32 id) {
122  m_seat->setTimestamp(m_timeSinceStart->elapsed());
123  const auto it = m_touchIdMapper.find(id);
124  if (it != m_touchIdMapper.end()) {
125  m_seat->touchUp(it.value());
126  m_touchIdMapper.erase(it);
127  }
128  }
129  );
131  [this] {
132  m_seat->setTimestamp(m_timeSinceStart->elapsed());
133  m_seat->cancelTouchSequence();
134  }
135  );
137  [this] {
138  m_seat->setTimestamp(m_timeSinceStart->elapsed());
139  m_seat->touchFrame();
140  }
141  );
142  }
143  );
144 
145  m_repaintTimer->setInterval(1000 / 60);
146  connect(m_repaintTimer, &QTimer::timeout, this, &TestServer::repaint);
147  m_repaintTimer->start();
148  m_timeSinceStart->start();
149 }
150 
151 void TestServer::startTestApp(const QString &app, const QStringList &arguments)
152 {
153  int sx[2];
154  if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sx) < 0) {
156  return;
157  }
158  m_display->createClient(sx[0]);
159  int socket = dup(sx[1]);
160  if (socket == -1) {
162  return;
163  }
164  QProcess *p = new QProcess(this);
167  environment.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("wayland"));
168  environment.insert(QStringLiteral("WAYLAND_SOCKET"), QString::fromUtf8(QByteArray::number(socket)));
169  p->setProcessEnvironment(environment);
170  auto finishedSignal = static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished);
173  [] {
175  }
176  );
177  p->start(app, arguments);
178 }
179 
180 void TestServer::repaint()
181 {
182  for (auto it = m_shellSurfaces.constBegin(), end = m_shellSurfaces.constEnd(); it != end; ++it) {
183  (*it)->surface()->frameRendered(m_timeSinceStart->elapsed());
184  }
185 }
void pointerAxisRequested(Qt::Orientation orientation, qreal delta)
Requests a pointer axis for the given orientation by delta.
void pointerMotionRequested(const QSizeF &delta)
Request a pointer motion by delta.
void pointerButtonReleaseRequested(quint32 button)
Requests a pointer button release for button.
Represents the Resource for a org_kde_kwin_fake_input interface.
void insert(const QString &name, const QString &value)
void deviceCreated(KWayland::Server::FakeInputDevice *device)
Signal emitted whenever a client bound the fake input device.
void timeout()
void exit(int returnCode)
void errorOccurred(QProcess::ProcessError error)
void touchCancelRequested()
Requests a touch cancel event.
QString fromUtf8(const char *str, int size)
QByteArray number(int n, int base)
void finished(int exitCode)
void touchDownRequested(quint32 id, const QPointF &pos)
Requests a touch down at pos and identified by id.
Class holding the Wayland server display loop.
Definition: display.h:89
QCoreApplication * instance()
void touchUpRequested(quint32 id)
Requests a touch up identified by id.
void touchMotionRequested(quint32 id, const QPointF &pos)
Requests a touch motion by pos and identified by id.
KWayland Server.
void setProcessChannelMode(QProcess::ProcessChannelMode mode)
void setProcessEnvironment(const QProcessEnvironment &environment)
const QList< QKeySequence > & end()
void pointerButtonPressRequested(quint32 button)
Requests a pointer button pressed for button.
Orientation
void surfaceCreated(KWayland::Server::ShellSurfaceInterface *)
Emitted whenever a new ShellSurfaceInterface gets created for a SurfaceInterface. ...
QProcessEnvironment systemEnvironment()
qreal height() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void touchFrameRequested()
Requests a touch frame event.
void setAuthentication(bool authenticated)
Authenticate this device to send events.
Resource for a wl_shell_surface.
void destroyed(QObject *obj)
qreal width() const const
void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:48:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.