257int main(
int argc,
char *argv[])
263 signal(SIGPIPE, SIG_IGN);
268 if (KWin::bumpNofileLimit()) {
269 pthread_atfork(
nullptr,
nullptr, KWin::restoreNofileLimit);
272 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
275 setenv(
"QT_QPA_PLATFORM",
"wayland-org.kde.kwin.qpa",
true);
280 qunsetenv(
"QT_QPA_PLATFORM");
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);
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));
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));
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));
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"));
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"));
329 QCommandLineOption xwaylandDisplayOption(QStringLiteral(
"xwayland-display"),
330 i18n(
"Name of the xwayland display that has been pre-set up"),
333 QCommandLineOption xwaylandXAuthorityOption(QStringLiteral(
"xwayland-xauthority"),
334 i18n(
"Name of the xauthority file "),
335 "xwayland-xauthority");
337 QCommandLineOption replaceOption(QStringLiteral(
"replace"),
338 i18n(
"Exits this instance so it can be restarted by kwin_wayland_wrapper."));
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"));
343 QCommandLineParser 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);
362 QCommandLineOption inputMethodOption(QStringLiteral(
"inputmethod"),
363 i18n(
"Input method that KWin starts."),
364 QStringLiteral(
"path/to/imserver"));
365 parser.addOption(inputMethodOption);
367#if KWIN_BUILD_SCREENLOCKER
368 QCommandLineOption screenLockerOption(QStringLiteral(
"lockscreen"),
369 i18n(
"Starts the session in locked mode."));
370 parser.addOption(screenLockerOption);
372 QCommandLineOption noScreenLockerOption(QStringLiteral(
"no-lockscreen"),
373 i18n(
"Starts the session without lock screen support."));
374 parser.addOption(noScreenLockerOption);
377 QCommandLineOption noGlobalShortcutsOption(QStringLiteral(
"no-global-shortcuts"),
378 i18n(
"Starts the session without global shortcuts support."));
379 parser.addOption(noGlobalShortcutsOption);
381#if KWIN_BUILD_ACTIVITIES
382 QCommandLineOption noActivitiesOption(QStringLiteral(
"no-kactivities"),
383 i18n(
"Disable KActivities integration."));
384 parser.addOption(noActivitiesOption);
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);
392 parser.addPositionalArgument(QStringLiteral(
"applications"),
393 i18n(
"Applications to start once Wayland and Xwayland server are started"),
394 QStringLiteral(
"[/path/to/application...]"));
399#if KWIN_BUILD_ACTIVITIES
400 if (parser.isSet(noActivitiesOption)) {
401 a.setUseKActivities(
false);
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);
412 if (parser.isSet(exitWithSessionOption)) {
416 enum class BackendType {
423 BackendType backendType;
425 QSize initialWindowSize;
427 qreal outputScale = 1;
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;
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;
446 qInfo(
"No backend specified, automatically choosing drm");
447 backendType = BackendType::Kms;
451 if (parser.isSet(locale1Option)) {
456 const int width = parser.value(widthOption).toInt(&ok);
458 std::cerr <<
"FATAL ERROR incorrect value for width" << std::endl;
461 const int height = parser.value(heightOption).toInt(&ok);
463 std::cerr <<
"FATAL ERROR incorrect value for height" << std::endl;
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;
473 initialWindowSize = QSize(width, height);
475 const int count = parser.value(outputCountOption).toInt(&ok);
477 outputCount = std::max(1, count);
483 KWin::WaylandServer::InitializationFlags flags;
484#if KWIN_BUILD_SCREENLOCKER
485 if (parser.isSet(screenLockerOption)) {
487 }
else if (parser.isSet(noScreenLockerOption)) {
491 if (parser.isSet(noGlobalShortcutsOption)) {
495 const QString socketName = parser.value(waylandSocketOption);
496 if (parser.isSet(waylandSocketFdOption)) {
498 int fd = parser.value(waylandSocketFdOption).toInt(&ok);
501 fcntl(fd, F_SETFD, FD_CLOEXEC);
504 std::cerr <<
"FATAL ERROR: could not parse socket FD" << std::endl;
510 std::cerr <<
"FATAL ERROR: could not add wayland socket " << qPrintable(socketName) << std::endl;
513 qInfo() <<
"Accepting client connections on sockets:" << server->
display()->
socketNames();
516 if (!server->
init(flags)) {
517 std::cerr <<
"FATAL ERROR: could not create Wayland server" << std::endl;
521 switch (backendType) {
522 case BackendType::Kms:
525 std::cerr <<
"FATAl ERROR: could not acquire a session" << std::endl;
530 case BackendType::Virtual: {
531 auto outputBackend = std::make_unique<KWin::VirtualBackend>();
532 for (
int i = 0; i < outputCount; ++i) {
534 .
geometry = QRect(QPoint(), initialWindowSize),
535 .scale = outputScale,
542 case BackendType::X11: {
543 QString display = parser.value(x11DisplayOption);
544 if (display.isEmpty()) {
545 display = qgetenv(
"DISPLAY");
550 .outputCount = outputCount,
551 .outputScale = outputScale,
552 .outputSize = initialWindowSize,
556 case BackendType::Wayland: {
557 QString socketName = parser.value(waylandDisplayOption);
558 if (socketName.isEmpty()) {
559 socketName = qgetenv(
"WAYLAND_DISPLAY");
564 .outputCount = outputCount,
565 .outputScale = outputScale,
566 .outputSize = initialWindowSize,
574 environment.insert(QStringLiteral(
"WAYLAND_DISPLAY"), server->
socketName());
575 qputenv(
"WAYLAND_DISPLAY", server->
socketName().toUtf8());
579 if (parser.isSet(xwaylandOption)) {
582 if (parser.isSet(xwaylandListenFdOption)) {
583 const QStringList fdStrings = parser.values(xwaylandListenFdOption);
584 for (
const QString &fdString : fdStrings) {
586 int fd = fdString.toInt(&ok);
589 fcntl(fd, F_SETFD, FD_CLOEXEC);
593 if (parser.isSet(xwaylandDisplayOption)) {
596 std::cerr <<
"Using xwayland-fd without xwayland-display is undefined" << std::endl;
599 if (parser.isSet(xwaylandXAuthorityOption)) {