Warning, file /plasma/kwin/src/main_wayland.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "main_wayland.h" 0010 0011 #include <config-kwin.h> 0012 0013 #include "backends/drm/drm_backend.h" 0014 #include "backends/virtual/virtual_backend.h" 0015 #include "backends/wayland/wayland_backend.h" 0016 #include "backends/x11/windowed/x11_windowed_backend.h" 0017 #include "composite.h" 0018 #include "core/outputbackend.h" 0019 #include "core/session.h" 0020 #include "effects.h" 0021 #include "inputmethod.h" 0022 #include "tabletmodemanager.h" 0023 #include "utils/realtime.h" 0024 #include "wayland/display.h" 0025 #include "wayland/seat_interface.h" 0026 #include "wayland_server.h" 0027 #include "workspace.h" 0028 #include "xwayland/xwayland.h" 0029 #include "xwayland/xwaylandlauncher.h" 0030 0031 // KDE 0032 #include <KCrash> 0033 #include <KDesktopFile> 0034 #include <KLocalizedString> 0035 #include <KShell> 0036 #include <KSignalHandler> 0037 0038 // Qt 0039 #include <QCommandLineParser> 0040 #include <QDBusInterface> 0041 #include <QDebug> 0042 #include <QFileInfo> 0043 #include <QProcess> 0044 #include <QWindow> 0045 #include <qplatformdefs.h> 0046 0047 #include <sched.h> 0048 #include <sys/resource.h> 0049 0050 #include <iomanip> 0051 #include <iostream> 0052 0053 Q_IMPORT_PLUGIN(KWinIntegrationPlugin) 0054 Q_IMPORT_PLUGIN(KGlobalAccelImpl) 0055 Q_IMPORT_PLUGIN(KWindowSystemKWinPlugin) 0056 Q_IMPORT_PLUGIN(KWinIdleTimePoller) 0057 #if PipeWire_FOUND 0058 Q_IMPORT_PLUGIN(ScreencastManagerFactory) 0059 #endif 0060 0061 namespace KWin 0062 { 0063 0064 static rlimit originalNofileLimit = { 0065 .rlim_cur = 0, 0066 .rlim_max = 0, 0067 }; 0068 0069 static bool bumpNofileLimit() 0070 { 0071 if (getrlimit(RLIMIT_NOFILE, &originalNofileLimit) == -1) { 0072 std::cerr << "Failed to bump RLIMIT_NOFILE limit, getrlimit() failed: " << strerror(errno) << std::endl; 0073 return false; 0074 } 0075 0076 rlimit limit = originalNofileLimit; 0077 limit.rlim_cur = limit.rlim_max; 0078 0079 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) { 0080 std::cerr << "Failed to bump RLIMIT_NOFILE limit, setrlimit() failed: " << strerror(errno) << std::endl; 0081 return false; 0082 } 0083 0084 return true; 0085 } 0086 0087 static void restoreNofileLimit() 0088 { 0089 if (setrlimit(RLIMIT_NOFILE, &originalNofileLimit) == -1) { 0090 std::cerr << "Failed to restore RLIMIT_NOFILE limit, legacy apps might be broken" << std::endl; 0091 } 0092 } 0093 0094 void disableDrKonqi() 0095 { 0096 KCrash::setDrKonqiEnabled(false); 0097 } 0098 // run immediately, before Q_CORE_STARTUP functions 0099 // that would enable drkonqi 0100 Q_CONSTRUCTOR_FUNCTION(disableDrKonqi) 0101 0102 //************************************ 0103 // ApplicationWayland 0104 //************************************ 0105 0106 ApplicationWayland::ApplicationWayland(int &argc, char **argv) 0107 : Application(OperationModeWaylandOnly, argc, argv) 0108 { 0109 } 0110 0111 ApplicationWayland::~ApplicationWayland() 0112 { 0113 setTerminating(); 0114 if (!waylandServer()) { 0115 return; 0116 } 0117 0118 destroyPlugins(); 0119 0120 // need to unload all effects prior to destroying X connection as they might do X calls 0121 if (effects) { 0122 static_cast<EffectsHandlerImpl *>(effects)->unloadAllEffects(); 0123 } 0124 m_xwayland.reset(); 0125 destroyColorManager(); 0126 destroyWorkspace(); 0127 0128 destroyInputMethod(); 0129 destroyCompositor(); 0130 destroyInput(); 0131 } 0132 0133 void ApplicationWayland::performStartup() 0134 { 0135 if (m_startXWayland) { 0136 setOperationMode(OperationModeXwayland); 0137 setXwaylandScale(config()->group("Xwayland").readEntry("Scale", 1.0)); 0138 } 0139 // first load options - done internally by a different thread 0140 createOptions(); 0141 0142 if (!outputBackend()->initialize()) { 0143 std::exit(1); 0144 } 0145 0146 createInput(); 0147 createInputMethod(); 0148 createTabletModeManager(); 0149 0150 WaylandCompositor::create(); 0151 0152 connect(Compositor::self(), &Compositor::sceneCreated, outputBackend(), &OutputBackend::sceneInitialized); 0153 connect(Compositor::self(), &Compositor::sceneCreated, this, &ApplicationWayland::continueStartupWithScene); 0154 } 0155 0156 void ApplicationWayland::continueStartupWithScene() 0157 { 0158 disconnect(Compositor::self(), &Compositor::sceneCreated, this, &ApplicationWayland::continueStartupWithScene); 0159 0160 // Note that we start accepting client connections after creating the Workspace. 0161 createWorkspace(); 0162 createColorManager(); 0163 createPlugins(); 0164 0165 if (!waylandServer()->start()) { 0166 qFatal("Failed to initialze the Wayland server, exiting now"); 0167 } 0168 0169 if (operationMode() == OperationModeWaylandOnly) { 0170 finalizeStartup(); 0171 return; 0172 } 0173 0174 m_xwayland = std::make_unique<Xwl::Xwayland>(this); 0175 m_xwayland->xwaylandLauncher()->setListenFDs(m_xwaylandListenFds); 0176 m_xwayland->xwaylandLauncher()->setDisplayName(m_xwaylandDisplay); 0177 m_xwayland->xwaylandLauncher()->setXauthority(m_xwaylandXauthority); 0178 connect(m_xwayland.get(), &Xwl::Xwayland::errorOccurred, this, &ApplicationWayland::finalizeStartup); 0179 connect(m_xwayland.get(), &Xwl::Xwayland::started, this, &ApplicationWayland::finalizeStartup); 0180 m_xwayland->start(); 0181 } 0182 0183 void ApplicationWayland::finalizeStartup() 0184 { 0185 if (m_xwayland) { 0186 disconnect(m_xwayland.get(), &Xwl::Xwayland::errorOccurred, this, &ApplicationWayland::finalizeStartup); 0187 disconnect(m_xwayland.get(), &Xwl::Xwayland::started, this, &ApplicationWayland::finalizeStartup); 0188 } 0189 startSession(); 0190 notifyStarted(); 0191 } 0192 0193 void ApplicationWayland::refreshSettings(const KConfigGroup &group, const QByteArrayList &names) 0194 { 0195 if (group.name() == "Wayland" && names.contains("InputMethod")) { 0196 KDesktopFile file(group.readPathEntry("InputMethod", QString())); 0197 kwinApp()->inputMethod()->setInputMethodCommand(file.desktopGroup().readEntry("Exec", QString())); 0198 } 0199 0200 if (m_startXWayland && group.name() == "Xwayland" && names.contains("Scale")) { 0201 setXwaylandScale(group.readEntry("Scale", 1.0)); 0202 } 0203 } 0204 0205 void ApplicationWayland::startSession() 0206 { 0207 KSharedConfig::Ptr kwinSettings = kwinApp()->config(); 0208 m_settingsWatcher = KConfigWatcher::create(kwinSettings); 0209 connect(m_settingsWatcher.data(), &KConfigWatcher::configChanged, this, &ApplicationWayland::refreshSettings); 0210 0211 if (!m_inputMethodServerToStart.isEmpty()) { 0212 kwinApp()->inputMethod()->setInputMethodCommand(m_inputMethodServerToStart); 0213 } else { 0214 refreshSettings(kwinSettings->group("Wayland"), {"InputMethod"}); 0215 } 0216 0217 // start session 0218 if (!m_sessionArgument.isEmpty()) { 0219 QStringList arguments = KShell::splitArgs(m_sessionArgument); 0220 if (!arguments.isEmpty()) { 0221 QString program = arguments.takeFirst(); 0222 QProcess *p = new QProcess(this); 0223 p->setProcessChannelMode(QProcess::ForwardedErrorChannel); 0224 p->setProcessEnvironment(processStartupEnvironment()); 0225 connect(p, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [p](int code, QProcess::ExitStatus status) { 0226 p->deleteLater(); 0227 if (status == QProcess::CrashExit) { 0228 qWarning() << "Session process has crashed"; 0229 QCoreApplication::exit(-1); 0230 return; 0231 } 0232 0233 if (code) { 0234 qWarning() << "Session process exited with code" << code; 0235 } 0236 0237 QCoreApplication::exit(code); 0238 }); 0239 p->setProgram(program); 0240 p->setArguments(arguments); 0241 p->start(); 0242 } else { 0243 qWarning("Failed to launch the session process: %s is an invalid command", 0244 qPrintable(m_sessionArgument)); 0245 } 0246 } 0247 // start the applications passed to us as command line arguments 0248 if (!m_applicationsToStart.isEmpty()) { 0249 for (const QString &application : std::as_const(m_applicationsToStart)) { 0250 QStringList arguments = KShell::splitArgs(application); 0251 if (arguments.isEmpty()) { 0252 qWarning("Failed to launch application: %s is an invalid command", 0253 qPrintable(application)); 0254 continue; 0255 } 0256 QString program = arguments.takeFirst(); 0257 // note: this will kill the started process when we exit 0258 // this is going to happen anyway as we are the wayland and X server the app connects to 0259 QProcess *p = new QProcess(this); 0260 p->setProcessChannelMode(QProcess::ForwardedErrorChannel); 0261 p->setProcessEnvironment(processStartupEnvironment()); 0262 p->setProgram(program); 0263 p->setArguments(arguments); 0264 p->startDetached(); 0265 p->deleteLater(); 0266 } 0267 } 0268 } 0269 0270 XwaylandInterface *ApplicationWayland::xwayland() const 0271 { 0272 return m_xwayland.get(); 0273 } 0274 0275 } // namespace 0276 0277 int main(int argc, char *argv[]) 0278 { 0279 KWin::Application::setupMalloc(); 0280 KWin::Application::setupLocalizedString(); 0281 KWin::gainRealTime(); 0282 0283 signal(SIGPIPE, SIG_IGN); 0284 0285 // It's easy to exceed the file descriptor limit because many things are backed using fds 0286 // nowadays, e.g. dmabufs, shm buffers, etc. Bump the RLIMIT_NOFILE limit to handle that. 0287 // Some apps may still use select(), so we reset the limit to its original value in fork(). 0288 if (KWin::bumpNofileLimit()) { 0289 pthread_atfork(nullptr, nullptr, KWin::restoreNofileLimit); 0290 } 0291 0292 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); 0293 0294 // enforce our internal qpa plugin, unfortunately command line switch has precedence 0295 setenv("QT_QPA_PLATFORM", "wayland-org.kde.kwin.qpa", true); 0296 0297 qunsetenv("QT_DEVICE_PIXEL_RATIO"); 0298 qputenv("QSG_RENDER_LOOP", "basic"); 0299 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); 0300 KWin::ApplicationWayland a(argc, argv); 0301 a.setupTranslator(); 0302 // reset QT_QPA_PLATFORM so we don't propagate it to our children (e.g. apps launched from the overview effect) 0303 qunsetenv("QT_QPA_PLATFORM"); 0304 0305 KSignalHandler::self()->watchSignal(SIGTERM); 0306 KSignalHandler::self()->watchSignal(SIGINT); 0307 KSignalHandler::self()->watchSignal(SIGHUP); 0308 QObject::connect(KSignalHandler::self(), &KSignalHandler::signalReceived, 0309 &a, &QCoreApplication::exit); 0310 0311 KWin::Application::createAboutData(); 0312 0313 QCommandLineOption xwaylandOption(QStringLiteral("xwayland"), 0314 i18n("Start a rootless Xwayland server.")); 0315 QCommandLineOption waylandSocketOption(QStringList{QStringLiteral("s"), QStringLiteral("socket")}, 0316 i18n("Name of the Wayland socket to listen on. If not set \"wayland-0\" is used."), 0317 QStringLiteral("socket")); 0318 QCommandLineOption x11DisplayOption(QStringLiteral("x11-display"), 0319 i18n("The X11 Display to use in windowed mode on platform X11."), 0320 QStringLiteral("display")); 0321 QCommandLineOption waylandDisplayOption(QStringLiteral("wayland-display"), 0322 i18n("The Wayland Display to use in windowed mode on platform Wayland."), 0323 QStringLiteral("display")); 0324 QCommandLineOption virtualFbOption(QStringLiteral("virtual"), i18n("Render to a virtual framebuffer.")); 0325 QCommandLineOption widthOption(QStringLiteral("width"), 0326 i18n("The width for windowed mode. Default width is 1024."), 0327 QStringLiteral("width")); 0328 widthOption.setDefaultValue(QString::number(1024)); 0329 QCommandLineOption heightOption(QStringLiteral("height"), 0330 i18n("The height for windowed mode. Default height is 768."), 0331 QStringLiteral("height")); 0332 heightOption.setDefaultValue(QString::number(768)); 0333 0334 QCommandLineOption scaleOption(QStringLiteral("scale"), 0335 i18n("The scale for windowed mode. Default value is 1."), 0336 QStringLiteral("scale")); 0337 scaleOption.setDefaultValue(QString::number(1)); 0338 0339 QCommandLineOption outputCountOption(QStringLiteral("output-count"), 0340 i18n("The number of windows to open as outputs in windowed mode. Default value is 1"), 0341 QStringLiteral("count")); 0342 outputCountOption.setDefaultValue(QString::number(1)); 0343 0344 QCommandLineOption waylandSocketFdOption(QStringLiteral("wayland-fd"), 0345 i18n("Wayland socket to use for incoming connections. This can be combined with --socket to name the socket"), 0346 QStringLiteral("wayland-fd")); 0347 0348 QCommandLineOption xwaylandListenFdOption(QStringLiteral("xwayland-fd"), 0349 i18n("XWayland socket to use for Xwayland's incoming connections. This can be set multiple times"), 0350 QStringLiteral("xwayland-fds")); 0351 0352 QCommandLineOption xwaylandDisplayOption(QStringLiteral("xwayland-display"), 0353 i18n("Name of the xwayland display that has been pre-set up"), 0354 "xwayland-display"); 0355 0356 QCommandLineOption xwaylandXAuthorityOption(QStringLiteral("xwayland-xauthority"), 0357 i18n("Name of the xauthority file "), 0358 "xwayland-xauthority"); 0359 0360 QCommandLineOption replaceOption(QStringLiteral("replace"), 0361 i18n("Exits this instance so it can be restarted by kwin_wayland_wrapper.")); 0362 0363 QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node.")); 0364 QCommandLineOption locale1Option(QStringLiteral("locale1"), i18n("Extract locale information from locale1 rather than the user's configuration")); 0365 0366 QCommandLineParser parser; 0367 a.setupCommandLine(&parser); 0368 parser.addOption(xwaylandOption); 0369 parser.addOption(waylandSocketOption); 0370 parser.addOption(waylandSocketFdOption); 0371 parser.addOption(xwaylandListenFdOption); 0372 parser.addOption(xwaylandDisplayOption); 0373 parser.addOption(xwaylandXAuthorityOption); 0374 parser.addOption(replaceOption); 0375 parser.addOption(x11DisplayOption); 0376 parser.addOption(waylandDisplayOption); 0377 parser.addOption(virtualFbOption); 0378 parser.addOption(widthOption); 0379 parser.addOption(heightOption); 0380 parser.addOption(scaleOption); 0381 parser.addOption(outputCountOption); 0382 parser.addOption(drmOption); 0383 parser.addOption(locale1Option); 0384 0385 QCommandLineOption inputMethodOption(QStringLiteral("inputmethod"), 0386 i18n("Input method that KWin starts."), 0387 QStringLiteral("path/to/imserver")); 0388 parser.addOption(inputMethodOption); 0389 0390 #if KWIN_BUILD_SCREENLOCKER 0391 QCommandLineOption screenLockerOption(QStringLiteral("lockscreen"), 0392 i18n("Starts the session in locked mode.")); 0393 parser.addOption(screenLockerOption); 0394 0395 QCommandLineOption noScreenLockerOption(QStringLiteral("no-lockscreen"), 0396 i18n("Starts the session without lock screen support.")); 0397 parser.addOption(noScreenLockerOption); 0398 #endif 0399 0400 QCommandLineOption noGlobalShortcutsOption(QStringLiteral("no-global-shortcuts"), 0401 i18n("Starts the session without global shortcuts support.")); 0402 parser.addOption(noGlobalShortcutsOption); 0403 0404 #if KWIN_BUILD_ACTIVITIES 0405 QCommandLineOption noActivitiesOption(QStringLiteral("no-kactivities"), 0406 i18n("Disable KActivities integration.")); 0407 parser.addOption(noActivitiesOption); 0408 #endif 0409 0410 QCommandLineOption exitWithSessionOption(QStringLiteral("exit-with-session"), 0411 i18n("Exit after the session application, which is started by KWin, closed."), 0412 QStringLiteral("/path/to/session")); 0413 parser.addOption(exitWithSessionOption); 0414 0415 parser.addPositionalArgument(QStringLiteral("applications"), 0416 i18n("Applications to start once Wayland and Xwayland server are started"), 0417 QStringLiteral("[/path/to/application...]")); 0418 0419 parser.process(a); 0420 a.processCommandLine(&parser); 0421 0422 #if KWIN_BUILD_ACTIVITIES 0423 if (parser.isSet(noActivitiesOption)) { 0424 a.setUseKActivities(false); 0425 } 0426 #endif 0427 0428 if (parser.isSet(replaceOption)) { 0429 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), QStringLiteral("/KWin"), 0430 QStringLiteral("org.kde.KWin"), QStringLiteral("replace")); 0431 QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); 0432 return 0; 0433 } 0434 0435 if (parser.isSet(exitWithSessionOption)) { 0436 a.setSessionArgument(parser.value(exitWithSessionOption)); 0437 } 0438 0439 enum class BackendType { 0440 Kms, 0441 X11, 0442 Wayland, 0443 Virtual, 0444 }; 0445 0446 BackendType backendType; 0447 QString pluginName; 0448 QSize initialWindowSize; 0449 int outputCount = 1; 0450 qreal outputScale = 1; 0451 0452 // Decide what backend to use. 0453 if (parser.isSet(drmOption)) { 0454 backendType = BackendType::Kms; 0455 } else if (parser.isSet(x11DisplayOption)) { 0456 backendType = BackendType::X11; 0457 } else if (parser.isSet(waylandDisplayOption)) { 0458 backendType = BackendType::Wayland; 0459 } else if (parser.isSet(virtualFbOption)) { 0460 backendType = BackendType::Virtual; 0461 } else { 0462 if (qEnvironmentVariableIsSet("WAYLAND_DISPLAY")) { 0463 qWarning("No backend specified, automatically choosing Wayland because WAYLAND_DISPLAY is set"); 0464 backendType = BackendType::Wayland; 0465 } else if (qEnvironmentVariableIsSet("DISPLAY")) { 0466 qWarning("No backend specified, automatically choosing X11 because DISPLAY is set"); 0467 backendType = BackendType::X11; 0468 } else { 0469 qWarning("No backend specified, automatically choosing drm"); 0470 backendType = BackendType::Kms; 0471 } 0472 } 0473 0474 if (parser.isSet(locale1Option)) { 0475 a.setFollowLocale1(true); 0476 } 0477 0478 bool ok = false; 0479 const int width = parser.value(widthOption).toInt(&ok); 0480 if (!ok) { 0481 std::cerr << "FATAL ERROR incorrect value for width" << std::endl; 0482 return 1; 0483 } 0484 const int height = parser.value(heightOption).toInt(&ok); 0485 if (!ok) { 0486 std::cerr << "FATAL ERROR incorrect value for height" << std::endl; 0487 return 1; 0488 } 0489 const qreal scale = parser.value(scaleOption).toDouble(&ok); 0490 if (!ok || scale <= 0) { 0491 std::cerr << "FATAL ERROR incorrect value for scale" << std::endl; 0492 return 1; 0493 } 0494 0495 outputScale = scale; 0496 initialWindowSize = QSize(width, height); 0497 0498 const int count = parser.value(outputCountOption).toInt(&ok); 0499 if (ok) { 0500 outputCount = std::max(1, count); 0501 } 0502 0503 // TODO: create backend without having the server running 0504 KWin::WaylandServer *server = KWin::WaylandServer::create(&a); 0505 0506 KWin::WaylandServer::InitializationFlags flags; 0507 #if KWIN_BUILD_SCREENLOCKER 0508 if (parser.isSet(screenLockerOption)) { 0509 flags = KWin::WaylandServer::InitializationFlag::LockScreen; 0510 } else if (parser.isSet(noScreenLockerOption)) { 0511 flags = KWin::WaylandServer::InitializationFlag::NoLockScreenIntegration; 0512 } 0513 #endif 0514 if (parser.isSet(noGlobalShortcutsOption)) { 0515 flags |= KWin::WaylandServer::InitializationFlag::NoGlobalShortcuts; 0516 } 0517 0518 const QString socketName = parser.value(waylandSocketOption); 0519 if (parser.isSet(waylandSocketFdOption)) { 0520 bool ok; 0521 int fd = parser.value(waylandSocketFdOption).toInt(&ok); 0522 if (ok) { 0523 // make sure we don't leak this FD to children 0524 fcntl(fd, F_SETFD, FD_CLOEXEC); 0525 server->display()->addSocketFileDescriptor(fd, socketName); 0526 } else { 0527 std::cerr << "FATAL ERROR: could not parse socket FD" << std::endl; 0528 return 1; 0529 } 0530 } else { 0531 // socketName empty is fine here, addSocketName will automatically pick one 0532 if (!server->display()->addSocketName(socketName)) { 0533 std::cerr << "FATAL ERROR: could not add wayland socket " << qPrintable(socketName) << std::endl; 0534 return 1; 0535 } 0536 } 0537 0538 if (!server->init(flags)) { 0539 std::cerr << "FATAL ERROR: could not create Wayland server" << std::endl; 0540 return 1; 0541 } 0542 0543 switch (backendType) { 0544 case BackendType::Kms: 0545 a.setSession(KWin::Session::create()); 0546 if (!a.session()) { 0547 std::cerr << "FATAl ERROR: could not acquire a session" << std::endl; 0548 return 1; 0549 } 0550 a.setOutputBackend(std::make_unique<KWin::DrmBackend>(a.session())); 0551 break; 0552 case BackendType::Virtual: { 0553 auto outputBackend = std::make_unique<KWin::VirtualBackend>(); 0554 for (int i = 0; i < outputCount; ++i) { 0555 outputBackend->addOutput(initialWindowSize, outputScale); 0556 } 0557 a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); 0558 a.setOutputBackend(std::move(outputBackend)); 0559 break; 0560 } 0561 case BackendType::X11: { 0562 QString display = parser.value(x11DisplayOption); 0563 if (display.isEmpty()) { 0564 display = qgetenv("DISPLAY"); 0565 } 0566 a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); 0567 a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>(KWin::X11WindowedBackendOptions{ 0568 .display = display, 0569 .outputCount = outputCount, 0570 .outputScale = outputScale, 0571 .outputSize = initialWindowSize, 0572 })); 0573 break; 0574 } 0575 case BackendType::Wayland: { 0576 QString socketName = parser.value(waylandDisplayOption); 0577 if (socketName.isEmpty()) { 0578 socketName = qgetenv("WAYLAND_DISPLAY"); 0579 } 0580 a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); 0581 a.setOutputBackend(std::make_unique<KWin::Wayland::WaylandBackend>(KWin::Wayland::WaylandBackendOptions{ 0582 .socketName = socketName, 0583 .outputCount = outputCount, 0584 .outputScale = outputScale, 0585 .outputSize = initialWindowSize, 0586 })); 0587 break; 0588 } 0589 } 0590 0591 QObject::connect(&a, &KWin::Application::workspaceCreated, server, &KWin::WaylandServer::initWorkspace); 0592 if (!server->socketName().isEmpty()) { 0593 environment.insert(QStringLiteral("WAYLAND_DISPLAY"), server->socketName()); 0594 qputenv("WAYLAND_DISPLAY", server->socketName().toUtf8()); 0595 } 0596 a.setProcessStartupEnvironment(environment); 0597 0598 if (parser.isSet(xwaylandOption)) { 0599 a.setStartXwayland(true); 0600 0601 if (parser.isSet(xwaylandListenFdOption)) { 0602 const QStringList fdStrings = parser.values(xwaylandListenFdOption); 0603 for (const QString &fdString : fdStrings) { 0604 bool ok; 0605 int fd = fdString.toInt(&ok); 0606 if (ok) { 0607 // make sure we don't leak this FD to children 0608 fcntl(fd, F_SETFD, FD_CLOEXEC); 0609 a.addXwaylandSocketFileDescriptor(fd); 0610 } 0611 } 0612 if (parser.isSet(xwaylandDisplayOption)) { 0613 a.setXwaylandDisplay(parser.value(xwaylandDisplayOption)); 0614 } else { 0615 std::cerr << "Using xwayland-fd without xwayland-display is undefined" << std::endl; 0616 return 1; 0617 } 0618 if (parser.isSet(xwaylandXAuthorityOption)) { 0619 a.setXwaylandXauthority(parser.value(xwaylandXAuthorityOption)); 0620 } 0621 } 0622 } 0623 0624 a.setApplicationsToStart(parser.positionalArguments()); 0625 a.setInputMethodServerToStart(parser.value(inputMethodOption)); 0626 a.start(); 0627 0628 return a.exec(); 0629 }