From 7f0908546149a39f8db1e842f679364e5d1e59cb Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 11 Apr 2021 16:27:46 +0200 Subject: backend/session: Remove session_impl libseat provides all session functionality, so there is no longer need for a session backend abstraction. The libseat device ID, seat handle and event loop handle are moved to the main wlr_session and wlr_device structs. --- backend/session/session.c | 162 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 128 insertions(+), 34 deletions(-) (limited to 'backend/session/session.c') 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 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 const struct session_impl *const impls[] = { - &session_libseat, - NULL, +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. -- cgit v1.2.3