aboutsummaryrefslogtreecommitdiff
path: root/backend/session
diff options
context:
space:
mode:
authorKenny Levinsen <kl@kl.wtf>2020-07-25 21:53:06 +0200
committerSimon Ser <contact@emersion.fr>2020-08-24 11:13:55 +0200
commitbad1e9afa8ea7d8927c8b4df83d3f277379dd54e (patch)
treea5f655d5b3fa824e12a1429ec4c8e49ab53f2cc9 /backend/session
parent9feeb2738dfc5a2b07a817938cef9d553d0a26ee (diff)
session: Add libseat backend
Diffstat (limited to 'backend/session')
-rw-r--r--backend/session/direct.c3
-rw-r--r--backend/session/libseat.c190
-rw-r--r--backend/session/logind.c5
-rw-r--r--backend/session/meson.build9
-rw-r--r--backend/session/noop.c3
-rw-r--r--backend/session/session.c24
6 files changed, 228 insertions, 6 deletions
diff --git a/backend/session/direct.c b/backend/session/direct.c
index 4ffd711d..f9041070 100644
--- a/backend/session/direct.c
+++ b/backend/session/direct.c
@@ -18,6 +18,7 @@
#include <wlr/backend/session/interface.h>
#include <wlr/util/log.h>
#include "backend/session/direct-ipc.h"
+#include "backend/session/session.h"
#include "util/signal.h"
enum { DRM_MAJOR = 226 };
@@ -246,6 +247,7 @@ static struct wlr_session *direct_session_create(struct wl_display *disp) {
return NULL;
}
+ session_init(&session->base);
session->sock = direct_ipc_init(&session->child);
if (session->sock == -1) {
goto error_session;
@@ -267,6 +269,7 @@ static struct wlr_session *direct_session_create(struct wl_display *disp) {
snprintf(session->base.seat, sizeof(session->base.seat), "%s", seat);
session->base.impl = &session_direct;
+ session->base.active = true;
wlr_log(WLR_INFO, "Successfully loaded direct session");
return &session->base;
diff --git a/backend/session/libseat.c b/backend/session/libseat.c
new file mode 100644
index 00000000..77226204
--- /dev/null
+++ b/backend/session/libseat.c
@@ -0,0 +1,190 @@
+#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.session_signal, session);
+}
+
+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.session_signal, session);
+ 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 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);
+
+ 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);
+}
+
+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/logind.c b/backend/session/logind.c
index c5d0cb29..a460cbe2 100644
--- a/backend/session/logind.c
+++ b/backend/session/logind.c
@@ -13,6 +13,7 @@
#include <wlr/backend/session/interface.h>
#include <wlr/config.h>
#include <wlr/util/log.h>
+#include "backend/session/session.h"
#include "util/signal.h"
#if WLR_HAS_SYSTEMD
@@ -778,6 +779,8 @@ static struct wlr_session *logind_session_create(struct wl_display *disp) {
return NULL;
}
+ session_init(&session->base);
+
if (!get_display_session(&session->id)) {
goto error;
}
@@ -855,6 +858,8 @@ static struct wlr_session *logind_session_create(struct wl_display *disp) {
wlr_log(WLR_INFO, "Successfully loaded logind session");
session->base.impl = &session_logind;
+ session->base.active = true;
+
return &session->base;
error_bus:
diff --git a/backend/session/meson.build b/backend/session/meson.build
index 81ff6d85..4c83685e 100644
--- a/backend/session/meson.build
+++ b/backend/session/meson.build
@@ -62,3 +62,12 @@ if logind_found
wlr_files += files('logind.c')
wlr_deps += logind
endif
+
+# libseat
+
+libseat = dependency('libseat', required: get_option('libseat'))
+if libseat.found()
+ wlr_files += files('libseat.c')
+ wlr_deps += libseat
+ conf_data.set10('WLR_HAS_LIBSEAT', true)
+endif
diff --git a/backend/session/noop.c b/backend/session/noop.c
index 0e13a177..3f293775 100644
--- a/backend/session/noop.c
+++ b/backend/session/noop.c
@@ -6,6 +6,7 @@
#include <wayland-server-core.h>
#include <wlr/backend/session/interface.h>
#include <wlr/util/log.h>
+#include "backend/session/session.h"
#include "util/signal.h"
const struct session_impl session_noop;
@@ -33,7 +34,9 @@ static struct wlr_session *noop_session_create(struct wl_display *disp) {
return NULL;
}
+ session_init(session);
session->impl = &session_noop;
+ session->active = true;
wlr_log(WLR_INFO, "Successfully initialized noop session");
return session;
diff --git a/backend/session/session.c b/backend/session/session.c
index 01eeffd9..d8e9509d 100644
--- a/backend/session/session.c
+++ b/backend/session/session.c
@@ -13,13 +13,18 @@
#include <wlr/util/log.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
+#include "backend/session/session.h"
#include "util/signal.h"
+extern const struct session_impl session_libseat;
extern const struct session_impl session_logind;
extern const struct session_impl session_direct;
extern const struct session_impl session_noop;
static const struct session_impl *impls[] = {
+#if WLR_HAS_LIBSEAT
+ &session_libseat,
+#endif
#if WLR_HAS_SYSTEMD || WLR_HAS_ELOGIND
&session_logind,
#endif
@@ -65,12 +70,24 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
wlr_session_destroy(session);
}
+void session_init(struct wlr_session *session) {
+ wl_signal_init(&session->session_signal);
+ 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, "logind") == 0 ||
+ if (strcmp(env_wlr_session, "libseat") == 0) {
+#if WLR_HAS_LIBSEAT
+ session = session_libseat.create(disp);
+#else
+ wlr_log(WLR_ERROR, "wlroots is not compiled with libseat support");
+#endif
+ } else if (strcmp(env_wlr_session, "logind") == 0 ||
strcmp(env_wlr_session, "systemd") == 0) {
#if WLR_HAS_SYSTEMD || WLR_HAS_ELOGIND
session = session_logind.create(disp);
@@ -97,11 +114,6 @@ struct wlr_session *wlr_session_create(struct wl_display *disp) {
return NULL;
}
- session->active = true;
- wl_signal_init(&session->session_signal);
- wl_signal_init(&session->events.destroy);
- wl_list_init(&session->devices);
-
session->udev = udev_new();
if (!session->udev) {
wlr_log_errno(WLR_ERROR, "Failed to create udev context");