static void weston_xserver_cleanup(struct weston_process *process, int status) { struct weston_xserver *mxs = container_of(process, struct weston_xserver, process); mxs->process.pid = 0; mxs->client = NULL; mxs->resource = NULL; mxs->abstract_source = wl_event_loop_add_fd(mxs->loop, mxs->abstract_fd, WL_EVENT_READABLE, weston_xserver_handle_event, mxs); mxs->unix_source = wl_event_loop_add_fd(mxs->loop, mxs->unix_fd, WL_EVENT_READABLE, weston_xserver_handle_event, mxs); if (mxs->wm) { weston_log("xserver exited, code %d\n", status); weston_wm_destroy(mxs->wm); mxs->wm = NULL; } else { /* If the X server crashes before it binds to the * xserver interface, shut down and don't try * again. */ weston_log("xserver crashing too fast: %d\n", status); weston_xserver_shutdown(mxs); } }
static void weston_wm_send_incr_chunk(struct weston_wm *wm) { int length; weston_log("property deleted\n"); wm->selection_property_set = 0; if (wm->flush_property_on_delete) { weston_log("setting new property, %zu bytes\n", wm->source_data.size); wm->flush_property_on_delete = 0; length = weston_wm_flush_source_data(wm); if (wm->data_source_fd >= 0) { wm->property_source = wl_event_loop_add_fd(wm->server->loop, wm->data_source_fd, WL_EVENT_READABLE, weston_wm_read_data_source, wm); } else if (length > 0) { /* Transfer is all done, but queue a flush for * the delete of the last chunk so we can set * the 0 sized propert to signal the end of * the transfer. */ wm->flush_property_on_delete = 1; wl_array_release(&wm->source_data); } else { wm->selection_request.requestor = XCB_NONE; } } }
static void weston_wm_send_data(struct weston_wm *wm, xcb_atom_t target, const char *mime_type) { struct weston_data_source *source; struct weston_seat *seat = weston_wm_pick_seat(wm); int p[2]; if (pipe2(p, O_CLOEXEC | O_NONBLOCK) == -1) { weston_log("pipe2 failed: %m\n"); weston_wm_send_selection_notify(wm, XCB_ATOM_NONE); return; } wl_array_init(&wm->source_data); wm->selection_target = target; wm->data_source_fd = p[0]; wm->property_source = wl_event_loop_add_fd(wm->server->loop, wm->data_source_fd, WL_EVENT_READABLE, weston_wm_read_data_source, wm); source = seat->selection_data_source; source->send(source, mime_type, p[1]); close(p[1]); }
static void weston_wm_get_incr_chunk(struct weston_wm *wm) { xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *reply; cookie = xcb_get_property(wm->conn, 0, /* delete */ wm->selection_window, wm->atom.wl_selection, XCB_GET_PROPERTY_TYPE_ANY, 0, /* offset */ 0x1fffffff /* length */); reply = xcb_get_property_reply(wm->conn, cookie, NULL); dump_property(wm, wm->atom.wl_selection, reply); if (xcb_get_property_value_length(reply) > 0) { wm->property_start = 0; wm->property_source = wl_event_loop_add_fd(wm->server->loop, wm->data_source_fd, WL_EVENT_WRITABLE, weston_wm_write_property, wm); wm->property_reply = reply; } else { weston_log("transfer complete\n"); close(wm->data_source_fd); free(reply); } }
static void weston_wm_get_selection_data(struct weston_wm *wm) { xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *reply; cookie = xcb_get_property(wm->conn, 1, /* delete */ wm->selection_window, wm->atom.wl_selection, XCB_GET_PROPERTY_TYPE_ANY, 0, /* offset */ 0x1fffffff /* length */); reply = xcb_get_property_reply(wm->conn, cookie, NULL); if (reply->type == wm->atom.incr) { dump_property(wm, wm->atom.wl_selection, reply); wm->incr = 1; free(reply); } else { dump_property(wm, wm->atom.wl_selection, reply); wm->incr = 0; wm->property_start = 0; wm->property_source = wl_event_loop_add_fd(wm->server->loop, wm->data_source_fd, WL_EVENT_WRITABLE, weston_wm_write_property, wm); wm->property_reply = reply; } }
static struct clipboard_source * clipboard_source_create(struct clipboard *clipboard, const char *mime_type, uint32_t serial, int fd) { struct wl_display *display = clipboard->seat->compositor->wl_display; struct wl_event_loop *loop = wl_display_get_event_loop(display); struct clipboard_source *source; char **s; source = malloc(sizeof *source); wl_array_init(&source->contents); wl_array_init(&source->base.mime_types); source->base.accept = clipboard_source_accept; source->base.send = clipboard_source_send; source->base.cancel = clipboard_source_cancel; source->base.resource.data = &source->base; wl_signal_init(&source->base.resource.destroy_signal); source->refcount = 1; source->clipboard = clipboard; source->serial = serial; s = wl_array_add(&source->base.mime_types, sizeof *s); *s = strdup(mime_type); source->event_source = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, clipboard_source_data, source); return source; }
//Callbacks implementation unsigned int DBusHandler::Callbacks::addWatch(DBusWatch* watch, void* data) { if(!data) return 0; auto& loop = static_cast<DBusHandler*>(data)->compositor().wlEventLoop(); unsigned int mask = 0; if (dbus_watch_get_enabled(watch)) { unsigned int flags = dbus_watch_get_flags(watch); if (flags & DBUS_WATCH_READABLE) mask |= WL_EVENT_READABLE; if (flags & DBUS_WATCH_WRITABLE) mask |= WL_EVENT_WRITABLE; } int fd = dbus_watch_get_unix_fd(watch); wl_event_source* source = wl_event_loop_add_fd(&loop, fd, mask, dispatchWatch, watch); if (!source) { ny::sendWarning("failed to add dbus watch wl_event_loop_fd"); return 0; } dbus_watch_set_data(watch, source, nullptr); return 1; }
static int weston_dbus_bind(struct wl_event_loop *loop, DBusConnection *c, struct wl_event_source **ctx_out) { bool b; int r, fd; /* Idle events cannot reschedule themselves, therefore we use a dummy * event-fd and mark it for post-dispatch. Hence, the dbus * dispatcher is called after every dispatch-round. * This is required as dbus doesn't allow dispatching events from * within its own event sources. */ fd = eventfd(0, EFD_CLOEXEC); if (fd < 0) return -errno; *ctx_out = wl_event_loop_add_fd(loop, fd, 0, weston_dbus_dispatch, c); close(fd); if (!*ctx_out) return -ENOMEM; wl_event_source_check(*ctx_out); b = dbus_connection_set_watch_functions(c, weston_dbus_add_watch, weston_dbus_remove_watch, weston_dbus_toggle_watch, loop, NULL); if (!b) { r = -ENOMEM; goto error; } b = dbus_connection_set_timeout_functions(c, weston_dbus_add_timeout, weston_dbus_remove_timeout, weston_dbus_toggle_timeout, loop, NULL); if (!b) { r = -ENOMEM; goto error; } dbus_connection_ref(c); return 0; error: dbus_connection_set_timeout_functions(c, NULL, NULL, NULL, NULL, NULL); dbus_connection_set_watch_functions(c, NULL, NULL, NULL, NULL, NULL); wl_event_source_remove(*ctx_out); *ctx_out = NULL; return r; }
struct evdev_device * evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) { struct evdev_device *device; struct weston_compositor *ec; char devname[256] = "unknown"; device = zalloc(sizeof *device); if (device == NULL) return NULL; ec = seat->compositor; device->output = container_of(ec->output_list.next, struct weston_output, link); device->seat = seat; device->is_mt = 0; device->mtdev = NULL; device->devnode = strdup(path); device->mt.slot = -1; device->rel.dx = 0; device->rel.dy = 0; device->dispatch = NULL; device->fd = device_fd; ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); devname[sizeof(devname) - 1] = '\0'; device->devname = strdup(devname); if (!evdev_handle_device(device)) { evdev_device_destroy(device); return EVDEV_UNHANDLED_DEVICE; } if (evdev_configure_device(device) == -1) goto err; /* If the dispatch was not set up use the fallback. */ if (device->dispatch == NULL) device->dispatch = fallback_dispatch_create(); if (device->dispatch == NULL) goto err; device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, evdev_device_data, device); if (device->source == NULL) goto err; return device; err: evdev_device_destroy(device); return NULL; }
static bool input_set_event_loop(struct wl_event_loop *loop) { if (input.event_source) { wl_event_source_remove(input.event_source); input.event_source = NULL; } if (input.handle && loop && !(input.event_source = wl_event_loop_add_fd(loop, libinput_get_fd(input.handle), WL_EVENT_READABLE, input_event, &input))) return false; return true; }
struct weston_launcher * weston_launcher_connect(struct weston_compositor *compositor, int tty, const char *seat_id) { struct weston_launcher *launcher; struct wl_event_loop *loop; int r; launcher = malloc(sizeof *launcher); if (launcher == NULL) return NULL; launcher->logind = NULL; launcher->compositor = compositor; launcher->drm_fd = -1; launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK"); if (launcher->fd != -1) { launcher->tty = weston_environment_get_fd("WESTON_TTY_FD"); /* We don't get a chance to read out the original kb * mode for the tty, so just hard code K_UNICODE here * in case we have to clean if weston-launch dies. */ launcher->kb_mode = K_UNICODE; loop = wl_display_get_event_loop(compositor->wl_display); launcher->source = wl_event_loop_add_fd(loop, launcher->fd, WL_EVENT_READABLE, weston_launcher_data, launcher); if (launcher->source == NULL) { free(launcher); return NULL; } } else { r = weston_logind_connect(&launcher->logind, compositor, seat_id, tty); if (r < 0) { launcher->logind = NULL; if (geteuid() == 0) { if (setup_tty(launcher, tty) == -1) { free(launcher); return NULL; } } else { free(launcher); return NULL; } } } return launcher; }
static void weston_wm_write_property(struct weston_wm *wm, xcb_get_property_reply_t *reply) { wm->property_start = 0; wm->property_reply = reply; writable_callback(wm->data_source_fd, WL_EVENT_WRITABLE, wm); if (wm->property_reply) wm->property_source = wl_event_loop_add_fd(wm->server->loop, wm->data_source_fd, WL_EVENT_WRITABLE, writable_callback, wm); }
static void clipboard_client_create(struct clipboard_source *source, int fd) { struct weston_seat *seat = source->clipboard->seat; struct clipboard_client *client; struct wl_event_loop *loop = wl_display_get_event_loop(seat->compositor->wl_display); client = malloc(sizeof *client); client->offset = 0; client->source = source; source->refcount++; client->event_source = wl_event_loop_add_fd(loop, fd, WL_EVENT_WRITABLE, clipboard_client_data, client); }
static dbus_bool_t weston_dbus_add_watch(DBusWatch *watch, void *data) { struct wl_event_loop *loop = data; struct wl_event_source *s; int fd; uint32_t mask = 0, flags; if (dbus_watch_get_enabled(watch)) { flags = dbus_watch_get_flags(watch); if (flags & DBUS_WATCH_READABLE) mask |= WL_EVENT_READABLE; if (flags & DBUS_WATCH_WRITABLE) mask |= WL_EVENT_WRITABLE; } fd = dbus_watch_get_unix_fd(watch); s = wl_event_loop_add_fd(loop, fd, mask, weston_dbus_dispatch_watch, watch); if (!s) return FALSE; dbus_watch_set_data(watch, s, NULL); return TRUE; }
//DbusHandler DBusHandler::DBusHandler(Compositor& comp) : compositor_(&comp) { DBusError err; dbus_error_init(&err); dbus_connection_set_change_sigpipe(false); //todo: error checking everywhere if(!(dbusConnection_ = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err))) { std::string errStr; checkError(err, errStr); throw std::runtime_error("DBus::DBus: cant connect to dbus. " + errStr); return; } dbus_connection_set_exit_on_disconnect(dbusConnection_, false); //use dummy event fd int fd; if((fd = eventfd(0, EFD_CLOEXEC)) < 0) { throw std::runtime_error("DBus::DBus: cant create eventfd"); return; } //event source dbusEventSource_ = wl_event_loop_add_fd(&comp.wlEventLoop(), fd, 0, Callbacks::dispatchDBus, this); close(fd); wl_event_source_check(dbusEventSource_); //watch if(!dbus_connection_set_watch_functions(dbusConnection_, Callbacks::addWatch, Callbacks::removeWatch, Callbacks::toggleWatch, this, nullptr)) { throw std::runtime_error("dbus_connection_set_watch_functions failed"); return; } //timeout if(!dbus_connection_set_timeout_functions(dbusConnection_, Callbacks::addTimeout, Callbacks::removeTimeout, Callbacks::toggleTimeout, this, nullptr)) { throw std::runtime_error("dbus_connection_set_timeout_functions failed"); return; } //filter if(!dbus_connection_add_filter(dbusConnection_, Callbacks::dbusFilter, this, nullptr)) { throw std::runtime_error("dbus add filter failed"); return; } //disconnected callback signalCallbacks_.emplace_back(MsgCallback{DBUS_INTERFACE_LOCAL, "Diconnected", nytl::memberCallback(&DBusHandler::disconnected, this)}); ny::sendLog("dbus handler succesfully set up"); }
X11Backend::X11Backend(Compositor& comp, Seat& seat) : Backend(), compositor_(&comp), seat_(&seat) { //setup x connection xDisplay_ = XOpenDisplay(nullptr); if(!xDisplay_) { throw std::runtime_error("cant connect to x11 server"); return; } xConnection_ = XGetXCBConnection(xDisplay_); if(!xConnection_) { throw std::runtime_error("cant get xcb connection"); return; } XSetEventQueueOwner(xDisplay_, XCBOwnsEventQueue); if(xcb_connection_has_error(xConnection_)) { throw std::runtime_error("xcb connection error"); return; } xScreen_ = xcb_setup_roots_iterator(xcb_get_setup(xConnection_)).data; //atoms struct atomProp { xcb_atom_t& ret; std::string str; }; atomProp vec[] = { {atoms::protocols, "WM_PROTOCOLS"}, {atoms::deleteWindow, "WM_DELETE_WINDOW"} }; xcb_intern_atom_reply_t* reply; for(auto& p : vec) { auto atom = xcb_intern_atom(xConnection_, 0, p.str.size(), p.str.c_str()); reply = xcb_intern_atom_reply(xConnection_, atom, nullptr); p.ret = (reply ? reply->atom : 0); } //xkb xkbSetup(); //event source inputEventSource_ = wl_event_loop_add_fd(&comp.wlEventLoop(), xcb_get_file_descriptor(xConnection_), WL_EVENT_READABLE, eventCallback, this); if(!inputEventSource_) throw std::runtime_error("could not create wayland event source"); //what does this? really needed? wl_event_source_check(inputEventSource_); //eglContext eglContext_ = std::make_unique<WaylandEglContext>(xDisplay_); if(!eglContext_) throw std::runtime_error("x11Backend::x11Backend: failed to create EglContext"); eglContext_->bindWlDisplay(compositor_->wlDisplay()); xcb_flush(xConnection_); }
static struct weston_compositor * wayland_compositor_create(struct wl_display *display, int width, int height, const char *display_name, int *argc, char *argv[], struct weston_config *config) { struct wayland_compositor *c; struct wl_event_loop *loop; int fd; c = malloc(sizeof *c); if (c == NULL) return NULL; memset(c, 0, sizeof *c); if (weston_compositor_init(&c->base, display, argc, argv, config) < 0) goto err_free; c->parent.wl_display = wl_display_connect(display_name); if (c->parent.wl_display == NULL) { weston_log("failed to create display: %m\n"); goto err_compositor; } wl_list_init(&c->input_list); c->parent.registry = wl_display_get_registry(c->parent.wl_display); wl_registry_add_listener(c->parent.registry, ®istry_listener, c); wl_display_dispatch(c->parent.wl_display); c->base.wl_display = display; if (gl_renderer_create(&c->base, c->parent.wl_display, gl_renderer_alpha_attribs, NULL) < 0) goto err_display; c->base.destroy = wayland_destroy; c->base.restore = wayland_restore; c->border.top = 30; c->border.bottom = 24; c->border.left = 25; c->border.right = 26; /* requires border fields */ if (wayland_compositor_create_output(c, width, height) < 0) goto err_gl; /* requires gl_renderer_output_state_create called * by wayland_compositor_create_output */ create_border(c); loop = wl_display_get_event_loop(c->base.wl_display); fd = wl_display_get_fd(c->parent.wl_display); c->parent.wl_source = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, wayland_compositor_handle_event, c); if (c->parent.wl_source == NULL) goto err_gl; wl_event_source_check(c->parent.wl_source); return &c->base; err_gl: c->base.renderer->destroy(&c->base); err_display: wl_display_disconnect(c->parent.wl_display); err_compositor: weston_compositor_shutdown(&c->base); err_free: free(c); return NULL; }
struct evdev_device * evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) { struct evdev_device *device; struct weston_compositor *ec; char devname[256] = "unknown"; device = malloc(sizeof *device); if (device == NULL) return NULL; memset(device, 0, sizeof *device); ec = seat->compositor; device->output = container_of(ec->output_list.next, struct weston_output, link); device->seat = seat; device->is_mt = 0; device->mtdev = NULL; device->devnode = strdup(path); device->mt.slot = -1; device->rel.dx = 0; device->rel.dy = 0; device->dispatch = NULL; device->fd = device_fd; ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); device->devname = strdup(devname); if (!evdev_handle_device(device)) { free(device->devnode); free(device->devname); free(device); return EVDEV_UNHANDLED_DEVICE; } if (evdev_configure_device(device) == -1) goto err1; /* If the dispatch was not set up use the fallback. */ if (device->dispatch == NULL) device->dispatch = fallback_dispatch_create(); if (device->dispatch == NULL) goto err1; if (device->is_mt) { device->mtdev = mtdev_new_open(device->fd); if (!device->mtdev) weston_log("mtdev failed to open for %s\n", path); } device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, evdev_device_data, device); if (device->source == NULL) goto err2; return device; err2: device->dispatch->interface->destroy(device->dispatch); err1: free(device->devname); free(device->devnode); free(device); return NULL; }
struct tty * tty_create(struct weston_compositor *compositor, tty_vt_func_t vt_func, int tty_nr) { struct termios raw_attributes; struct vt_mode mode = { 0 }; int ret; struct tty *tty; struct wl_event_loop *loop; struct stat buf; char filename[16]; struct vt_stat vts; tty = malloc(sizeof *tty); if (tty == NULL) return NULL; memset(tty, 0, sizeof *tty); tty->compositor = compositor; tty->vt_func = vt_func; tty->fd = weston_environment_get_fd("WESTON_TTY_FD"); if (tty->fd < 0) tty->fd = STDIN_FILENO; if (tty_nr > 0) { snprintf(filename, sizeof filename, "/dev/tty%d", tty_nr); weston_log("compositor: using %s\n", filename); tty->fd = open(filename, O_RDWR | O_NOCTTY | O_CLOEXEC); tty->vt = tty_nr; } else if (fstat(tty->fd, &buf) == 0 && major(buf.st_rdev) == TTY_MAJOR && minor(buf.st_rdev) > 0) { if (tty->fd == STDIN_FILENO) tty->fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 0); tty->vt = minor(buf.st_rdev); } else { /* Fall back to try opening a new VT. This typically * requires root. */ tty->fd = try_open_vt(tty); } if (tty->fd <= 0) { weston_log("failed to open tty: %m\n"); free(tty); return NULL; } if (ioctl(tty->fd, VT_GETSTATE, &vts) == 0) tty->starting_vt = vts.v_active; else tty->starting_vt = tty->vt; if (tty->starting_vt != tty->vt) { if (ioctl(tty->fd, VT_ACTIVATE, tty->vt) < 0 || ioctl(tty->fd, VT_WAITACTIVE, tty->vt) < 0) { weston_log("failed to swtich to new vt\n"); goto err; } } if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0) { weston_log("could not get terminal attributes: %m\n"); goto err; } /* Ignore control characters and disable echo */ raw_attributes = tty->terminal_attributes; cfmakeraw(&raw_attributes); /* Fix up line endings to be normal (cfmakeraw hoses them) */ raw_attributes.c_oflag |= OPOST | OCRNL; if (tcsetattr(tty->fd, TCSANOW, &raw_attributes) < 0) weston_log("could not put terminal into raw mode: %m\n"); loop = wl_display_get_event_loop(compositor->wl_display); ioctl(tty->fd, KDGKBMODE, &tty->kb_mode); ret = ioctl(tty->fd, KDSKBMODE, K_OFF); if (ret) { ret = ioctl(tty->fd, KDSKBMODE, K_RAW); if (ret) { weston_log("failed to set keyboard mode on tty: %m\n"); goto err_attr; } tty->input_source = wl_event_loop_add_fd(loop, tty->fd, WL_EVENT_READABLE, on_tty_input, tty); if (!tty->input_source) goto err_kdkbmode; } ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); if (ret) { weston_log("failed to set KD_GRAPHICS mode on tty: %m\n"); goto err_kdkbmode; } tty->has_vt = 1; mode.mode = VT_PROCESS; mode.relsig = SIGUSR1; mode.acqsig = SIGUSR1; if (ioctl(tty->fd, VT_SETMODE, &mode) < 0) { weston_log("failed to take control of vt handling\n"); goto err_kdmode; } tty->vt_source = wl_event_loop_add_signal(loop, SIGUSR1, vt_handler, tty); if (!tty->vt_source) goto err_vtmode; return tty; err_vtmode: ioctl(tty->fd, VT_SETMODE, &mode); err_kdmode: ioctl(tty->fd, KDSETMODE, KD_TEXT); err_kdkbmode: if (tty->input_source) wl_event_source_remove(tty->input_source); ioctl(tty->fd, KDSKBMODE, tty->kb_mode); err_attr: tcsetattr(tty->fd, TCSANOW, &tty->terminal_attributes); err: close(tty->fd); free(tty); return NULL; }
WL_EXPORT int weston_xserver_init(struct weston_compositor *compositor) { struct wl_display *display = compositor->wl_display; struct weston_xserver *mxs; char lockfile[256], display_name[8]; mxs = malloc(sizeof *mxs); memset(mxs, 0, sizeof *mxs); mxs->process.cleanup = weston_xserver_cleanup; mxs->wl_display = display; mxs->compositor = compositor; mxs->display = 0; retry: if (create_lockfile(mxs->display, lockfile, sizeof lockfile) < 0) { if (errno == EAGAIN) { goto retry; } else if (errno == EEXIST) { mxs->display++; goto retry; } else { free(mxs); return -1; } } mxs->abstract_fd = bind_to_abstract_socket(mxs->display); if (mxs->abstract_fd < 0 && errno == EADDRINUSE) { mxs->display++; unlink(lockfile); goto retry; } mxs->unix_fd = bind_to_unix_socket(mxs->display); if (mxs->unix_fd < 0) { unlink(lockfile); close(mxs->abstract_fd); free(mxs); return -1; } snprintf(display_name, sizeof display_name, ":%d", mxs->display); weston_log("xserver listening on display %s\n", display_name); setenv("DISPLAY", display_name, 1); mxs->loop = wl_display_get_event_loop(display); mxs->abstract_source = wl_event_loop_add_fd(mxs->loop, mxs->abstract_fd, WL_EVENT_READABLE, weston_xserver_handle_event, mxs); mxs->unix_source = wl_event_loop_add_fd(mxs->loop, mxs->unix_fd, WL_EVENT_READABLE, weston_xserver_handle_event, mxs); wl_display_add_global(display, &xserver_interface, mxs, bind_xserver); mxs->destroy_listener.notify = weston_xserver_destroy; wl_signal_add(&compositor->destroy_signal, &mxs->destroy_listener); return 0; }
bool swc_drm_initialize() { struct stat master, render; if (!find_primary_drm_device(drm.path, sizeof drm.path)) { ERROR("Could not find DRM device\n"); goto error0; } drm.taken_ids = 0; swc.drm->fd = launch_open_device(drm.path, O_RDWR | O_CLOEXEC); if (swc.drm->fd == -1) { ERROR("Could not open DRM device at %s\n", drm.path); goto error0; } if (fstat(swc.drm->fd, &master) != 0) { ERROR("Could not fstat DRM FD: %s\n", strerror(errno)); goto error1; } if (snprintf(drm.path, sizeof drm.path, "/dev/dri/renderD%d", minor(master.st_rdev) + 0x80) >= sizeof drm.path) { ERROR("Render node path is too long"); goto error1; } if (stat(drm.path, &render) != 0) { ERROR("Could not stat render node for primary DRM device: %s\n", strerror(errno)); goto error1; } if (master.st_mode != render.st_mode || minor(master.st_rdev) + 0x80 != minor(render.st_rdev)) { ERROR("Render node does not have expected mode or minor number\n"); goto error1; } if (!(swc.drm->context = wld_drm_create_context(swc.drm->fd))) { ERROR("Could not create WLD DRM context\n"); goto error1; } if (!(swc.drm->renderer = wld_create_renderer(swc.drm->context))) { ERROR("Could not create WLD DRM renderer\n"); goto error2; } drm.event_source = wl_event_loop_add_fd (swc.event_loop, swc.drm->fd, WL_EVENT_READABLE, &handle_data, NULL); if (!drm.event_source) { ERROR("Could not create DRM event source\n"); goto error3; } if (!wld_drm_is_dumb(swc.drm->context)) { drm.global = wl_global_create(swc.display, &wl_drm_interface, 2, NULL, &bind_drm); if (!drm.global) { ERROR("Could not create wl_drm global\n"); goto error4; } } return true; error4: wl_event_source_remove(drm.event_source); error3: wld_destroy_renderer(swc.drm->renderer); error2: wld_destroy_context(swc.drm->context); error1: close(swc.drm->fd); error0: return false; }
WL_EXPORT int module_init(struct weston_compositor *compositor, int *argc, char *argv[]) { struct wl_display *display = compositor->wl_display; struct weston_xserver *wxs; char lockfile[256], display_name[8]; wxs = zalloc(sizeof *wxs); if (wxs == NULL) return -1; wxs->process.cleanup = weston_xserver_cleanup; wxs->wl_display = display; wxs->compositor = compositor; wxs->display = 0; retry: if (create_lockfile(wxs->display, lockfile, sizeof lockfile) < 0) { if (errno == EAGAIN) { goto retry; } else if (errno == EEXIST) { wxs->display++; goto retry; } else { free(wxs); return -1; } } wxs->abstract_fd = bind_to_abstract_socket(wxs->display); if (wxs->abstract_fd < 0 && errno == EADDRINUSE) { wxs->display++; unlink(lockfile); goto retry; } wxs->unix_fd = bind_to_unix_socket(wxs->display); if (wxs->unix_fd < 0) { unlink(lockfile); close(wxs->abstract_fd); free(wxs); return -1; } snprintf(display_name, sizeof display_name, ":%d", wxs->display); weston_log("xserver listening on display %s\n", display_name); setenv("DISPLAY", display_name, 1); wxs->loop = wl_display_get_event_loop(display); wxs->abstract_source = wl_event_loop_add_fd(wxs->loop, wxs->abstract_fd, WL_EVENT_READABLE, weston_xserver_handle_event, wxs); wxs->unix_source = wl_event_loop_add_fd(wxs->loop, wxs->unix_fd, WL_EVENT_READABLE, weston_xserver_handle_event, wxs); wxs->sigusr1_source = wl_event_loop_add_signal(wxs->loop, SIGUSR1, handle_sigusr1, wxs); wxs->destroy_listener.notify = weston_xserver_destroy; wl_signal_add(&compositor->destroy_signal, &wxs->destroy_listener); return 0; }
struct tty * tty_create(struct wlsc_compositor *compositor) { struct termios raw_attributes; struct vt_mode mode = { 0 }; int ret; struct tty *tty; struct wl_event_loop *loop; tty = malloc(sizeof *tty); if (tty == NULL) return NULL; memset(tty, 0, sizeof *tty); tty->compositor = compositor; tty->fd = open("/dev/tty0", O_RDWR | O_NOCTTY); if (tty->fd <= 0) { fprintf(stderr, "failed to open active tty: %m\n"); return NULL; } if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0) { fprintf(stderr, "could not get terminal attributes: %m\n"); return NULL; } /* Ignore control characters and disable echo */ raw_attributes = tty->terminal_attributes; cfmakeraw(&raw_attributes); /* Fix up line endings to be normal (cfmakeraw hoses them) */ raw_attributes.c_oflag |= OPOST | OCRNL; if (tcsetattr(tty->fd, TCSANOW, &raw_attributes) < 0) fprintf(stderr, "could not put terminal into raw mode: %m\n"); loop = wl_display_get_event_loop(compositor->wl_display); tty->input_source = wl_event_loop_add_fd(loop, tty->fd, WL_EVENT_READABLE, on_tty_input, tty); ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS); if (ret) { fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n"); return NULL; } tty->compositor->focus = 1; mode.mode = VT_PROCESS; mode.relsig = SIGUSR1; mode.acqsig = SIGUSR2; if (!ioctl(tty->fd, VT_SETMODE, &mode) < 0) { fprintf(stderr, "failed to take control of vt handling\n"); return NULL; } tty->leave_vt_source = wl_event_loop_add_signal(loop, SIGUSR1, on_leave_vt, tty); tty->enter_vt_source = wl_event_loop_add_signal(loop, SIGUSR2, on_enter_vt, tty); return tty; }
WLC_API struct wlc_event_source* wlc_event_loop_add_fd(int fd, uint32_t mask, int (*cb)(int fd, uint32_t mask, void *arg), void *arg) { assert(wlc_event_loop()); return (struct wlc_event_source*)wl_event_loop_add_fd(wlc_event_loop(), fd, mask, cb, arg); }