KWin
Loading...
Searching...
No Matches
main_wayland.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "main_wayland.h"
10
11#include <config-kwin.h>
12
17#include "compositor_wayland.h"
18#include "core/outputbackend.h"
19#include "core/session.h"
21#include "inputmethod.h"
22#include "tabletmodemanager.h"
23#include "utils/realtime.h"
24#include "wayland/display.h"
25#include "wayland/seat.h"
26#include "wayland_server.h"
27#include "workspace.h"
28#include "xwayland/xwayland.h"
30
31// KDE
32#include <KCrash>
33#include <KDesktopFile>
34#include <KLocalizedString>
35#include <KShell>
36#include <KSignalHandler>
37
38// Qt
39#include <QCommandLineParser>
40#include <QDBusInterface>
41#include <QDebug>
42#include <QFileInfo>
43#include <QProcess>
44#include <QWindow>
45#include <QtPlugin>
46#include <qplatformdefs.h>
47
48#include <sched.h>
49#include <sys/resource.h>
50
51#include <iomanip>
52#include <iostream>
53
54Q_IMPORT_PLUGIN(KWinIntegrationPlugin)
55#if KWIN_BUILD_GLOBALSHORTCUTS
56Q_IMPORT_PLUGIN(KGlobalAccelImpl)
57#endif
58Q_IMPORT_PLUGIN(KWindowSystemKWinPlugin)
59Q_IMPORT_PLUGIN(KWinIdleTimePoller)
60
61namespace KWin
62{
63
64static rlimit originalNofileLimit = {
65 .rlim_cur = 0,
66 .rlim_max = 0,
67};
68
69static bool bumpNofileLimit()
70{
71 if (getrlimit(RLIMIT_NOFILE, &originalNofileLimit) == -1) {
72 std::cerr << "Failed to bump RLIMIT_NOFILE limit, getrlimit() failed: " << strerror(errno) << std::endl;
73 return false;
74 }
75
76 rlimit limit = originalNofileLimit;
77 limit.rlim_cur = limit.rlim_max;
78
79 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
80 std::cerr << "Failed to bump RLIMIT_NOFILE limit, setrlimit() failed: " << strerror(errno) << std::endl;
81 return false;
82 }
83
84 return true;
85}
86
87static void restoreNofileLimit()
88{
89 if (setrlimit(RLIMIT_NOFILE, &originalNofileLimit) == -1) {
90 std::cerr << "Failed to restore RLIMIT_NOFILE limit, legacy apps might be broken" << std::endl;
91 }
92}
93
95{
96 KCrash::setDrKonqiEnabled(false);
97}
98// run immediately, before Q_CORE_STARTUP functions
99// that would enable drkonqi
100Q_CONSTRUCTOR_FUNCTION(disableDrKonqi)
101
102//************************************
103// ApplicationWayland
104//************************************
105
107 : Application(OperationModeWaylandOnly, argc, argv)
108{
109}
110
112{
114 if (!waylandServer()) {
115 return;
116 }
117
119
120 // need to unload all effects prior to destroying X connection as they might do X calls
121 if (effects) {
123 }
124 m_xwayland.reset();
127
130 destroyInput();
131}
132
134{
135 if (m_startXWayland) {
137 setXwaylandScale(config()->group(QStringLiteral("Xwayland")).readEntry("Scale", 1.0));
138 }
140
141 if (!outputBackend()->initialize()) {
142 std::exit(1);
143 }
144
145 createInput();
148
153
155 connect(Compositor::self(), &Compositor::sceneCreated, this, &ApplicationWayland::continueStartupWithScene, Qt::SingleShotConnection);
156}
157
158void ApplicationWayland::continueStartupWithScene()
159{
160 // Note that we start accepting client connections after creating the Workspace.
161 if (!waylandServer()->start()) {
162 qFatal("Failed to initialze the Wayland server, exiting now");
163 }
164
166 m_xwayland = std::make_unique<Xwl::Xwayland>(this);
167 m_xwayland->xwaylandLauncher()->setListenFDs(m_xwaylandListenFds);
168 m_xwayland->xwaylandLauncher()->setDisplayName(m_xwaylandDisplay);
169 m_xwayland->xwaylandLauncher()->setXauthority(m_xwaylandXauthority);
170 m_xwayland->init();
171 connect(m_xwayland.get(), &Xwl::Xwayland::started, this, &ApplicationWayland::applyXwaylandScale);
172 }
173 startSession();
175}
176
177void ApplicationWayland::refreshSettings(const KConfigGroup &group, const QByteArrayList &names)
178{
179 if (group.name() == "Wayland" && names.contains("InputMethod")) {
180 KDesktopFile file(group.readPathEntry("InputMethod", QString()));
181 kwinApp()->inputMethod()->setInputMethodCommand(file.desktopGroup().readEntry("Exec", QString()));
182 }
183}
184
185void ApplicationWayland::startSession()
186{
187 KSharedConfig::Ptr kwinSettings = kwinApp()->config();
188 m_settingsWatcher = KConfigWatcher::create(kwinSettings);
189 connect(m_settingsWatcher.data(), &KConfigWatcher::configChanged, this, &ApplicationWayland::refreshSettings);
190
191 if (!m_inputMethodServerToStart.isEmpty()) {
192 kwinApp()->inputMethod()->setInputMethodCommand(m_inputMethodServerToStart);
193 } else {
194 refreshSettings(kwinSettings->group(QStringLiteral("Wayland")), {"InputMethod"});
195 }
196
197 // start session
198 if (!m_sessionArgument.isEmpty()) {
199 QStringList arguments = KShell::splitArgs(m_sessionArgument);
200 if (!arguments.isEmpty()) {
201 QString program = arguments.takeFirst();
202 QProcess *p = new QProcess(this);
203 p->setProcessChannelMode(QProcess::ForwardedChannels);
204 p->setProcessEnvironment(processStartupEnvironment());
205 connect(p, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [p](int code, QProcess::ExitStatus status) {
206 p->deleteLater();
207 if (status == QProcess::CrashExit) {
208 qWarning() << "Session process has crashed";
209 QCoreApplication::exit(-1);
210 return;
211 }
212
213 if (code) {
214 qWarning() << "Session process exited with code" << code;
215 }
216
217 QCoreApplication::exit(code);
218 });
219 p->setProgram(program);
220 p->setArguments(arguments);
221 p->start();
222 } else {
223 qWarning("Failed to launch the session process: %s is an invalid command",
224 qPrintable(m_sessionArgument));
225 }
226 }
227 // start the applications passed to us as command line arguments
228 if (!m_applicationsToStart.isEmpty()) {
229 for (const QString &application : std::as_const(m_applicationsToStart)) {
230 QStringList arguments = KShell::splitArgs(application);
231 if (arguments.isEmpty()) {
232 qWarning("Failed to launch application: %s is an invalid command",
233 qPrintable(application));
234 continue;
235 }
236 QString program = arguments.takeFirst();
237 // note: this will kill the started process when we exit
238 // this is going to happen anyway as we are the wayland and X server the app connects to
239 QProcess *p = new QProcess(this);
240 p->setProcessChannelMode(QProcess::ForwardedChannels);
241 p->setProcessEnvironment(processStartupEnvironment());
242 p->setProgram(program);
243 p->setArguments(arguments);
244 p->startDetached();
245 p->deleteLater();
246 }
247 }
248}
249
251{
252 return m_xwayland.get();
253}
254
255} // namespace
256
257int main(int argc, char *argv[])
258{
262
263 signal(SIGPIPE, SIG_IGN);
264
265 // It's easy to exceed the file descriptor limit because many things are backed using fds
266 // nowadays, e.g. dmabufs, shm buffers, etc. Bump the RLIMIT_NOFILE limit to handle that.
267 // Some apps may still use select(), so we reset the limit to its original value in fork().
268 if (KWin::bumpNofileLimit()) {
269 pthread_atfork(nullptr, nullptr, KWin::restoreNofileLimit);
270 }
271
272 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
273
274 // enforce our internal qpa plugin, unfortunately command line switch has precedence
275 setenv("QT_QPA_PLATFORM", "wayland-org.kde.kwin.qpa", true);
276
277 KWin::ApplicationWayland a(argc, argv);
278
279 // reset QT_QPA_PLATFORM so we don't propagate it to our children (e.g. apps launched from the overview effect)
280 qunsetenv("QT_QPA_PLATFORM");
281
282 KSignalHandler::self()->watchSignal(SIGTERM);
283 KSignalHandler::self()->watchSignal(SIGINT);
284 KSignalHandler::self()->watchSignal(SIGHUP);
285 QObject::connect(KSignalHandler::self(), &KSignalHandler::signalReceived,
286 &a, &QCoreApplication::exit);
287
289
290 QCommandLineOption xwaylandOption(QStringLiteral("xwayland"),
291 i18n("Start a rootless Xwayland server."));
292 QCommandLineOption waylandSocketOption(QStringList{QStringLiteral("s"), QStringLiteral("socket")},
293 i18n("Name of the Wayland socket to listen on. If not set \"wayland-0\" is used."),
294 QStringLiteral("socket"));
295 QCommandLineOption x11DisplayOption(QStringLiteral("x11-display"),
296 i18n("The X11 Display to use in windowed mode on platform X11."),
297 QStringLiteral("display"));
298 QCommandLineOption waylandDisplayOption(QStringLiteral("wayland-display"),
299 i18n("The Wayland Display to use in windowed mode on platform Wayland."),
300 QStringLiteral("display"));
301 QCommandLineOption virtualFbOption(QStringLiteral("virtual"), i18n("Render to a virtual framebuffer."));
302 QCommandLineOption widthOption(QStringLiteral("width"),
303 i18n("The width for windowed mode. Default width is 1024."),
304 QStringLiteral("width"));
305 widthOption.setDefaultValue(QString::number(1024));
306 QCommandLineOption heightOption(QStringLiteral("height"),
307 i18n("The height for windowed mode. Default height is 768."),
308 QStringLiteral("height"));
309 heightOption.setDefaultValue(QString::number(768));
310
311 QCommandLineOption scaleOption(QStringLiteral("scale"),
312 i18n("The scale for windowed mode. Default value is 1."),
313 QStringLiteral("scale"));
314 scaleOption.setDefaultValue(QString::number(1));
315
316 QCommandLineOption outputCountOption(QStringLiteral("output-count"),
317 i18n("The number of windows to open as outputs in windowed mode. Default value is 1"),
318 QStringLiteral("count"));
319 outputCountOption.setDefaultValue(QString::number(1));
320
321 QCommandLineOption waylandSocketFdOption(QStringLiteral("wayland-fd"),
322 i18n("Wayland socket to use for incoming connections. This can be combined with --socket to name the socket"),
323 QStringLiteral("wayland-fd"));
324
325 QCommandLineOption xwaylandListenFdOption(QStringLiteral("xwayland-fd"),
326 i18n("XWayland socket to use for Xwayland's incoming connections. This can be set multiple times"),
327 QStringLiteral("xwayland-fds"));
328
329 QCommandLineOption xwaylandDisplayOption(QStringLiteral("xwayland-display"),
330 i18n("Name of the xwayland display that has been pre-set up"),
331 "xwayland-display");
332
333 QCommandLineOption xwaylandXAuthorityOption(QStringLiteral("xwayland-xauthority"),
334 i18n("Name of the xauthority file "),
335 "xwayland-xauthority");
336
337 QCommandLineOption replaceOption(QStringLiteral("replace"),
338 i18n("Exits this instance so it can be restarted by kwin_wayland_wrapper."));
339
340 QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node."));
341 QCommandLineOption locale1Option(QStringLiteral("locale1"), i18n("Extract locale information from locale1 rather than the user's configuration"));
342
343 QCommandLineParser parser;
344 a.setupCommandLine(&parser);
345 parser.addOption(xwaylandOption);
346 parser.addOption(waylandSocketOption);
347 parser.addOption(waylandSocketFdOption);
348 parser.addOption(xwaylandListenFdOption);
349 parser.addOption(xwaylandDisplayOption);
350 parser.addOption(xwaylandXAuthorityOption);
351 parser.addOption(replaceOption);
352 parser.addOption(x11DisplayOption);
353 parser.addOption(waylandDisplayOption);
354 parser.addOption(virtualFbOption);
355 parser.addOption(widthOption);
356 parser.addOption(heightOption);
357 parser.addOption(scaleOption);
358 parser.addOption(outputCountOption);
359 parser.addOption(drmOption);
360 parser.addOption(locale1Option);
361
362 QCommandLineOption inputMethodOption(QStringLiteral("inputmethod"),
363 i18n("Input method that KWin starts."),
364 QStringLiteral("path/to/imserver"));
365 parser.addOption(inputMethodOption);
366
367#if KWIN_BUILD_SCREENLOCKER
368 QCommandLineOption screenLockerOption(QStringLiteral("lockscreen"),
369 i18n("Starts the session in locked mode."));
370 parser.addOption(screenLockerOption);
371
372 QCommandLineOption noScreenLockerOption(QStringLiteral("no-lockscreen"),
373 i18n("Starts the session without lock screen support."));
374 parser.addOption(noScreenLockerOption);
375#endif
376
377 QCommandLineOption noGlobalShortcutsOption(QStringLiteral("no-global-shortcuts"),
378 i18n("Starts the session without global shortcuts support."));
379 parser.addOption(noGlobalShortcutsOption);
380
381#if KWIN_BUILD_ACTIVITIES
382 QCommandLineOption noActivitiesOption(QStringLiteral("no-kactivities"),
383 i18n("Disable KActivities integration."));
384 parser.addOption(noActivitiesOption);
385#endif
386
387 QCommandLineOption exitWithSessionOption(QStringLiteral("exit-with-session"),
388 i18n("Exit after the session application, which is started by KWin, closed."),
389 QStringLiteral("/path/to/session"));
390 parser.addOption(exitWithSessionOption);
391
392 parser.addPositionalArgument(QStringLiteral("applications"),
393 i18n("Applications to start once Wayland and Xwayland server are started"),
394 QStringLiteral("[/path/to/application...]"));
395
396 parser.process(a);
397 a.processCommandLine(&parser);
398
399#if KWIN_BUILD_ACTIVITIES
400 if (parser.isSet(noActivitiesOption)) {
401 a.setUseKActivities(false);
402 }
403#endif
404
405 if (parser.isSet(replaceOption)) {
406 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), QStringLiteral("/KWin"),
407 QStringLiteral("org.kde.KWin"), QStringLiteral("replace"));
408 QDBusConnection::sessionBus().call(msg, QDBus::NoBlock);
409 return 0;
410 }
411
412 if (parser.isSet(exitWithSessionOption)) {
413 a.setSessionArgument(parser.value(exitWithSessionOption));
414 }
415
416 enum class BackendType {
417 Kms,
418 X11,
419 Wayland,
420 Virtual,
421 };
422
423 BackendType backendType;
424 QString pluginName;
425 QSize initialWindowSize;
426 int outputCount = 1;
427 qreal outputScale = 1;
428
429 // Decide what backend to use.
430 if (parser.isSet(drmOption)) {
431 backendType = BackendType::Kms;
432 } else if (parser.isSet(x11DisplayOption)) {
433 backendType = BackendType::X11;
434 } else if (parser.isSet(waylandDisplayOption)) {
435 backendType = BackendType::Wayland;
436 } else if (parser.isSet(virtualFbOption)) {
437 backendType = BackendType::Virtual;
438 } else {
439 if (qEnvironmentVariableIsSet("WAYLAND_DISPLAY")) {
440 qInfo("No backend specified, automatically choosing Wayland because WAYLAND_DISPLAY is set");
441 backendType = BackendType::Wayland;
442 } else if (qEnvironmentVariableIsSet("DISPLAY")) {
443 qInfo("No backend specified, automatically choosing X11 because DISPLAY is set");
444 backendType = BackendType::X11;
445 } else {
446 qInfo("No backend specified, automatically choosing drm");
447 backendType = BackendType::Kms;
448 }
449 }
450
451 if (parser.isSet(locale1Option)) {
452 a.setFollowLocale1(true);
453 }
454
455 bool ok = false;
456 const int width = parser.value(widthOption).toInt(&ok);
457 if (!ok) {
458 std::cerr << "FATAL ERROR incorrect value for width" << std::endl;
459 return 1;
460 }
461 const int height = parser.value(heightOption).toInt(&ok);
462 if (!ok) {
463 std::cerr << "FATAL ERROR incorrect value for height" << std::endl;
464 return 1;
465 }
466 const qreal scale = parser.value(scaleOption).toDouble(&ok);
467 if (!ok || scale <= 0) {
468 std::cerr << "FATAL ERROR incorrect value for scale" << std::endl;
469 return 1;
470 }
471
472 outputScale = scale;
473 initialWindowSize = QSize(width, height);
474
475 const int count = parser.value(outputCountOption).toInt(&ok);
476 if (ok) {
477 outputCount = std::max(1, count);
478 }
479
480 // TODO: create backend without having the server running
481 KWin::WaylandServer *server = KWin::WaylandServer::create(&a);
482
483 KWin::WaylandServer::InitializationFlags flags;
484#if KWIN_BUILD_SCREENLOCKER
485 if (parser.isSet(screenLockerOption)) {
487 } else if (parser.isSet(noScreenLockerOption)) {
489 }
490#endif
491 if (parser.isSet(noGlobalShortcutsOption)) {
493 }
494
495 const QString socketName = parser.value(waylandSocketOption);
496 if (parser.isSet(waylandSocketFdOption)) {
497 bool ok;
498 int fd = parser.value(waylandSocketFdOption).toInt(&ok);
499 if (ok) {
500 // make sure we don't leak this FD to children
501 fcntl(fd, F_SETFD, FD_CLOEXEC);
502 server->display()->addSocketFileDescriptor(fd, socketName);
503 } else {
504 std::cerr << "FATAL ERROR: could not parse socket FD" << std::endl;
505 return 1;
506 }
507 } else {
508 // socketName empty is fine here, addSocketName will automatically pick one
509 if (!server->display()->addSocketName(socketName)) {
510 std::cerr << "FATAL ERROR: could not add wayland socket " << qPrintable(socketName) << std::endl;
511 return 1;
512 }
513 qInfo() << "Accepting client connections on sockets:" << server->display()->socketNames();
514 }
515
516 if (!server->init(flags)) {
517 std::cerr << "FATAL ERROR: could not create Wayland server" << std::endl;
518 return 1;
519 }
520
521 switch (backendType) {
522 case BackendType::Kms:
524 if (!a.session()) {
525 std::cerr << "FATAl ERROR: could not acquire a session" << std::endl;
526 return 1;
527 }
528 a.setOutputBackend(std::make_unique<KWin::DrmBackend>(a.session()));
529 break;
530 case BackendType::Virtual: {
531 auto outputBackend = std::make_unique<KWin::VirtualBackend>();
532 for (int i = 0; i < outputCount; ++i) {
533 outputBackend->addOutput(KWin::VirtualBackend::OutputInfo{
534 .geometry = QRect(QPoint(), initialWindowSize),
535 .scale = outputScale,
536 });
537 }
539 a.setOutputBackend(std::move(outputBackend));
540 break;
541 }
542 case BackendType::X11: {
543 QString display = parser.value(x11DisplayOption);
544 if (display.isEmpty()) {
545 display = qgetenv("DISPLAY");
546 }
548 a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>(KWin::X11WindowedBackendOptions{
549 .display = display,
550 .outputCount = outputCount,
551 .outputScale = outputScale,
552 .outputSize = initialWindowSize,
553 }));
554 break;
555 }
556 case BackendType::Wayland: {
557 QString socketName = parser.value(waylandDisplayOption);
558 if (socketName.isEmpty()) {
559 socketName = qgetenv("WAYLAND_DISPLAY");
560 }
562 a.setOutputBackend(std::make_unique<KWin::Wayland::WaylandBackend>(KWin::Wayland::WaylandBackendOptions{
563 .socketName = socketName,
564 .outputCount = outputCount,
565 .outputScale = outputScale,
566 .outputSize = initialWindowSize,
567 }));
568 break;
569 }
570 }
571
573 if (!server->socketName().isEmpty()) {
574 environment.insert(QStringLiteral("WAYLAND_DISPLAY"), server->socketName());
575 qputenv("WAYLAND_DISPLAY", server->socketName().toUtf8());
576 }
577 a.setProcessStartupEnvironment(environment);
578
579 if (parser.isSet(xwaylandOption)) {
580 a.setStartXwayland(true);
581
582 if (parser.isSet(xwaylandListenFdOption)) {
583 const QStringList fdStrings = parser.values(xwaylandListenFdOption);
584 for (const QString &fdString : fdStrings) {
585 bool ok;
586 int fd = fdString.toInt(&ok);
587 if (ok) {
588 // make sure we don't leak this FD to children
589 fcntl(fd, F_SETFD, FD_CLOEXEC);
591 }
592 }
593 if (parser.isSet(xwaylandDisplayOption)) {
594 a.setXwaylandDisplay(parser.value(xwaylandDisplayOption));
595 } else {
596 std::cerr << "Using xwayland-fd without xwayland-display is undefined" << std::endl;
597 return 1;
598 }
599 if (parser.isSet(xwaylandXAuthorityOption)) {
600 a.setXwaylandXauthority(parser.value(xwaylandXAuthorityOption));
601 }
602 }
603 }
604
605 a.setApplicationsToStart(parser.positionalArguments());
606 a.setInputMethodServerToStart(parser.value(inputMethodOption));
607 a.start();
608
609 return a.exec();
610}
611
612#include "moc_main_wayland.cpp"
void destroyWorkspace()
Definition main.cpp:313
void notifyStarted()
Definition main.cpp:146
OutputBackend * outputBackend() const
Definition main.h:242
void destroyColorManager()
Definition main.cpp:328
void createOptions()
Definition main.cpp:268
static void createAboutData()
Definition main.cpp:177
void createPlugins()
Definition main.cpp:273
void destroyInput()
Definition main.cpp:308
void setOperationMode(OperationMode mode)
Definition main.cpp:102
void createTabletModeManager()
Definition main.cpp:288
static void setupMalloc()
Definition main.cpp:220
void createInput()
Definition main.cpp:253
void setSession(std::unique_ptr< Session > &&session)
Definition main.cpp:644
void setFollowLocale1(bool follow)
Definition main.h:253
void destroyPlugins()
Definition main.cpp:323
void setOutputBackend(std::unique_ptr< OutputBackend > &&backend)
Definition main.cpp:638
void processCommandLine(QCommandLineParser *parser)
Definition main.cpp:212
void setProcessStartupEnvironment(const QProcessEnvironment &environment)
Definition main.cpp:633
QProcessEnvironment processStartupEnvironment() const
Definition main.cpp:628
Session * session() const
Definition main.h:248
void destroyInputMethod()
Definition main.cpp:333
void createColorManager()
Definition main.cpp:278
void setXwaylandScale(qreal scale)
Definition main.cpp:382
static void setupLocalizedString()
Definition main.cpp:234
void setupCommandLine(QCommandLineParser *parser)
Definition main.cpp:201
void createWorkspace()
Definition main.cpp:239
OperationMode operationMode() const
The operation mode used by KWin.
Definition main.cpp:97
void createInputMethod()
Definition main.cpp:283
void applyXwaylandScale()
Definition main.cpp:392
void setTerminating()
Definition main.h:365
@ OperationModeXwayland
KWin uses Wayland and controls a nested Xwayland server.
Definition main.h:95
void destroyCompositor()
Definition main.cpp:318
KSharedConfigPtr config
Definition main.h:74
void setInputMethodServerToStart(const QString &inputMethodServer)
void setStartXwayland(bool start)
void setApplicationsToStart(const QStringList &applications)
void addXwaylandSocketFileDescriptor(int fd)
void setSessionArgument(const QString &session)
void performStartup() override
void setXwaylandXauthority(const QString &xauthority)
void setXwaylandDisplay(const QString &display)
XwaylandInterface * xwayland() const override
static Compositor * self()
QStringList socketNames() const
Definition display.cpp:87
bool addSocketName(const QString &name=QString())
Definition display.cpp:68
bool addSocketFileDescriptor(int fileDescriptor, const QString &socketName=QString())
Definition display.cpp:56
virtual void sceneInitialized()
static std::unique_ptr< Session > create()
Definition session.cpp:25
static WaylandCompositor * create(QObject *parent=nullptr)
bool init(const QString &socketName, InitializationFlags flags=InitializationFlag::NoOptions)
Display * display() const
QString socketName() const
void gainRealTime()
Definition realtime.cpp:16
void disableDrKonqi()
WaylandServer * waylandServer()
EffectsHandler * effects