WLC_API void wlc_run(void) { if (!wlc.display) return; wlc.compositor.state.ready = false; bool emit_ready = true; const char *xwayland = getenv("WLC_XWAYLAND"); if (!xwayland || !chck_cstreq(xwayland, "0")) emit_ready = !wlc_xwayland_init(); // Emit ready immediately when no Xwayland if (emit_ready) { WLC_INTERFACE_EMIT(compositor.ready); wlc.compositor.state.ready = true; } wlc_set_active(true); if (wlc_compositor_is_good(&wlc.compositor)) wl_display_run(wlc.display); wlc_cleanup(); }
WLC_API bool wlc_init(const struct wlc_interface *interface, int argc, char *argv[]) { assert(interface); if (!interface) die("no wlc_interface was given"); if (wlc.display) return true; memset(&wlc, 0, sizeof(wlc)); wl_log_set_handler_server(wl_cb_log); for (int i = 1; i < argc; ++i) { if (chck_cstreq(argv[i], "--log")) { if (i + 1 >= argc) die("--log takes an argument (filename)"); wlc_set_log_file(fopen(argv[++i], "a")); } } unsetenv("TERM"); const char *x11display = getenv("DISPLAY"); bool privilidged = false; const bool has_logind = wlc_logind_available(); if (getuid() != geteuid() || getgid() != getegid()) { wlc_log(WLC_LOG_INFO, "Doing work on SUID/SGID side and dropping permissions"); privilidged = true; } else if (getuid() == 0) { die("Do not run wlc compositor as root"); } else if (!x11display && !has_logind && access("/dev/input/event0", R_OK | W_OK) != 0) { die("Not running from X11 and no access to /dev/input/event0 or logind available"); } #ifndef NDEBUG { struct sigaction action = { .sa_handler = backtrace }; sigaction(SIGABRT, &action, NULL); sigaction(SIGSEGV, &action, NULL); // XXX: Some weird sigfpes seems to come when running // wlc compositor inside wlc compositor (X11 backend). // Seems to be caused by resolution changes and mouse clicks. // Gather more information about this later and see what's going on. if (!getenv("WAYLAND_DISPLAY")) fpesetup(&action); } #endif int vt = 0; #ifdef HAS_LOGIND // Init logind if we are not running as SUID. // We need event loop for logind to work, and thus we won't allow it on SUID process. if (!privilidged && !x11display && has_logind) { if (!(wlc.display = wl_display_create())) die("Failed to create wayland display"); if (!(vt = wlc_logind_init("seat0"))) die("Failed to init logind"); } #else (void)privilidged; #endif if (!x11display) wlc_tty_init(vt); // -- we open tty before dropping permissions // so the fd process can also handle cleanup in case of crash // if logind initialized correctly, fd process does nothing but handle crash. { struct wl_display *display = wlc.display; wlc.display = NULL; wlc_fd_init(argc, argv, (vt != 0)); wlc.display = display; } // -- permissions are now dropped wl_signal_init(&wlc.signals.terminate); wl_signal_init(&wlc.signals.activate); wl_signal_init(&wlc.signals.compositor); wl_signal_init(&wlc.signals.focus); wl_signal_init(&wlc.signals.surface); wl_signal_init(&wlc.signals.input); wl_signal_init(&wlc.signals.output); wl_signal_init(&wlc.signals.render); wl_signal_init(&wlc.signals.xwayland); wl_signal_add(&wlc.signals.compositor, &compositor_listener); if (!wlc_resources_init()) die("Failed to init resource manager"); if (!wlc.display && !(wlc.display = wl_display_create())) die("Failed to create wayland display"); const char *socket_name; if (!(socket_name = wl_display_add_socket_auto(wlc.display))) die("Failed to add socket to wayland display"); if (socket_name) // shut up static analyze setenv("WAYLAND_DISPLAY", socket_name, true); if (wl_display_init_shm(wlc.display) != 0) die("Failed to init shm"); if (!wlc_udev_init()) die("Failed to init udev"); const char *libinput = getenv("WLC_LIBINPUT"); if (!x11display || (libinput && !chck_cstreq(libinput, "0"))) { if (!wlc_input_init()) die("Failed to init input"); } memcpy(&wlc.interface, interface, sizeof(wlc.interface)); if (!wlc_compositor(&wlc.compositor)) die("Failed to init compositor"); const char *xwayland = getenv("WLC_XWAYLAND"); if (!xwayland || !chck_cstreq(xwayland, "0")) { if (!(wlc_xwayland_init())) die("Failed to init xwayland"); } else { wlc.set_ready_on_run = true; } wlc_set_active(true); return wlc_compositor_is_good(&wlc.compositor); }