File indexing completed on 2024-11-10 04:57:51
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 "compositor_wayland.h" 0018 #include "core/outputbackend.h" 0019 #include "core/session.h" 0020 #include "effect/effecthandler.h" 0021 #include "inputmethod.h" 0022 #include "tabletmodemanager.h" 0023 #include "utils/realtime.h" 0024 #include "wayland/display.h" 0025 #include "wayland/seat.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 <QtPlugin> 0046 #include <qplatformdefs.h> 0047 0048 #include <sched.h> 0049 #include <sys/resource.h> 0050 0051 #include <iomanip> 0052 #include <iostream> 0053 0054 Q_IMPORT_PLUGIN(KWinIntegrationPlugin) 0055 #if KWIN_BUILD_GLOBALSHORTCUTS 0056 Q_IMPORT_PLUGIN(KGlobalAccelImpl) 0057 #endif 0058 Q_IMPORT_PLUGIN(KWindowSystemKWinPlugin) 0059 Q_IMPORT_PLUGIN(KWinIdleTimePoller) 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 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(QStringLiteral("Xwayland")).readEntry("Scale", 1.0)); 0138 } 0139 createOptions(); 0140 0141 if (!outputBackend()->initialize()) { 0142 std::exit(1); 0143 } 0144 0145 createInput(); 0146 createInputMethod(); 0147 createTabletModeManager(); 0148 0149 WaylandCompositor::create(); 0150 createWorkspace(); 0151 createColorManager(); 0152 createPlugins(); 0153 0154 connect(Compositor::self(), &Compositor::sceneCreated, outputBackend(), &OutputBackend::sceneInitialized); 0155 connect(Compositor::self(), &Compositor::sceneCreated, this, &ApplicationWayland::continueStartupWithScene, Qt::SingleShotConnection); 0156 } 0157 0158 void ApplicationWayland::continueStartupWithScene() 0159 { 0160 // Note that we start accepting client connections after creating the Workspace. 0161 if (!waylandServer()->start()) { 0162 qFatal("Failed to initialze the Wayland server, exiting now"); 0163 } 0164 0165 if (operationMode() == OperationModeXwayland) { 0166 m_xwayland = std::make_unique<Xwl::Xwayland>(this); 0167 m_xwayland->xwaylandLauncher()->setListenFDs(m_xwaylandListenFds); 0168 m_xwayland->xwaylandLauncher()->setDisplayName(m_xwaylandDisplay); 0169 m_xwayland->xwaylandLauncher()->setXauthority(m_xwaylandXauthority); 0170 m_xwayland->init(); 0171 connect(m_xwayland.get(), &Xwl::Xwayland::started, this, &ApplicationWayland::applyXwaylandScale); 0172 } 0173 startSession(); 0174 notifyStarted(); 0175 } 0176 0177 void ApplicationWayland::refreshSettings(const KConfigGroup &group, const QByteArrayList &names) 0178 { 0179 if (group.name() == "Wayland" && names.contains("InputMethod")) { 0180 KDesktopFile file(group.readPathEntry("InputMethod", QString())); 0181 kwinApp()->inputMethod()->setInputMethodCommand(file.desktopGroup().readEntry("Exec", QString())); 0182 } 0183 } 0184 0185 void ApplicationWayland::startSession() 0186 { 0187 KSharedConfig::Ptr kwinSettings = kwinApp()->config(); 0188 m_settingsWatcher = KConfigWatcher::create(kwinSettings); 0189 connect(m_settingsWatcher.data(), &KConfigWatcher::configChanged, this, &ApplicationWayland::refreshSettings); 0190 0191 if (!m_inputMethodServerToStart.isEmpty()) { 0192 kwinApp()->inputMethod()->setInputMethodCommand(m_inputMethodServerToStart); 0193 } else { 0194 refreshSettings(kwinSettings->group(QStringLiteral("Wayland")), {"InputMethod"}); 0195 } 0196 0197 // start session 0198 if (!m_sessionArgument.isEmpty()) { 0199 QStringList arguments = KShell::splitArgs(m_sessionArgument); 0200 if (!arguments.isEmpty()) { 0201 QString program = arguments.takeFirst(); 0202 QProcess *p = new QProcess(this); 0203 p->setProcessChannelMode(QProcess::ForwardedChannels); 0204 p->setProcessEnvironment(processStartupEnvironment()); 0205 connect(p, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, [p](int code, QProcess::ExitStatus status) { 0206 p->deleteLater(); 0207 if (status == QProcess::CrashExit) { 0208 qWarning() << "Session process has crashed"; 0209 QCoreApplication::exit(-1); 0210 return; 0211 } 0212 0213 if (code) { 0214 qWarning() << "Session process exited with code" << code; 0215 } 0216 0217 QCoreApplication::exit(code); 0218 }); 0219 p->setProgram(program); 0220 p->setArguments(arguments); 0221 p->start(); 0222 } else { 0223 qWarning("Failed to launch the session process: %s is an invalid command", 0224 qPrintable(m_sessionArgument)); 0225 } 0226 } 0227 // start the applications passed to us as command line arguments 0228 if (!m_applicationsToStart.isEmpty()) { 0229 for (const QString &application : std::as_const(m_applicationsToStart)) { 0230 QStringList arguments = KShell::splitArgs(application); 0231 if (arguments.isEmpty()) { 0232 qWarning("Failed to launch application: %s is an invalid command", 0233 qPrintable(application)); 0234 continue; 0235 } 0236 QString program = arguments.takeFirst(); 0237 // note: this will kill the started process when we exit 0238 // this is going to happen anyway as we are the wayland and X server the app connects to 0239 QProcess *p = new QProcess(this); 0240 p->setProcessChannelMode(QProcess::ForwardedChannels); 0241 p->setProcessEnvironment(processStartupEnvironment()); 0242 p->setProgram(program); 0243 p->setArguments(arguments); 0244 p->startDetached(); 0245 p->deleteLater(); 0246 } 0247 } 0248 } 0249 0250 XwaylandInterface *ApplicationWayland::xwayland() const 0251 { 0252 return m_xwayland.get(); 0253 } 0254 0255 } // namespace 0256 0257 int main(int argc, char *argv[]) 0258 { 0259 KWin::Application::setupMalloc(); 0260 KWin::Application::setupLocalizedString(); 0261 KWin::gainRealTime(); 0262 0263 signal(SIGPIPE, SIG_IGN); 0264 0265 // It's easy to exceed the file descriptor limit because many things are backed using fds 0266 // nowadays, e.g. dmabufs, shm buffers, etc. Bump the RLIMIT_NOFILE limit to handle that. 0267 // Some apps may still use select(), so we reset the limit to its original value in fork(). 0268 if (KWin::bumpNofileLimit()) { 0269 pthread_atfork(nullptr, nullptr, KWin::restoreNofileLimit); 0270 } 0271 0272 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); 0273 0274 // enforce our internal qpa plugin, unfortunately command line switch has precedence 0275 setenv("QT_QPA_PLATFORM", "wayland-org.kde.kwin.qpa", true); 0276 0277 KWin::ApplicationWayland a(argc, argv); 0278 0279 // reset QT_QPA_PLATFORM so we don't propagate it to our children (e.g. apps launched from the overview effect) 0280 qunsetenv("QT_QPA_PLATFORM"); 0281 0282 KSignalHandler::self()->watchSignal(SIGTERM); 0283 KSignalHandler::self()->watchSignal(SIGINT); 0284 KSignalHandler::self()->watchSignal(SIGHUP); 0285 QObject::connect(KSignalHandler::self(), &KSignalHandler::signalReceived, 0286 &a, &QCoreApplication::exit); 0287 0288 KWin::Application::createAboutData(); 0289 0290 QCommandLineOption xwaylandOption(QStringLiteral("xwayland"), 0291 i18n("Start a rootless Xwayland server.")); 0292 QCommandLineOption waylandSocketOption(QStringList{QStringLiteral("s"), QStringLiteral("socket")}, 0293 i18n("Name of the Wayland socket to listen on. If not set \"wayland-0\" is used."), 0294 QStringLiteral("socket")); 0295 QCommandLineOption x11DisplayOption(QStringLiteral("x11-display"), 0296 i18n("The X11 Display to use in windowed mode on platform X11."), 0297 QStringLiteral("display")); 0298 QCommandLineOption waylandDisplayOption(QStringLiteral("wayland-display"), 0299 i18n("The Wayland Display to use in windowed mode on platform Wayland."), 0300 QStringLiteral("display")); 0301 QCommandLineOption virtualFbOption(QStringLiteral("virtual"), i18n("Render to a virtual framebuffer.")); 0302 QCommandLineOption widthOption(QStringLiteral("width"), 0303 i18n("The width for windowed mode. Default width is 1024."), 0304 QStringLiteral("width")); 0305 widthOption.setDefaultValue(QString::number(1024)); 0306 QCommandLineOption heightOption(QStringLiteral("height"), 0307 i18n("The height for windowed mode. Default height is 768."), 0308 QStringLiteral("height")); 0309 heightOption.setDefaultValue(QString::number(768)); 0310 0311 QCommandLineOption scaleOption(QStringLiteral("scale"), 0312 i18n("The scale for windowed mode. Default value is 1."), 0313 QStringLiteral("scale")); 0314 scaleOption.setDefaultValue(QString::number(1)); 0315 0316 QCommandLineOption outputCountOption(QStringLiteral("output-count"), 0317 i18n("The number of windows to open as outputs in windowed mode. Default value is 1"), 0318 QStringLiteral("count")); 0319 outputCountOption.setDefaultValue(QString::number(1)); 0320 0321 QCommandLineOption waylandSocketFdOption(QStringLiteral("wayland-fd"), 0322 i18n("Wayland socket to use for incoming connections. This can be combined with --socket to name the socket"), 0323 QStringLiteral("wayland-fd")); 0324 0325 QCommandLineOption xwaylandListenFdOption(QStringLiteral("xwayland-fd"), 0326 i18n("XWayland socket to use for Xwayland's incoming connections. This can be set multiple times"), 0327 QStringLiteral("xwayland-fds")); 0328 0329 QCommandLineOption xwaylandDisplayOption(QStringLiteral("xwayland-display"), 0330 i18n("Name of the xwayland display that has been pre-set up"), 0331 "xwayland-display"); 0332 0333 QCommandLineOption xwaylandXAuthorityOption(QStringLiteral("xwayland-xauthority"), 0334 i18n("Name of the xauthority file "), 0335 "xwayland-xauthority"); 0336 0337 QCommandLineOption replaceOption(QStringLiteral("replace"), 0338 i18n("Exits this instance so it can be restarted by kwin_wayland_wrapper.")); 0339 0340 QCommandLineOption drmOption(QStringLiteral("drm"), i18n("Render through drm node.")); 0341 QCommandLineOption locale1Option(QStringLiteral("locale1"), i18n("Extract locale information from locale1 rather than the user's configuration")); 0342 0343 QCommandLineParser parser; 0344 a.setupCommandLine(&parser); 0345 parser.addOption(xwaylandOption); 0346 parser.addOption(waylandSocketOption); 0347 parser.addOption(waylandSocketFdOption); 0348 parser.addOption(xwaylandListenFdOption); 0349 parser.addOption(xwaylandDisplayOption); 0350 parser.addOption(xwaylandXAuthorityOption); 0351 parser.addOption(replaceOption); 0352 parser.addOption(x11DisplayOption); 0353 parser.addOption(waylandDisplayOption); 0354 parser.addOption(virtualFbOption); 0355 parser.addOption(widthOption); 0356 parser.addOption(heightOption); 0357 parser.addOption(scaleOption); 0358 parser.addOption(outputCountOption); 0359 parser.addOption(drmOption); 0360 parser.addOption(locale1Option); 0361 0362 QCommandLineOption inputMethodOption(QStringLiteral("inputmethod"), 0363 i18n("Input method that KWin starts."), 0364 QStringLiteral("path/to/imserver")); 0365 parser.addOption(inputMethodOption); 0366 0367 #if KWIN_BUILD_SCREENLOCKER 0368 QCommandLineOption screenLockerOption(QStringLiteral("lockscreen"), 0369 i18n("Starts the session in locked mode.")); 0370 parser.addOption(screenLockerOption); 0371 0372 QCommandLineOption noScreenLockerOption(QStringLiteral("no-lockscreen"), 0373 i18n("Starts the session without lock screen support.")); 0374 parser.addOption(noScreenLockerOption); 0375 #endif 0376 0377 QCommandLineOption noGlobalShortcutsOption(QStringLiteral("no-global-shortcuts"), 0378 i18n("Starts the session without global shortcuts support.")); 0379 parser.addOption(noGlobalShortcutsOption); 0380 0381 #if KWIN_BUILD_ACTIVITIES 0382 QCommandLineOption noActivitiesOption(QStringLiteral("no-kactivities"), 0383 i18n("Disable KActivities integration.")); 0384 parser.addOption(noActivitiesOption); 0385 #endif 0386 0387 QCommandLineOption exitWithSessionOption(QStringLiteral("exit-with-session"), 0388 i18n("Exit after the session application, which is started by KWin, closed."), 0389 QStringLiteral("/path/to/session")); 0390 parser.addOption(exitWithSessionOption); 0391 0392 parser.addPositionalArgument(QStringLiteral("applications"), 0393 i18n("Applications to start once Wayland and Xwayland server are started"), 0394 QStringLiteral("[/path/to/application...]")); 0395 0396 parser.process(a); 0397 a.processCommandLine(&parser); 0398 0399 #if KWIN_BUILD_ACTIVITIES 0400 if (parser.isSet(noActivitiesOption)) { 0401 a.setUseKActivities(false); 0402 } 0403 #endif 0404 0405 if (parser.isSet(replaceOption)) { 0406 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"), QStringLiteral("/KWin"), 0407 QStringLiteral("org.kde.KWin"), QStringLiteral("replace")); 0408 QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); 0409 return 0; 0410 } 0411 0412 if (parser.isSet(exitWithSessionOption)) { 0413 a.setSessionArgument(parser.value(exitWithSessionOption)); 0414 } 0415 0416 enum class BackendType { 0417 Kms, 0418 X11, 0419 Wayland, 0420 Virtual, 0421 }; 0422 0423 BackendType backendType; 0424 QString pluginName; 0425 QSize initialWindowSize; 0426 int outputCount = 1; 0427 qreal outputScale = 1; 0428 0429 // Decide what backend to use. 0430 if (parser.isSet(drmOption)) { 0431 backendType = BackendType::Kms; 0432 } else if (parser.isSet(x11DisplayOption)) { 0433 backendType = BackendType::X11; 0434 } else if (parser.isSet(waylandDisplayOption)) { 0435 backendType = BackendType::Wayland; 0436 } else if (parser.isSet(virtualFbOption)) { 0437 backendType = BackendType::Virtual; 0438 } else { 0439 if (qEnvironmentVariableIsSet("WAYLAND_DISPLAY")) { 0440 qInfo("No backend specified, automatically choosing Wayland because WAYLAND_DISPLAY is set"); 0441 backendType = BackendType::Wayland; 0442 } else if (qEnvironmentVariableIsSet("DISPLAY")) { 0443 qInfo("No backend specified, automatically choosing X11 because DISPLAY is set"); 0444 backendType = BackendType::X11; 0445 } else { 0446 qInfo("No backend specified, automatically choosing drm"); 0447 backendType = BackendType::Kms; 0448 } 0449 } 0450 0451 if (parser.isSet(locale1Option)) { 0452 a.setFollowLocale1(true); 0453 } 0454 0455 bool ok = false; 0456 const int width = parser.value(widthOption).toInt(&ok); 0457 if (!ok) { 0458 std::cerr << "FATAL ERROR incorrect value for width" << std::endl; 0459 return 1; 0460 } 0461 const int height = parser.value(heightOption).toInt(&ok); 0462 if (!ok) { 0463 std::cerr << "FATAL ERROR incorrect value for height" << std::endl; 0464 return 1; 0465 } 0466 const qreal scale = parser.value(scaleOption).toDouble(&ok); 0467 if (!ok || scale <= 0) { 0468 std::cerr << "FATAL ERROR incorrect value for scale" << std::endl; 0469 return 1; 0470 } 0471 0472 outputScale = scale; 0473 initialWindowSize = QSize(width, height); 0474 0475 const int count = parser.value(outputCountOption).toInt(&ok); 0476 if (ok) { 0477 outputCount = std::max(1, count); 0478 } 0479 0480 // TODO: create backend without having the server running 0481 KWin::WaylandServer *server = KWin::WaylandServer::create(&a); 0482 0483 KWin::WaylandServer::InitializationFlags flags; 0484 #if KWIN_BUILD_SCREENLOCKER 0485 if (parser.isSet(screenLockerOption)) { 0486 flags = KWin::WaylandServer::InitializationFlag::LockScreen; 0487 } else if (parser.isSet(noScreenLockerOption)) { 0488 flags = KWin::WaylandServer::InitializationFlag::NoLockScreenIntegration; 0489 } 0490 #endif 0491 if (parser.isSet(noGlobalShortcutsOption)) { 0492 flags |= KWin::WaylandServer::InitializationFlag::NoGlobalShortcuts; 0493 } 0494 0495 const QString socketName = parser.value(waylandSocketOption); 0496 if (parser.isSet(waylandSocketFdOption)) { 0497 bool ok; 0498 int fd = parser.value(waylandSocketFdOption).toInt(&ok); 0499 if (ok) { 0500 // make sure we don't leak this FD to children 0501 fcntl(fd, F_SETFD, FD_CLOEXEC); 0502 server->display()->addSocketFileDescriptor(fd, socketName); 0503 } else { 0504 std::cerr << "FATAL ERROR: could not parse socket FD" << std::endl; 0505 return 1; 0506 } 0507 } else { 0508 // socketName empty is fine here, addSocketName will automatically pick one 0509 if (!server->display()->addSocketName(socketName)) { 0510 std::cerr << "FATAL ERROR: could not add wayland socket " << qPrintable(socketName) << std::endl; 0511 return 1; 0512 } 0513 qInfo() << "Accepting client connections on sockets:" << server->display()->socketNames(); 0514 } 0515 0516 if (!server->init(flags)) { 0517 std::cerr << "FATAL ERROR: could not create Wayland server" << std::endl; 0518 return 1; 0519 } 0520 0521 switch (backendType) { 0522 case BackendType::Kms: 0523 a.setSession(KWin::Session::create()); 0524 if (!a.session()) { 0525 std::cerr << "FATAl ERROR: could not acquire a session" << std::endl; 0526 return 1; 0527 } 0528 a.setOutputBackend(std::make_unique<KWin::DrmBackend>(a.session())); 0529 break; 0530 case BackendType::Virtual: { 0531 auto outputBackend = std::make_unique<KWin::VirtualBackend>(); 0532 for (int i = 0; i < outputCount; ++i) { 0533 outputBackend->addOutput(KWin::VirtualBackend::OutputInfo{ 0534 .geometry = QRect(QPoint(), initialWindowSize), 0535 .scale = outputScale, 0536 }); 0537 } 0538 a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); 0539 a.setOutputBackend(std::move(outputBackend)); 0540 break; 0541 } 0542 case BackendType::X11: { 0543 QString display = parser.value(x11DisplayOption); 0544 if (display.isEmpty()) { 0545 display = qgetenv("DISPLAY"); 0546 } 0547 a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); 0548 a.setOutputBackend(std::make_unique<KWin::X11WindowedBackend>(KWin::X11WindowedBackendOptions{ 0549 .display = display, 0550 .outputCount = outputCount, 0551 .outputScale = outputScale, 0552 .outputSize = initialWindowSize, 0553 })); 0554 break; 0555 } 0556 case BackendType::Wayland: { 0557 QString socketName = parser.value(waylandDisplayOption); 0558 if (socketName.isEmpty()) { 0559 socketName = qgetenv("WAYLAND_DISPLAY"); 0560 } 0561 a.setSession(KWin::Session::create(KWin::Session::Type::Noop)); 0562 a.setOutputBackend(std::make_unique<KWin::Wayland::WaylandBackend>(KWin::Wayland::WaylandBackendOptions{ 0563 .socketName = socketName, 0564 .outputCount = outputCount, 0565 .outputScale = outputScale, 0566 .outputSize = initialWindowSize, 0567 })); 0568 break; 0569 } 0570 } 0571 0572 QObject::connect(&a, &KWin::Application::workspaceCreated, server, &KWin::WaylandServer::initWorkspace); 0573 if (!server->socketName().isEmpty()) { 0574 environment.insert(QStringLiteral("WAYLAND_DISPLAY"), server->socketName()); 0575 qputenv("WAYLAND_DISPLAY", server->socketName().toUtf8()); 0576 } 0577 a.setProcessStartupEnvironment(environment); 0578 0579 if (parser.isSet(xwaylandOption)) { 0580 a.setStartXwayland(true); 0581 0582 if (parser.isSet(xwaylandListenFdOption)) { 0583 const QStringList fdStrings = parser.values(xwaylandListenFdOption); 0584 for (const QString &fdString : fdStrings) { 0585 bool ok; 0586 int fd = fdString.toInt(&ok); 0587 if (ok) { 0588 // make sure we don't leak this FD to children 0589 fcntl(fd, F_SETFD, FD_CLOEXEC); 0590 a.addXwaylandSocketFileDescriptor(fd); 0591 } 0592 } 0593 if (parser.isSet(xwaylandDisplayOption)) { 0594 a.setXwaylandDisplay(parser.value(xwaylandDisplayOption)); 0595 } else { 0596 std::cerr << "Using xwayland-fd without xwayland-display is undefined" << std::endl; 0597 return 1; 0598 } 0599 if (parser.isSet(xwaylandXAuthorityOption)) { 0600 a.setXwaylandXauthority(parser.value(xwaylandXAuthorityOption)); 0601 } 0602 } 0603 } 0604 0605 a.setApplicationsToStart(parser.positionalArguments()); 0606 a.setInputMethodServerToStart(parser.value(inputMethodOption)); 0607 a.start(); 0608 0609 return a.exec(); 0610 } 0611 0612 #include "moc_main_wayland.cpp"