diff --git a/backend/session/libseat.c b/backend/session/libseat.c deleted file mode 100644 index 52862d82..00000000 --- a/backend/session/libseat.c +++ /dev/null @@ -1,218 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "backend/session/session.h" -#include "util/signal.h" - -#include - -const struct session_impl session_libseat; - -struct libseat_device { - struct wl_list link; - int fd; - int device_id; -}; - -struct libseat_session { - struct wlr_session base; - - struct libseat *seat; - struct wl_event_source *event; - struct wl_list devices; -}; - -static void handle_enable_seat(struct libseat *seat, void *data) { - struct libseat_session *session = data; - session->base.active = true; - wlr_signal_emit_safe(&session->base.events.active, NULL); -} - -static void handle_disable_seat(struct libseat *seat, void *data) { - struct libseat_session *session = data; - session->base.active = false; - wlr_signal_emit_safe(&session->base.events.active, NULL); - libseat_disable_seat(session->seat); -} - -static int libseat_event(int fd, uint32_t mask, void *data) { - struct libseat *seat = data; - libseat_dispatch(seat, 0); - return 1; -} - -static struct libseat_seat_listener seat_listener = { - .enable_seat = handle_enable_seat, - .disable_seat = handle_disable_seat, -}; - -static struct libseat_session *libseat_session_from_session( - struct wlr_session *base) { - assert(base->impl == &session_libseat); - return (struct libseat_session *)base; -} - -static enum wlr_log_importance libseat_log_level_to_wlr( - enum libseat_log_level level) { - switch (level) { - case LIBSEAT_LOG_LEVEL_ERROR: - return WLR_ERROR; - case LIBSEAT_LOG_LEVEL_INFO: - return WLR_INFO; - default: - return WLR_DEBUG; - } -} - -static void log_libseat(enum libseat_log_level level, - const char *fmt, va_list args) { - enum wlr_log_importance importance = libseat_log_level_to_wlr(level); - - static char wlr_fmt[1024]; - snprintf(wlr_fmt, sizeof(wlr_fmt), "[libseat] %s", fmt); - - _wlr_vlog(importance, wlr_fmt, args); -} - -static struct wlr_session *libseat_session_create(struct wl_display *disp) { - struct libseat_session *session = calloc(1, sizeof(*session)); - if (!session) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - return NULL; - } - - session_init(&session->base); - wl_list_init(&session->devices); - - libseat_set_log_handler(log_libseat); - libseat_set_log_level(LIBSEAT_LOG_LEVEL_INFO); - - // libseat will take care of updating the logind state if necessary - setenv("XDG_SESSION_TYPE", "wayland", 1); - - session->seat = libseat_open_seat(&seat_listener, session); - if (session->seat == NULL) { - wlr_log_errno(WLR_ERROR, "Unable to create seat"); - goto error; - } - - const char *seat_name = libseat_seat_name(session->seat); - if (seat_name == NULL) { - wlr_log_errno(WLR_ERROR, "Unable to get seat info"); - goto error; - } - snprintf(session->base.seat, sizeof(session->base.seat), "%s", seat_name); - - struct wl_event_loop *event_loop = wl_display_get_event_loop(disp); - session->event = wl_event_loop_add_fd(event_loop, libseat_get_fd(session->seat), - WL_EVENT_READABLE, libseat_event, session->seat); - if (session->event == NULL) { - wlr_log(WLR_ERROR, "Failed to create libseat event source"); - goto error; - } - - // We may have received enable_seat immediately after the open_seat result, - // so, dispatch once without timeout to speed up activation. - if (libseat_dispatch(session->seat, 0) == -1) { - wlr_log_errno(WLR_ERROR, "libseat dispatch failed"); - goto error; - } - - wlr_log(WLR_INFO, "Successfully loaded libseat session"); - session->base.impl = &session_libseat; - return &session->base; - -error: - if (session->seat != NULL) { - libseat_close_seat(session->seat); - } - if (session->event != NULL) { - wl_event_source_remove(session->event); - } - free(session); - return NULL; -} - -static void libseat_session_destroy(struct wlr_session *base) { - struct libseat_session *session = libseat_session_from_session(base); - - libseat_close_seat(session->seat); - wl_event_source_remove(session->event); - free(session); -} - -static struct libseat_device *find_device_by_fd(struct libseat_session *session, int fd) { - struct libseat_device *dev; - wl_list_for_each(dev, &session->devices, link) { - if (dev->fd == fd) { - return dev; - } - } - return NULL; -} - -static int libseat_session_open_device(struct wlr_session *base, const char *path) { - struct libseat_session *session = libseat_session_from_session(base); - - int fd; - int device_id = libseat_open_device(session->seat, path, &fd); - if (device_id == -1) { - wlr_log_errno(WLR_ERROR, "Failed to open device '%s'", path); - return -1; - } - - struct libseat_device *dev = calloc(1, sizeof(struct libseat_device)); - if (dev == NULL) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - libseat_close_device(session->seat, device_id); - return -1; - } - - dev->fd = fd; - dev->device_id = device_id; - wl_list_insert(&session->devices, &dev->link); - - return fd; -} - -static void libseat_session_close_device(struct wlr_session *base, int fd) { - struct libseat_session *session = libseat_session_from_session(base); - - struct libseat_device *dev = find_device_by_fd(session, fd); - if (dev == NULL) { - wlr_log(WLR_ERROR, "No device with fd %d found", fd); - close(fd); - return; - } - - if (libseat_close_device(session->seat, dev->device_id) == -1) { - wlr_log_errno(WLR_ERROR, "Failed to close device %d", dev->device_id); - } - - wl_list_remove(&dev->link); - free(dev); - close(fd); -} - -static bool libseat_change_vt(struct wlr_session *base, unsigned vt) { - struct libseat_session *session = libseat_session_from_session(base); - return libseat_switch_session(session->seat, vt) == 0; -} - -const struct session_impl session_libseat = { - .create = libseat_session_create, - .destroy = libseat_session_destroy, - .open = libseat_session_open_device, - .close = libseat_session_close_device, - .change_vt = libseat_change_vt, -}; diff --git a/backend/session/meson.build b/backend/session/meson.build index 41a56031..66c908a2 100644 --- a/backend/session/meson.build +++ b/backend/session/meson.build @@ -3,10 +3,5 @@ libseat = dependency('libseat', fallback: ['seatd', 'libseat'], default_options: ['server=disabled', 'man-pages=disabled'], ) - -wlr_files += files( - 'session.c', - 'libseat.c' -) - +wlr_files += files('session.c') wlr_deps += libseat diff --git a/backend/session/session.c b/backend/session/session.c index c9df78e4..63bca140 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -1,8 +1,10 @@ #define _POSIX_C_SOURCE 200809L #include #include +#include #include #include +#include #include #include #include @@ -10,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -18,15 +19,113 @@ #include "backend/session/session.h" #include "util/signal.h" +#include + #define WAIT_GPU_TIMEOUT 10000 // ms -extern const struct session_impl session_libseat; +static void handle_enable_seat(struct libseat *seat, void *data) { + struct wlr_session *session = data; + session->active = true; + wlr_signal_emit_safe(&session->events.active, NULL); +} -static const struct session_impl *const impls[] = { - &session_libseat, - NULL, +static void handle_disable_seat(struct libseat *seat, void *data) { + struct wlr_session *session = data; + session->active = false; + wlr_signal_emit_safe(&session->events.active, NULL); + libseat_disable_seat(session->seat_handle); +} + +static int libseat_event(int fd, uint32_t mask, void *data) { + struct wlr_session *session = data; + if (libseat_dispatch(session->seat_handle, 0) == -1) { + wlr_log_errno(WLR_ERROR, "Failed to dispatch libseat"); + wl_display_terminate(session->display); + } + return 1; +} + +static struct libseat_seat_listener seat_listener = { + .enable_seat = handle_enable_seat, + .disable_seat = handle_disable_seat, }; +static enum wlr_log_importance libseat_log_level_to_wlr( + enum libseat_log_level level) { + switch (level) { + case LIBSEAT_LOG_LEVEL_ERROR: + return WLR_ERROR; + case LIBSEAT_LOG_LEVEL_INFO: + return WLR_INFO; + default: + return WLR_DEBUG; + } +} + +static void log_libseat(enum libseat_log_level level, + const char *fmt, va_list args) { + enum wlr_log_importance importance = libseat_log_level_to_wlr(level); + + static char wlr_fmt[1024]; + snprintf(wlr_fmt, sizeof(wlr_fmt), "[libseat] %s", fmt); + + _wlr_vlog(importance, wlr_fmt, args); +} + +static int libseat_session_init(struct wlr_session *session, struct wl_display *disp) { + libseat_set_log_handler(log_libseat); + libseat_set_log_level(LIBSEAT_LOG_LEVEL_INFO); + + // libseat will take care of updating the logind state if necessary + setenv("XDG_SESSION_TYPE", "wayland", 1); + + session->seat_handle = libseat_open_seat(&seat_listener, session); + if (session->seat_handle == NULL) { + wlr_log_errno(WLR_ERROR, "Unable to create seat"); + return -1; + } + + const char *seat_name = libseat_seat_name(session->seat_handle); + if (seat_name == NULL) { + wlr_log_errno(WLR_ERROR, "Unable to get seat info"); + goto error; + } + snprintf(session->seat, sizeof(session->seat), "%s", seat_name); + + struct wl_event_loop *event_loop = wl_display_get_event_loop(disp); + session->libseat_event = wl_event_loop_add_fd(event_loop, libseat_get_fd(session->seat_handle), + WL_EVENT_READABLE, libseat_event, session); + if (session->libseat_event == NULL) { + wlr_log(WLR_ERROR, "Failed to create libseat event source"); + goto error; + } + + // We may have received enable_seat immediately after the open_seat result, + // so, dispatch once without timeout to speed up activation. + if (libseat_dispatch(session->seat_handle, 0) == -1) { + wlr_log_errno(WLR_ERROR, "libseat dispatch failed"); + goto error_dispatch; + } + + wlr_log(WLR_INFO, "Successfully loaded libseat session"); + return 0; + +error_dispatch: + wl_event_source_remove(session->libseat_event); + session->libseat_event = NULL; +error: + libseat_close_seat(session->seat_handle); + session->seat_handle = NULL; + return -1; +} + +static void libseat_session_finish(struct wlr_session *session) { + libseat_close_seat(session->seat_handle); + wl_event_source_remove(session->libseat_event); + session->seat_handle = NULL; + session->libseat_event = NULL; +} + static bool is_drm_card(const char *sysname) { const char prefix[] = "card"; if (strncmp(sysname, prefix, strlen(prefix)) != 0) { @@ -94,34 +193,21 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { wlr_session_destroy(session); } -void session_init(struct wlr_session *session) { +struct wlr_session *wlr_session_create(struct wl_display *disp) { + struct wlr_session *session = calloc(1, sizeof(*session)); + if (!session) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + return NULL; + } + wl_signal_init(&session->events.active); wl_signal_init(&session->events.add_drm_card); wl_signal_init(&session->events.destroy); wl_list_init(&session->devices); -} -struct wlr_session *wlr_session_create(struct wl_display *disp) { - struct wlr_session *session = NULL; - - const char *env_wlr_session = getenv("WLR_SESSION"); - if (env_wlr_session) { - if (strcmp(env_wlr_session, "libseat") == 0) { - session = session_libseat.create(disp); - } else { - wlr_log(WLR_ERROR, "Unsupported WLR_SESSION: %s", - env_wlr_session); - } - } else { - const struct session_impl *const *iter; - for (iter = impls; !session && *iter; ++iter) { - session = (*iter)->create(disp); - } - } - - if (!session) { + if (libseat_session_init(session, disp) == -1) { wlr_log(WLR_ERROR, "Failed to load session backend"); - return NULL; + goto error_open; } session->udev = udev_new(); @@ -161,7 +247,9 @@ error_mon: error_udev: udev_unref(session->udev); error_session: - session->impl->destroy(session); + libseat_session_finish(session); +error_open: + free(session); return NULL; } @@ -177,13 +265,16 @@ void wlr_session_destroy(struct wlr_session *session) { udev_monitor_unref(session->mon); udev_unref(session->udev); - session->impl->destroy(session); + libseat_session_finish(session); + free(session); } struct wlr_device *wlr_session_open_file(struct wlr_session *session, const char *path) { - int fd = session->impl->open(session, path); - if (fd < 0) { + int fd; + int device_id = libseat_open_device(session->seat_handle, path, &fd); + if (device_id == -1) { + wlr_log_errno(WLR_ERROR, "Failed to open device: '%s'", path); return NULL; } @@ -201,12 +292,14 @@ struct wlr_device *wlr_session_open_file(struct wlr_session *session, dev->fd = fd; dev->dev = st.st_rdev; + dev->device_id = device_id; wl_signal_init(&dev->events.change); wl_list_insert(&session->devices, &dev->link); return dev; error: + libseat_close_device(session->seat_handle, device_id); free(dev); close(fd); return NULL; @@ -214,7 +307,9 @@ error: void wlr_session_close_file(struct wlr_session *session, struct wlr_device *dev) { - session->impl->close(session, dev->fd); + if (libseat_close_device(session->seat_handle, dev->device_id) == -1) { + wlr_log_errno(WLR_ERROR, "Failed to close device %d", dev->device_id); + } wl_list_remove(&dev->link); free(dev); } @@ -223,8 +318,7 @@ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) { if (!session) { return false; } - - return session->impl->change_vt(session, vt); + return libseat_switch_session(session->seat_handle, vt) == 0; } /* Tests if 'path' is KMS compatible by trying to open it. diff --git a/docs/env_vars.md b/docs/env_vars.md index 34b8b823..8461d132 100644 --- a/docs/env_vars.md +++ b/docs/env_vars.md @@ -6,8 +6,6 @@ wlroots reads these environment variables libinput, drm, wayland, x11, headless, noop) * *WLR_NO_HARDWARE_CURSORS*: set to 1 to use software cursors instead of hardware cursors -* *WLR_SESSION*: specifies the `wlr_session` to be used (available sessions: - libseat) * *WLR_DIRECT_TTY*: specifies the tty to be used (instead of using /dev/tty) * *WLR_XWAYLAND*: specifies the path to an Xwayland binary to be used (instead of following shell search semantics for "Xwayland") diff --git a/include/backend/session/session.h b/include/backend/session/session.h index 626f470a..ebe6fc70 100644 --- a/include/backend/session/session.h +++ b/include/backend/session/session.h @@ -3,6 +3,12 @@ struct wlr_session; +struct wlr_session *libseat_session_create(struct wl_display *disp); +void libseat_session_destroy(struct wlr_session *base); +int libseat_session_open_device(struct wlr_session *base, const char *path); +void libseat_session_close_device(struct wlr_session *base, int fd); +bool libseat_change_vt(struct wlr_session *base, unsigned vt); + void session_init(struct wlr_session *session); #endif diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h index 6fee0421..0c744673 100644 --- a/include/wlr/backend/session.h +++ b/include/wlr/backend/session.h @@ -6,10 +6,11 @@ #include #include -struct session_impl; +struct libseat; struct wlr_device { int fd; + int device_id; dev_t dev; struct wl_list link; @@ -19,7 +20,6 @@ struct wlr_device { }; struct wlr_session { - const struct session_impl *impl; /* * Signal for when the session becomes active/inactive. * It's called when we swap virtual terminal. @@ -37,6 +37,9 @@ struct wlr_session { struct udev_monitor *mon; struct wl_event_source *udev_event; + struct libseat *seat_handle; + struct wl_event_source *libseat_event; + struct wl_list devices; struct wl_display *display; diff --git a/include/wlr/backend/session/interface.h b/include/wlr/backend/session/interface.h deleted file mode 100644 index 5ccf9c8a..00000000 --- a/include/wlr/backend/session/interface.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_BACKEND_SESSION_INTERFACE_H -#define WLR_BACKEND_SESSION_INTERFACE_H - -#include - -struct session_impl { - struct wlr_session *(*create)(struct wl_display *disp); - void (*destroy)(struct wlr_session *session); - int (*open)(struct wlr_session *session, const char *path); - void (*close)(struct wlr_session *session, int fd); - bool (*change_vt)(struct wlr_session *session, unsigned vt); -}; - -#endif