aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.builds/alpine.yml2
-rw-r--r--.builds/archlinux.yml1
-rw-r--r--.builds/freebsd.yml1
-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
-rw-r--r--include/backend/session/session.h8
-rw-r--r--include/wlr/config.h.in2
-rw-r--r--meson.build2
-rw-r--r--meson_options.txt1
13 files changed, 244 insertions, 7 deletions
diff --git a/.builds/alpine.yml b/.builds/alpine.yml
index 13221d25..402f72f6 100644
--- a/.builds/alpine.yml
+++ b/.builds/alpine.yml
@@ -16,7 +16,7 @@ sources:
tasks:
- setup: |
cd wlroots
- meson build -Dauto_features=enabled -Dlogind=disabled -Dxcb-errors=disabled
+ meson build -Dauto_features=enabled -Dlogind=disabled -Dlibseat=disabled -Dxcb-errors=disabled
- build: |
cd wlroots
ninja -C build
diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml
index b3b1a3c0..9cf2f84f 100644
--- a/.builds/archlinux.yml
+++ b/.builds/archlinux.yml
@@ -12,6 +12,7 @@ packages:
- xcb-util-errors
- xcb-util-image
- xcb-util-wm
+ - seatd
sources:
- https://github.com/swaywm/wlroots
tasks:
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
index a0dfc442..74553f7b 100644
--- a/.builds/freebsd.yml
+++ b/.builds/freebsd.yml
@@ -18,6 +18,7 @@ packages:
- x11/pixman
- x11/xcb-util-errors
- x11/xcb-util-wm
+- sysutils/seatd
sources:
- https://github.com/swaywm/wlroots
tasks:
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");
diff --git a/include/backend/session/session.h b/include/backend/session/session.h
new file mode 100644
index 00000000..626f470a
--- /dev/null
+++ b/include/backend/session/session.h
@@ -0,0 +1,8 @@
+#ifndef BACKEND_SESSION_SESSION_H
+#define BACKEND_SESSION_SESSION_H
+
+struct wlr_session;
+
+void session_init(struct wlr_session *session);
+
+#endif
diff --git a/include/wlr/config.h.in b/include/wlr/config.h.in
index a7691ff9..77a15598 100644
--- a/include/wlr/config.h.in
+++ b/include/wlr/config.h.in
@@ -8,6 +8,8 @@
#mesondefine WLR_HAS_SYSTEMD
#mesondefine WLR_HAS_ELOGIND
+#mesondefine WLR_HAS_LIBSEAT
+
#mesondefine WLR_HAS_X11_BACKEND
#mesondefine WLR_HAS_XWAYLAND
diff --git a/meson.build b/meson.build
index 4abe6318..ca26391e 100644
--- a/meson.build
+++ b/meson.build
@@ -82,6 +82,7 @@ endif
conf_data = configuration_data()
conf_data.set10('WLR_HAS_SYSTEMD', false)
conf_data.set10('WLR_HAS_ELOGIND', false)
+conf_data.set10('WLR_HAS_LIBSEAT', false)
conf_data.set10('WLR_HAS_X11_BACKEND', false)
conf_data.set10('WLR_HAS_XWAYLAND', false)
conf_data.set10('WLR_HAS_XCB_ERRORS', false)
@@ -176,6 +177,7 @@ meson.override_dependency('wlroots', wlroots)
summary({
'systemd': conf_data.get('WLR_HAS_SYSTEMD', 0),
'elogind': conf_data.get('WLR_HAS_ELOGIND', 0),
+ 'libseat': conf_data.get('WLR_HAS_LIBSEAT', 0),
'xwayland': conf_data.get('WLR_HAS_XWAYLAND', 0),
'x11_backend': conf_data.get('WLR_HAS_X11_BACKEND', 0),
'xcb-icccm': conf_data.get('WLR_HAS_XCB_ICCCM', 0),
diff --git a/meson_options.txt b/meson_options.txt
index 894113e7..382ef2a6 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,5 +1,6 @@
option('logind', type: 'feature', value: 'auto', description: 'Enable support for rootless session via logind')
option('logind-provider', type: 'combo', choices: ['auto', 'systemd', 'elogind'], value: 'auto', description: 'Provider of logind support library')
+option('libseat', type: 'feature', value: 'auto', description: 'Enable support for rootless session via libseat')
option('xcb-errors', type: 'feature', value: 'auto', description: 'Use xcb-errors util library')
option('xcb-icccm', type: 'feature', value: 'auto', description: 'Use xcb-icccm util library')
option('xwayland', type: 'feature', value: 'auto', yield: true, description: 'Enable support for X11 applications')