From 6c4a993a999048a2054ec97e71d32839b312c642 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Wed, 21 Oct 2020 21:36:57 +0200 Subject: [PATCH] libweston/launcher: libseat backend This adds support for libseat as a seat backend. libseat provides seatd, (e)logind and direct seat backends as compile-time and runtime options. The backend is currently disabled by default. It can be enabled through the launcher-libseat option. Signed-off-by: Kenny Levinsen --- libweston/launcher-impl.h | 1 + libweston/launcher-libseat.c | 255 +++++++++++++++++++++++++++++++++++ libweston/launcher-util.c | 3 + libweston/meson.build | 10 ++ meson_options.txt | 7 + 5 files changed, 276 insertions(+) create mode 100644 libweston/launcher-libseat.c diff --git a/libweston/launcher-impl.h b/libweston/launcher-impl.h index a04647ef..6bcbbc54 100644 --- a/libweston/launcher-impl.h +++ b/libweston/launcher-impl.h @@ -45,6 +45,7 @@ struct weston_launcher { const struct launcher_interface *iface; }; +extern const struct launcher_interface launcher_libseat_iface; extern const struct launcher_interface launcher_logind_iface; extern const struct launcher_interface launcher_weston_launch_iface; extern const struct launcher_interface launcher_direct_iface; diff --git a/libweston/launcher-libseat.c b/libweston/launcher-libseat.c new file mode 100644 index 00000000..6aa8ad0f --- /dev/null +++ b/libweston/launcher-libseat.c @@ -0,0 +1,255 @@ +/* + * Copyright © 2020 Kenny Levinsen + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "backend.h" +#include "dbus.h" +#include "launcher-impl.h" + +struct launcher_libseat_device { + struct wl_list link; + int fd; + int device_id; + dev_t fsdev; +}; + +struct launcher_libseat { + struct weston_launcher base; + struct weston_compositor *compositor; + struct libseat *seat; + + struct wl_event_source *seat_ctx; + struct wl_list devices; +}; + +static struct launcher_libseat_device * +find_device_by_fd(struct launcher_libseat *wl, int fd) +{ + struct launcher_libseat_device *dev; + wl_list_for_each(dev, &wl->devices, link) { + if (dev->fd == fd) { + return dev; + } + } + return NULL; +} + +static void +handle_enable_seat(struct libseat *seat, void *data) +{ + struct launcher_libseat *wl = data; + if (wl->compositor->session_active) + return; + + wl->compositor->session_active = true; + + wl_signal_emit(&wl->compositor->session_signal, + wl->compositor); +} + +static void +handle_disable_seat(struct libseat *seat, void *data) +{ + struct launcher_libseat *wl = data; + if (!wl->compositor->session_active) + return; + + wl->compositor->session_active = false; + + wl_signal_emit(&wl->compositor->session_signal, + wl->compositor); + libseat_disable_seat(wl->seat); +} + +static struct libseat_seat_listener seat_listener = { + .enable_seat = handle_enable_seat, + .disable_seat = handle_disable_seat, +}; + +static int +seat_open_device(struct weston_launcher *launcher, const char *path, int flags) +{ + struct launcher_libseat *wl = wl_container_of(launcher, wl, base); + struct launcher_libseat_device *dev; + struct stat st; + + dev = zalloc(sizeof(struct launcher_libseat_device)); + if (dev == NULL) { + goto err_alloc; + } + + dev->device_id = libseat_open_device(wl->seat, path, &dev->fd); + if (dev->device_id == -1) { + goto err_open; + } + + if (fstat(dev->fd, &st) == -1) { + goto err_fd; + } + dev->fsdev = st.st_rdev; + + wl_list_insert(&wl->devices, &dev->link); + return dev->fd; + +err_fd: + libseat_close_device(wl->seat, dev->device_id); + close(dev->fd); +err_open: + free(dev); +err_alloc: + return -1; +} + +static void +seat_close_device(struct weston_launcher *launcher, int fd) +{ + struct launcher_libseat *wl = wl_container_of(launcher, wl, base); + struct launcher_libseat_device *dev; + + dev = find_device_by_fd(wl, fd); + if (dev == NULL) { + weston_log("libseat: No device with fd %d found\n", fd); + close(fd); + return; + } + + if (libseat_close_device(wl->seat, dev->device_id) == -1) { + weston_log("libseat: Could not close device %d", + dev->device_id); + } + + wl_list_remove(&dev->link); + free(dev); + close(fd); +} + +static int +seat_switch_session(struct weston_launcher *launcher, int vt) +{ + struct launcher_libseat *wl = wl_container_of(launcher, wl, base); + return libseat_switch_session(wl->seat, vt); +} + +static int +libseat_event(int fd, uint32_t mask, void *data) +{ + struct libseat *seat = data; + if (libseat_dispatch(seat, 0) == -1) { + weston_log("libseat: dispatch failed: %s\n", strerror(errno)); + exit(-1); + } + return 1; +} + +static int +seat_open(struct weston_launcher **out, struct weston_compositor *compositor, + int tty, const char *seat_id, bool sync_drm) +{ + struct launcher_libseat *wl; + struct wl_event_loop *event_loop; + + wl = zalloc(sizeof(*wl)); + if (wl == NULL) { + goto err_out; + } + + wl->base.iface = &launcher_libseat_iface; + wl->compositor = compositor; + wl_list_init(&wl->devices); + + wl->seat = libseat_open_seat(&seat_listener, wl); + if (wl->seat == NULL) { + weston_log("libseat: could not open seat\n"); + goto err_seat; + } + + event_loop = wl_display_get_event_loop(compositor->wl_display); + wl->seat_ctx = wl_event_loop_add_fd(event_loop, + libseat_get_fd(wl->seat), WL_EVENT_READABLE, + libseat_event, wl->seat); + if (wl->seat_ctx == NULL) { + weston_log("libseat: could not register connection to event loop\n"); + goto err_session; + } + if (libseat_dispatch(wl->seat, 0) == -1) { + weston_log("libseat: dispatch failed\n"); + goto err_session; + } + + weston_log("libseat: session control granted\n"); + *out = &wl->base; + return 0; + +err_session: + libseat_close_seat(wl->seat); +err_seat: + free(wl); +err_out: + return -1; +} + +static void +seat_close(struct weston_launcher *launcher) +{ + struct launcher_libseat *wl = wl_container_of(launcher, wl, base); + + if (wl->seat != NULL) { + libseat_close_seat(wl->seat); + } + wl_event_source_remove(wl->seat_ctx); + free(wl); +} + +static int +seat_get_vt(struct weston_launcher *launcher) +{ + return -ENOSYS; +} + +const struct launcher_interface launcher_libseat_iface = { + .name = "libseat", + .connect = seat_open, + .destroy = seat_close, + .open = seat_open_device, + .close = seat_close_device, + .activate_vt = seat_switch_session, + .get_vt = seat_get_vt, +}; diff --git a/libweston/launcher-util.c b/libweston/launcher-util.c index 2e472aed..058b6ac0 100644 --- a/libweston/launcher-util.c +++ b/libweston/launcher-util.c @@ -36,6 +36,9 @@ #include static const struct launcher_interface *ifaces[] = { +#ifdef HAVE_LIBSEAT + &launcher_libseat_iface, +#endif #ifdef HAVE_SYSTEMD_LOGIN &launcher_logind_iface, #endif diff --git a/libweston/meson.build b/libweston/meson.build index 08d23ecd..ee1d128c 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -180,6 +180,16 @@ if get_option('launcher-logind') systemd_dep, ] endif +if get_option('launcher-libseat') + libseat_dep = dependency('libseat', version: '>= 0.4') + config_h.set('HAVE_LIBSEAT', '1') + srcs_session_helper += [ + 'launcher-libseat.c', + ] + deps_session_helper += [ + libseat_dep, + ] +endif lib_session_helper = static_library( 'session-helper', diff --git a/meson_options.txt b/meson_options.txt index ea225a90..da4ccaab 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -158,6 +158,13 @@ option( description: 'Compositor: support systemd-logind D-Bus protocol' ) +option( + 'launcher-libseat', + type: 'boolean', + value: false, + description: 'Compositor: support libseat' +) + option( 'image-jpeg', type: 'boolean',