mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-22 09:59:48 +01:00
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.
This commit is contained in:
parent
3f87c2caea
commit
7f09085461
7 changed files with 140 additions and 284 deletions
|
@ -1,218 +0,0 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/backend/session/interface.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/session/session.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
#include <libseat.h>
|
||||
|
||||
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,
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <libudev.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -10,7 +12,6 @@
|
|||
#include <time.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/backend/session/interface.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <xf86drm.h>
|
||||
|
@ -18,15 +19,113 @@
|
|||
#include "backend/session/session.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
#include <libseat.h>
|
||||
|
||||
#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.
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
#include <sys/types.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
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;
|
||||
|
|
|
@ -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 <wlr/backend/session.h>
|
||||
|
||||
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
|
Loading…
Reference in a new issue