From 6b423de3169d75a6178c570d15f7933427a86564 Mon Sep 17 00:00:00 2001 From: Imran Zaman Date: Tue, 18 Nov 2014 17:03:42 +0200 Subject: [PATCH] downstream: Multiseat support for drm/wayland backends Change-Id: I04f04df98c2f76cf09b5d4d14867f918919aeb15 Signed-off-by: Imran Zaman --- configure.ac | 11 ++ fullscreen-shell/fullscreen-shell.c | 33 +++-- src/compositor-drm.c | 70 +++++++---- src/compositor-rdp.c | 1 + src/compositor-wayland.c | 234 +++++++++++++++++++++++++++++------- src/compositor.c | 40 ++++-- src/compositor.h | 7 +- src/input.c | 33 +++-- src/launcher-util.c | 4 +- src/libinput-seat.c | 69 +++++++++-- src/libinput-seat.h | 18 +-- src/udev-seat.c | 81 ++++++++++--- src/udev-seat.h | 19 +-- 13 files changed, 479 insertions(+), 141 deletions(-) diff --git a/configure.ac b/configure.ac index abaa945..d2b125e 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,17 @@ if test x$enable_xkbcommon = xyes; then COMPOSITOR_MODULES="$COMPOSITOR_MODULES xkbcommon >= 0.3.0" fi +AC_ARG_ENABLE([multiseat], + [AC_HELP_STRING([--enable-multiseat], + [Enable multiseat feature])], + [], + [enable_multiseat=no]) + +if test "x$enable_multiseat" = "xyes"; then + AC_DEFINE(HAVE_MULTISEAT, [1], [Enable multiseat feature]) +fi +AM_CONDITIONAL(HAVE_MULTISEAT, test "x$enable_multiseat" = xyes) + AC_ARG_ENABLE(sys-uid, [ --enable-sys-uid],, enable_sys_uid=no) if test x$enable_sys_uid = xyes; then diff --git a/fullscreen-shell/fullscreen-shell.c b/fullscreen-shell/fullscreen-shell.c index 25932d4..57ef641 100644 --- a/fullscreen-shell/fullscreen-shell.c +++ b/fullscreen-shell/fullscreen-shell.c @@ -32,9 +32,14 @@ #include "compositor.h" #include "fullscreen-shell-server-protocol.h" -struct fullscreen_shell { +struct fs_client { struct wl_client *client; struct wl_listener client_destroyed; + struct wl_list link; +}; + +struct fullscreen_shell { + struct wl_list client_list; struct weston_compositor *compositor; struct weston_layer layer; @@ -755,10 +760,9 @@ output_created(struct wl_listener *listener, void *data) static void client_destroyed(struct wl_listener *listener, void *data) { - struct fullscreen_shell *shell = container_of(listener, - struct fullscreen_shell, - client_destroyed); - shell->client = NULL; + struct fs_client *client = container_of(listener, + struct fs_client, client_destroyed); + if (client) wl_list_remove(&client->link); } static void @@ -767,12 +771,15 @@ bind_fullscreen_shell(struct wl_client *client, void *data, uint32_t version, { struct fullscreen_shell *shell = data; struct wl_resource *resource; - - if (shell->client != NULL && shell->client != client) - return; - else if (shell->client == NULL) { - shell->client = client; - wl_client_add_destroy_listener(client, &shell->client_destroyed); + struct fs_client *new_client; + + new_client = malloc(sizeof *new_client); + if (new_client) { + memset(new_client, 0, sizeof *new_client); + new_client->client = client; + new_client->client_destroyed.notify = client_destroyed; + wl_list_insert(&shell->client_list, &new_client->link); + wl_client_add_destroy_listener(client, &new_client->client_destroyed); } resource = wl_resource_create(client, &_wl_fullscreen_shell_interface, @@ -805,7 +812,7 @@ module_init(struct weston_compositor *compositor, memset(shell, 0, sizeof *shell); shell->compositor = compositor; - shell->client_destroyed.notify = client_destroyed; + wl_list_init(&shell->client_list); weston_layer_init(&shell->layer, &compositor->cursor_layer.link); @@ -820,7 +827,7 @@ module_init(struct weston_compositor *compositor, wl_signal_add(&compositor->seat_created_signal, &shell->seat_created_listener); wl_list_for_each(seat, &compositor->seat_list, link) - seat_created(NULL, seat); + seat_created(&shell->seat_created_listener, seat); wl_global_create(compositor->wl_display, &_wl_fullscreen_shell_interface, 1, shell, diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 6732c1b..d558f7d 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -120,6 +120,7 @@ struct drm_compositor { clockid_t clock; struct udev_input input; + char *main_seat; uint32_t cursor_width; uint32_t cursor_height; @@ -1878,14 +1879,21 @@ setup_output_seat_constraint(struct drm_compositor *ec, if (strcmp(s, "") != 0) { struct udev_seat *seat; - seat = udev_seat_get_named(&ec->input, s); - if (seat) - seat->base.output = output; - - if (seat && seat->base.pointer) - weston_pointer_clamp(seat->base.pointer, + seat = udev_seat_get_named(&ec->base, s); + if (seat) { + udev_seat_link_output(seat, output); +#if HAVE_MULTISEAT + if (!seat->input.libinput) + udev_input_init(&seat->input, &ec->base, + ec->udev, s); + else if (seat->input.suspended) + udev_input_enable(&seat->input); +#endif + if (seat->base.pointer) + weston_pointer_clamp(seat->base.pointer, &seat->base.pointer->x, &seat->base.pointer->y); + } } } @@ -1994,6 +2002,9 @@ create_output_for_connector(struct drm_compositor *ec, output->format = ec->format; weston_config_section_get_string(section, "seat", &s, ""); + output->base.seat_data.seatname = strdup(s); + weston_log("output %p belongs to seat '%s'\n", output, + output->base.seat_data.seatname); setup_output_seat_constraint(ec, &output->base, s); free(s); @@ -2411,8 +2422,6 @@ drm_destroy(struct weston_compositor *ec) { struct drm_compositor *d = (struct drm_compositor *) ec; - udev_input_destroy(&d->input); - wl_event_source_remove(d->udev_drm_source); wl_event_source_remove(d->drm_source); @@ -2426,7 +2435,7 @@ drm_destroy(struct weston_compositor *ec) weston_launcher_destroy(d->base.launcher); close(d->drm.fd); - + free (d->main_seat); free(d); } @@ -2469,16 +2478,24 @@ session_notify(struct wl_listener *listener, void *data) struct drm_compositor *ec = data; struct drm_sprite *sprite; struct drm_output *output; + struct udev_seat *useat; + struct weston_seat *seat, *next; if (ec->base.session_active) { weston_log("activating session\n"); compositor->state = ec->prev_state; drm_compositor_set_modes(ec); weston_compositor_damage_all(compositor); - udev_input_enable(&ec->input); + wl_list_for_each_safe(seat, next, &ec->base.seat_list, link) { + useat = container_of(seat, struct udev_seat, base); + udev_input_enable(&useat->input); + } } else { weston_log("deactivating session\n"); - udev_input_disable(&ec->input); + wl_list_for_each_safe(seat, next, &ec->base.seat_list, link) { + useat = container_of(seat, struct udev_seat, base); + udev_input_disable(&useat->input); + } ec->prev_state = compositor->state; weston_compositor_offscreen(compositor); @@ -2748,6 +2765,23 @@ renderer_switch_binding(struct weston_seat *seat, uint32_t time, uint32_t key, switch_to_gl_renderer(c); } +static int +create_seats(struct drm_compositor *ec, int connector, + struct udev_device *drm_device) +{ + struct udev_seat *seat = udev_seat_get_named(&ec->base, ec->main_seat); + if (seat && udev_input_init(&seat->input, &ec->base, + ec->udev, ec->main_seat) < 0) { + weston_log("failed to create input devices\n"); + return -1; + } + + if (create_outputs(ec, connector, drm_device) < 0) + return -1; + + return 0; +} + static struct weston_compositor * drm_compositor_create(struct wl_display *display, struct drm_parameters *param, @@ -2841,15 +2875,10 @@ drm_compositor_create(struct wl_display *display, wl_list_init(&ec->sprite_list); create_sprites(ec); - if (udev_input_init(&ec->input, - &ec->base, ec->udev, param->seat_id) < 0) { - weston_log("failed to create input devices\n"); - goto err_sprite; - } - - if (create_outputs(ec, param->connector, drm_device) < 0) { + ec->main_seat = strdup(param->seat_id); + if (create_seats(ec, param->connector, drm_device) < 0) { weston_log("failed to create output for %s\n", path); - goto err_udev_input; + goto err_sprite; } /* A this point we have some idea of whether or not we have a working @@ -2901,8 +2930,6 @@ err_udev_monitor: udev_monitor_unref(ec->udev_monitor); err_drm_source: wl_event_source_remove(ec->drm_source); -err_udev_input: - udev_input_destroy(&ec->input); err_sprite: ec->base.renderer->destroy(&ec->base); gbm_device_destroy(ec->gbm); @@ -2916,6 +2943,7 @@ err_udev: err_compositor: weston_compositor_shutdown(&ec->base); err_base: + free(ec->main_seat); free(ec); return NULL; } diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c index 6af37b0..df66738 100644 --- a/src/compositor-rdp.c +++ b/src/compositor-rdp.c @@ -46,6 +46,7 @@ #include #include "compositor.h" +#include "../shared/str-util.h" #include "pixman-renderer.h" #define MAX_FREERDP_FDS 32 diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 5f73c78..3b0dd83 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -65,6 +65,8 @@ struct wayland_compositor { int use_pixman; int sprawl_across_outputs; + int seatfilter; + char *seatname; struct theme *theme; cairo_device_t *frame_device; @@ -114,6 +116,7 @@ struct wayland_output { struct wayland_parent_output { struct wayland_output *output; + struct wayland_compositor *c; struct wl_list link; struct wl_output *global; @@ -133,10 +136,12 @@ struct wayland_parent_output { struct wl_list mode_list; struct weston_mode *preferred_mode; struct weston_mode *current_mode; + char *seatname; }; struct wayland_shm_buffer { struct wayland_output *output; + struct wl_list link; struct wl_list free_link; @@ -173,6 +178,10 @@ struct wayland_input { int focus; struct wayland_output *output; struct wayland_output *keyboard_focus; + + enum wl_seat_capability caps; + int initialized; + int caps_update_required; }; struct gl_renderer_interface *gl_renderer; @@ -596,6 +605,7 @@ wayland_output_destroy(struct weston_output *output_base) if (output->frame) frame_destroy(output->frame); + free(output->name); cairo_surface_destroy(output->gl.border.top); cairo_surface_destroy(output->gl.border.left); @@ -1146,6 +1156,11 @@ wayland_output_create_for_parent_output(struct wayland_compositor *c, struct weston_mode *mode; int32_t x; + if(poutput->output) { + weston_log("parent output already exists\n"); + return poutput->output; + } + if (poutput->current_mode) { mode = poutput->current_mode; } else if (poutput->preferred_mode) { @@ -1154,7 +1169,7 @@ wayland_output_create_for_parent_output(struct wayland_compositor *c, mode = container_of(poutput->mode_list.next, struct weston_mode, link); } else { - weston_log("No valid modes found. Skipping output"); + weston_log("No valid modes found. Skipping output\n"); return NULL; } @@ -1172,6 +1187,7 @@ wayland_output_create_for_parent_output(struct wayland_compositor *c, if (!output) return NULL; + poutput->output = output; output->parent.output = poutput->global; output->base.make = poutput->physical.make; @@ -1593,37 +1609,76 @@ static const struct wl_keyboard_listener keyboard_listener = { }; static void -input_handle_capabilities(void *data, struct wl_seat *seat, - enum wl_seat_capability caps) +input_capabilities_updated(struct wayland_input *input) { - struct wayland_input *input = data; - - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->parent.pointer) { - input->parent.pointer = wl_seat_get_pointer(seat); + if ((input->caps & WL_SEAT_CAPABILITY_POINTER) && + !input->parent.pointer) { + input->parent.pointer = wl_seat_get_pointer(input->parent.seat); wl_pointer_set_user_data(input->parent.pointer, input); wl_pointer_add_listener(input->parent.pointer, &pointer_listener, input); weston_seat_init_pointer(&input->base); - } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->parent.pointer) { + } else if (!(input->caps & WL_SEAT_CAPABILITY_POINTER) && + input->parent.pointer) { wl_pointer_destroy(input->parent.pointer); input->parent.pointer = NULL; } - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->parent.keyboard) { - input->parent.keyboard = wl_seat_get_keyboard(seat); + if ((input->caps & WL_SEAT_CAPABILITY_KEYBOARD) && + !input->parent.keyboard) { + input->parent.keyboard = wl_seat_get_keyboard( + input->parent.seat); wl_keyboard_set_user_data(input->parent.keyboard, input); wl_keyboard_add_listener(input->parent.keyboard, &keyboard_listener, input); - } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->parent.keyboard) { + } else if (!(input->caps & WL_SEAT_CAPABILITY_KEYBOARD) && + input->parent.keyboard) { wl_keyboard_destroy(input->parent.keyboard); input->parent.keyboard = NULL; } + input->caps_update_required = 0; +} + +static void +input_handle_capabilities(void *data, struct wl_seat *seat, + enum wl_seat_capability caps) +{ + struct wayland_input *input = data; + + input->caps = caps; + weston_log ("input_handle_capabilities input with seatname %s" + " and caps %d\n", input->base.seat_name, input->caps); + if (input->base.seat_name || !input->compositor->seatfilter) { + input_capabilities_updated (input); + } else { + input->caps_update_required = 1; + } } static void input_handle_name(void *data, struct wl_seat *seat, - const char *name) + const char *name) { + struct wayland_input *input = data; + if (input->compositor->seatfilter && + (!name || !input->compositor->seatname || + strcmp(input->compositor->seatname, name) != 0)) { + weston_log("seatname does not match %s:%s; remove " + "input\n", name, input->compositor->seatname); + wl_seat_destroy(input->parent.seat); + wl_list_remove(&input->link); + free(input); + return; + } + if (!input->initialized) { + weston_log ("initialise input with seat name %s\n", name); + weston_seat_init (&input->base, &input->compositor->base, name); + input->parent.cursor.surface = wl_compositor_create_surface( + input->compositor->parent.compositor); + input->initialized = 1; + } + if (input->caps_update_required) + input_capabilities_updated (input); } static const struct wl_seat_listener seat_listener = { @@ -1640,17 +1695,51 @@ display_add_seat(struct wayland_compositor *c, uint32_t id, uint32_t version) if (input == NULL) return; - weston_seat_init(&input->base, &c->base, "default"); + weston_log ("create input with id %d\n", id); input->compositor = c; - input->parent.seat = wl_registry_bind(c->parent.registry, id, - &wl_seat_interface, MIN(version, 4)); + if (c->seatfilter) + input->parent.seat = wl_registry_bind(c->parent.registry, id, + &wl_seat_interface, + version > 2 ? version : 2); + else + input->parent.seat = wl_registry_bind(c->parent.registry, id, + &wl_seat_interface, MIN(version, 4)); + input->base.seat_name = NULL; + input->initialized = 0; + wl_list_insert(c->input_list.prev, &input->link); wl_seat_add_listener(input->parent.seat, &seat_listener, input); wl_seat_set_user_data(input->parent.seat, input); - input->parent.cursor.surface = - wl_compositor_create_surface(c->parent.compositor); + if (!input->compositor->seatfilter) { + weston_log ("initialise input with seat name %s\n", + c->seatname); + weston_seat_init (&input->base, &input->compositor->base, + c->seatname ? c->seatname : ""); + input->parent.cursor.surface = wl_compositor_create_surface( + c->parent.compositor); + input->initialized = 1; + } +} + +static void +wayland_parent_output_destroy(struct wayland_parent_output *output) +{ + struct weston_mode *mode, *next; + + if (output->output) + wayland_output_destroy(&output->output->base); + + wl_output_destroy(output->global); + free(output->physical.make); + free(output->physical.model); + free(output->seatname); + + wl_list_for_each_safe(mode, next, &output->mode_list, link) { + wl_list_remove(&mode->link); + free(mode); + } } static void @@ -1726,9 +1815,60 @@ wayland_parent_output_mode(void *data, struct wl_output *wl_output_proxy, } } +#if HAVE_MULTISEAT +static void +wayland_parent_output_done(void *data, + struct wl_output *wl_output) +{ + struct wayland_parent_output *output = data; + if (!output->seatname || !output->c || !output->c->seatname || + strcmp(output->c->seatname, output->seatname) != 0) { + weston_log("output seatname (%s) doesnt match with" + " compositor seatname. destroying output\n", + output->seatname); + wayland_parent_output_destroy (output); + wl_list_remove(&output->link); + return; + } + if (output->c->sprawl_across_outputs) { + wayland_output_create_for_parent_output(output->c, output); + } +} + +static void +wayland_parent_output_scale(void *data, + struct wl_output *wl_output, + int32_t scale) +{ +} + +static void +wayland_parent_output_name(void *data, struct wl_output *wl_output_proxy, + const char *name) +{ + weston_log("output name %s\n", name); +} + +static void +wayland_parent_output_seatname(void *data, struct wl_output *wl_output_proxy, + const char *name) +{ + struct wayland_parent_output *poutput = data; + weston_log("output seatname %s\n", name); + poutput->seatname = strdup(name); +} +#endif + static const struct wl_output_listener output_listener = { wayland_parent_output_geometry, wayland_parent_output_mode +#if HAVE_MULTISEAT + , + wayland_parent_output_done, + wayland_parent_output_scale, + wayland_parent_output_name, + wayland_parent_output_seatname +#endif }; static void @@ -1741,13 +1881,21 @@ wayland_compositor_register_output(struct wayland_compositor *c, uint32_t id) return; output->id = id; - output->global = wl_registry_bind(c->parent.registry, id, + + if (c->seatfilter) + output->global = wl_registry_bind(c->parent.registry, id, + &wl_output_interface, 3); + else + output->global = wl_registry_bind(c->parent.registry, id, &wl_output_interface, 1); if (!output->global) { free(output); return; } + output->c = c; + output->seatname = NULL; + output->output = NULL; wl_output_add_listener(output->global, &output_listener, output); output->scale = 0; @@ -1756,27 +1904,9 @@ wayland_compositor_register_output(struct wayland_compositor *c, uint32_t id) wl_list_init(&output->mode_list); wl_list_insert(&c->parent.output_list, &output->link); - if (c->sprawl_across_outputs) { - wl_display_roundtrip(c->parent.wl_display); - wayland_output_create_for_parent_output(c, output); - } -} - -static void -wayland_parent_output_destroy(struct wayland_parent_output *output) -{ - struct weston_mode *mode, *next; - - if (output->output) - wayland_output_destroy(&output->output->base); - - wl_output_destroy(output->global); - free(output->physical.make); - free(output->physical.model); - - wl_list_for_each_safe(mode, next, &output->mode_list, link) { - wl_list_remove(&mode->link); - free(mode); + if (!c->seatfilter && output->c->sprawl_across_outputs) { + wl_display_roundtrip(output->c->parent.wl_display); + wayland_output_create_for_parent_output(output->c, output); } } @@ -1929,7 +2059,8 @@ fullscreen_binding(struct weston_seat *seat_base, uint32_t time, uint32_t key, static struct wayland_compositor * wayland_compositor_create(struct wl_display *display, int use_pixman, const char *display_name, int *argc, char *argv[], - struct weston_config *config) + struct weston_config *config, const char* seatname, + int seatfilter) { struct wayland_compositor *c; struct wl_event_loop *loop; @@ -1938,6 +2069,8 @@ wayland_compositor_create(struct wl_display *display, int use_pixman, c = zalloc(sizeof *c); if (c == NULL) return NULL; + c->seatname = seatname ? strdup(seatname) : NULL; + c->seatfilter = seatfilter; if (weston_compositor_init(&c->base, display, argc, argv, config) < 0) @@ -2008,6 +2141,7 @@ err_display: err_compositor: weston_compositor_shutdown(&c->base); err_free: + free(c->seatname); free(c); return NULL; } @@ -2030,6 +2164,7 @@ wayland_compositor_destroy(struct wayland_compositor *c) wl_cursor_theme_destroy(c->cursor_theme); weston_compositor_shutdown(&c->base); + free(c->seatname); free(c); } @@ -2042,7 +2177,12 @@ backend_init(struct wl_display *display, int *argc, char *argv[], struct wayland_parent_output *poutput; struct weston_config_section *section; int x, count, width, height, scale, use_pixman, fullscreen, sprawl; - const char *section_name, *display_name; +#if HAVE_MULTISEAT + int seatfilter = 1; +#else + int seatfilter = 0; +#endif + const char *section_name, *display_name, *seatname; char *name; const struct weston_option wayland_options[] = { @@ -2067,14 +2207,24 @@ backend_init(struct wl_display *display, int *argc, char *argv[], parse_options(wayland_options, ARRAY_LENGTH(wayland_options), argc, argv); + seatname = getenv("XDG_SEAT"); + if (!seatname && seatfilter) { + weston_log("unable to determine seat for the compositor from" + "XDG_SEAT env. Disabling seat filter\n"); + seatfilter = 0; + } + + weston_log("Multiseat enabled %d\n", seatfilter); c = wayland_compositor_create(display, use_pixman, display_name, - argc, argv, config); + argc, argv, config, seatname, seatfilter); if (!c) return NULL; if (sprawl || c->parent.fshell) { c->sprawl_across_outputs = 1; wl_display_roundtrip(c->parent.wl_display); + if (wl_list_empty(&c->parent.output_list)) + return NULL; wl_list_for_each(poutput, &c->parent.output_list, link) wayland_output_create_for_parent_output(c, poutput); diff --git a/src/compositor.c b/src/compositor.c index a219766..5547ab2 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -56,6 +56,7 @@ #include "compositor.h" #include "scaler-server-protocol.h" #include "../shared/os-compatibility.h" +#include "../shared/str-util.h" #include "git-version.h" #include "version.h" @@ -3190,7 +3191,12 @@ bind_output(struct wl_client *client, struct wl_resource *resource; resource = wl_resource_create(client, &wl_output_interface, - MIN(version, 2), id); +#if HAVE_MULTISEAT + MIN(version, 2), +#else + MIN(version, 3), +#endif + id); if (resource == NULL) { wl_client_post_no_memory(client); return; @@ -3211,6 +3217,14 @@ bind_output(struct wl_client *client, wl_output_send_scale(resource, output->current_scale); +#if HAVE_MULTISEAT + if (version >= WL_OUTPUT_NAME_SINCE_VERSION) + wl_output_send_name(resource, output->name); + + if (version >= WL_OUTPUT_SEATNAME_SINCE_VERSION) + wl_output_send_seatname(resource, output->seat_data.seatname); +#endif + wl_list_for_each (mode, &output->mode_list, link) { wl_output_send_mode(resource, mode->flags, @@ -3259,6 +3273,7 @@ weston_output_destroy(struct weston_output *output) wl_signal_emit(&output->destroy_signal, output); free(output->name); + free(output->seat_data.seatname); pixman_region32_fini(&output->region); pixman_region32_fini(&output->previous_damage); output->compositor->output_id_pool &= ~(1 << output->id); @@ -3442,6 +3457,11 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c, int x, int y, int mm_width, int mm_height, uint32_t transform, int32_t scale) { +#if HAVE_MULTISEAT + const int version = 3; +#else + const int version = 2; +#endif output->compositor = c; output->x = x; output->y = y; @@ -3465,7 +3485,7 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c, output->compositor->output_id_pool |= 1 << output->id; output->global = - wl_global_create(c->wl_display, &wl_output_interface, 2, + wl_global_create(c->wl_display, &wl_output_interface, version, output, bind_output); wl_signal_emit(&c->output_created_signal, output); } @@ -3767,14 +3787,13 @@ log_uname(void) WL_EXPORT int weston_environment_get_fd(const char *env) { - char *e, *end; + char *e; int fd, flags; e = getenv(env); if (!e) return -1; - fd = strtol(e, &end, 0); - if (*end != '\0') + if (!weston_strtoi(e, NULL, 0, &fd)) return -1; flags = fcntl(fd, F_GETFD); @@ -4338,7 +4357,7 @@ int main(int argc, char *argv[]) char *modules = NULL; char *option_modules = NULL; char *log = NULL; - char *server_socket = NULL, *end; + char *server_socket = NULL; int32_t idle_time = 300; int32_t help = 0; char *socket_name = NULL; @@ -4350,6 +4369,7 @@ int main(int argc, char *argv[]) struct wl_client *primary_client; struct wl_listener primary_client_destroyed; struct weston_seat *seat; + const char *conf_file = NULL; const struct weston_option core_options[] = { { WESTON_OPTION_STRING, "backend", 'B', &backend }, @@ -4405,7 +4425,10 @@ int main(int argc, char *argv[]) } if (noconfig == 0) - config = weston_config_parse("weston.ini"); + conf_file = getenv("WESTON_CONFIG"); + if (conf_file == NULL) + conf_file = "weston.ini"; + config = weston_config_parse(conf_file); if (config != NULL) { weston_log("Using config file '%s'\n", weston_config_get_full_path(config)); @@ -4452,8 +4475,7 @@ int main(int argc, char *argv[]) server_socket = getenv("WAYLAND_SERVER_SOCKET"); if (server_socket) { weston_log("Running with single client\n"); - fd = strtol(server_socket, &end, 0); - if (*end != '\0') + if (!weston_strtoi(server_socket, NULL, 0, &fd)) fd = -1; } else { fd = -1; diff --git a/src/compositor.h b/src/compositor.h index ec9b9e5..f7b5823 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -182,6 +182,11 @@ struct weston_output { uint32_t id; char *name; + struct { + char *seatname; + struct weston_seat *seat; + } seat_data; + void *renderer_state; struct wl_list link; @@ -506,8 +511,6 @@ struct weston_seat { int keyboard_device_count; int touch_device_count; - struct weston_output *output; /* constraint */ - struct wl_signal destroy_signal; struct wl_signal updated_caps_signal; diff --git a/src/input.c b/src/input.c index 530904d..2181415 100644 --- a/src/input.c +++ b/src/input.c @@ -840,8 +840,18 @@ WL_EXPORT void weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy) { struct weston_compositor *ec = pointer->seat->compositor; - struct weston_output *output, *prev = NULL; - int x, y, old_x, old_y, valid = 0; + struct weston_output *output, *prev = NULL, *closest = NULL; + int x, y, old_x, old_y; + int distance, min = INT_MAX; + int has_output = 0; + + /* check if any output is attached to the pointer's seat or not */ + wl_list_for_each(output, &ec->output_list, link) { + if (pointer->seat == output->seat_data.seat) { + has_output = 1; + break; + } + } x = wl_fixed_to_int(*fx); y = wl_fixed_to_int(*fy); @@ -849,20 +859,26 @@ weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t old_y = wl_fixed_to_int(pointer->y); wl_list_for_each(output, &ec->output_list, link) { - if (pointer->seat->output && pointer->seat->output != output) + if (has_output && pointer->seat != output->seat_data.seat) continue; if (pixman_region32_contains_point(&output->region, x, y, NULL)) - valid = 1; + return; if (pixman_region32_contains_point(&output->region, old_x, old_y, NULL)) prev = output; + distance = abs(output->x + output->width / 2 - x) + + abs(output->y + output->height / 2 - y); + if (distance < min) { + min = distance; + closest = output; + } } if (!prev) - prev = pointer->seat->output; + prev = closest; - if (prev && !valid) + if (prev) weston_pointer_clamp_for_output(pointer, prev, fx, fy); } @@ -901,7 +917,6 @@ weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data) struct weston_output *output, *closest = NULL; int x, y, distance, min = INT_MAX; wl_fixed_t fx, fy; - pointer = container_of(listener, struct weston_pointer, output_destroy_listener); ec = pointer->seat->compositor; @@ -913,8 +928,7 @@ weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data) if (pixman_region32_contains_point(&output->region, x, y, NULL)) return; - - /* Aproximante the distance from the pointer to the center of + /* Approximate the distance from the pointer to the centre of * the output. */ distance = abs(output->x + output->width / 2 - x) + abs(output->y + output->height / 2 - y); @@ -933,6 +947,7 @@ weston_pointer_handle_output_destroy(struct wl_listener *listener, void *data) weston_pointer_clamp_for_output(pointer, closest, &fx, &fy); weston_pointer_move(pointer, fx, fy); + } WL_EXPORT void diff --git a/src/launcher-util.c b/src/launcher-util.c index fdf4967..14f7c36 100644 --- a/src/launcher-util.c +++ b/src/launcher-util.c @@ -435,10 +435,10 @@ weston_launcher_destroy(struct weston_launcher *launcher) weston_logind_destroy(launcher->logind); } else if (launcher->fd != -1) { close(launcher->fd); - wl_event_source_remove(launcher->source); + if (launcher->source) wl_event_source_remove(launcher->source); } else { weston_launcher_restore(launcher); - wl_event_source_remove(launcher->vt_source); + if (launcher->vt_source) wl_event_source_remove(launcher->vt_source); } if (launcher->tty >= 0) diff --git a/src/libinput-seat.c b/src/libinput-seat.c index ef2d804..4724d54 100644 --- a/src/libinput-seat.c +++ b/src/libinput-seat.c @@ -41,10 +41,21 @@ static const char default_seat_name[] = "default"; static void process_events(struct udev_input *input); static struct udev_seat * -udev_seat_create(struct udev_input *input, const char *seat_name); +udev_seat_create(struct weston_compositor *c, const char *seat_name); static void udev_seat_destroy(struct udev_seat *seat); +static int +udev_seat_has_output(struct udev_seat *seat) +{ + struct weston_output *output; + wl_list_for_each(output, &seat->base.compositor->output_list, link) { + if (seat && (&seat->base == output->seat_data.seat)) + return 1; + } + return 0; +} + static void device_added(struct udev_input *input, struct libinput_device *libinput_device) { @@ -61,7 +72,7 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device) libinput_seat = libinput_device_get_seat(libinput_device); seat_name = libinput_seat_get_logical_name(libinput_seat); - udev_seat = udev_seat_get_named(input, seat_name); + udev_seat = udev_seat_get_named(c, seat_name); if (!udev_seat) return; @@ -70,10 +81,9 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device) if (device == NULL) return; - udev_seat = (struct udev_seat *) seat; wl_list_insert(udev_seat->devices_list.prev, &device->link); - if (seat->output && seat->pointer) + if (udev_seat_has_output(udev_seat) && seat->pointer) weston_pointer_clamp(seat->pointer, &seat->pointer->x, &seat->pointer->y); @@ -92,6 +102,7 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device) if (!input->suspended) weston_seat_repick(seat); + } static void @@ -323,16 +334,50 @@ udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds) evdev_led_update(device, leds); } +static int +udev_seat_is_output_linked(struct udev_seat *seat, struct weston_output *output) +{ + if (seat && output->seat_data.seat && + (&seat->base == output->seat_data.seat)) { + weston_log("output seatname (%s) is linked already with seat\n", + output->seat_data.seatname); + return 1; + } + return 0; +} + +int +udev_seat_link_output(struct udev_seat *seat, struct weston_output *output) +{ + if (udev_seat_is_output_linked(seat, output)) return 1; + + if (!seat || !output || !seat->base.seat_name || + !output->seat_data.seatname || + strcmp(seat->base.seat_name, output->seat_data.seatname) != 0) { + return 0; + } + + free(output->seat_data.seatname); + output->seat_data.seatname = strdup(seat->base.seat_name); + output->seat_data.seat = &seat->base; + weston_log("link output to seat %s\n", seat->base.seat_name); + return 1; +} + static void notify_output_create(struct wl_listener *listener, void *data) { struct udev_seat *seat = container_of(listener, struct udev_seat, output_create_listener); - struct evdev_device *device; + struct evdev_device *device, *next; struct weston_output *output = data; - wl_list_for_each(device, &seat->devices_list, link) { - if (device->output_name && + weston_log("notify received for output created for seat %s\n", + seat->base.seat_name); + udev_seat_link_output(seat, output); + + wl_list_for_each_safe(device, next, &seat->devices_list, link) { + if (device->output_name && output->name && strcmp(output->name, device->output_name) == 0) { evdev_device_set_output(device, output); } @@ -343,9 +388,8 @@ notify_output_create(struct wl_listener *listener, void *data) } static struct udev_seat * -udev_seat_create(struct udev_input *input, const char *seat_name) +udev_seat_create(struct weston_compositor *c, const char *seat_name) { - struct weston_compositor *c = input->compositor; struct udev_seat *seat; seat = zalloc(sizeof *seat); @@ -361,6 +405,7 @@ udev_seat_create(struct udev_input *input, const char *seat_name) wl_list_init(&seat->devices_list); + weston_log("seat created with name %s\n", seat_name); return seat; } @@ -376,14 +421,14 @@ udev_seat_destroy(struct udev_seat *seat) } struct udev_seat * -udev_seat_get_named(struct udev_input *input, const char *seat_name) +udev_seat_get_named(struct weston_compositor *c, const char *seat_name) { struct udev_seat *seat; - wl_list_for_each(seat, &input->compositor->seat_list, base.link) { + wl_list_for_each(seat, &c->seat_list, base.link) { if (strcmp(seat->base.seat_name, seat_name) == 0) return seat; } - return udev_seat_create(input, seat_name); + return udev_seat_create(c, seat_name); } diff --git a/src/libinput-seat.h b/src/libinput-seat.h index c448da0..d2bc54e 100644 --- a/src/libinput-seat.h +++ b/src/libinput-seat.h @@ -30,12 +30,6 @@ #include "compositor.h" -struct udev_seat { - struct weston_seat base; - struct wl_list devices_list; - struct wl_listener output_create_listener; -}; - struct udev_input { struct libinput *libinput; struct wl_event_source *libinput_source; @@ -43,6 +37,13 @@ struct udev_input { int suspended; }; +struct udev_seat { + struct weston_seat base; + struct udev_input input; + struct wl_list devices_list; + struct wl_listener output_create_listener; +}; + int udev_input_enable(struct udev_input *input); void @@ -56,7 +57,10 @@ void udev_input_destroy(struct udev_input *input); struct udev_seat * -udev_seat_get_named(struct udev_input *u, +udev_seat_get_named(struct weston_compositor *c, const char *seat_name); +int udev_seat_link_output(struct udev_seat *seat, + struct weston_output *output); + #endif diff --git a/src/udev-seat.c b/src/udev-seat.c index 8e7405d..4ae8592 100644 --- a/src/udev-seat.c +++ b/src/udev-seat.c @@ -33,12 +33,23 @@ #include "udev-seat.h" static const char default_seat[] = "seat0"; -static const char default_seat_name[] = "default"; +static const char default_seat_name[] = "seat0"; static void udev_seat_destroy(struct udev_seat *seat); static int +udev_seat_has_output(struct udev_seat *seat) +{ + struct weston_output *output; + wl_list_for_each(output, &seat->base.compositor->output_list, link) { + if (seat && (&seat->base == output->seat_data.seat)) + return 1; + } + return 0; +} + +static int device_added(struct udev_device *udev_device, struct udev_input *input) { struct weston_compositor *c; @@ -65,7 +76,7 @@ device_added(struct udev_device *udev_device, struct udev_input *input) if (!seat_name) seat_name = default_seat_name; - seat = udev_seat_get_named(input, seat_name); + seat = udev_seat_get_named(c, seat_name); if (seat == NULL) return -1; @@ -114,7 +125,7 @@ device_added(struct udev_device *udev_device, struct udev_input *input) wl_list_insert(seat->devices_list.prev, &device->link); - if (seat->base.output && seat->base.pointer) + if (udev_seat_has_output(seat) && seat->base.pointer) weston_pointer_clamp(seat->base.pointer, &seat->base.pointer->x, &seat->base.pointer->y); @@ -134,6 +145,8 @@ device_added(struct udev_device *udev_device, struct udev_input *input) if (input->enabled == 1) weston_seat_repick(&seat->base); + weston_log("device with path %s is added to seat %s\n", devnode, + input->seat_id); return 0; } @@ -316,7 +329,6 @@ udev_input_init(struct udev_input *input, struct weston_compositor *c, struct ud memset(input, 0, sizeof *input); input->seat_id = strdup(seat_id); input->compositor = c; - input->udev = udev; input->udev = udev_ref(udev); if (udev_input_enable(input) < 0) goto err; @@ -324,7 +336,6 @@ udev_input_init(struct udev_input *input, struct weston_compositor *c, struct ud return 0; err: - free(input->seat_id); return -1; } @@ -343,22 +354,57 @@ static void drm_led_update(struct weston_seat *seat_base, enum weston_led leds) { struct udev_seat *seat = (struct udev_seat *) seat_base; - struct evdev_device *device; + struct evdev_device *device, *next; - wl_list_for_each(device, &seat->devices_list, link) + wl_list_for_each_safe(device, next, &seat->devices_list, link) evdev_led_update(device, leds); } +static int +udev_seat_is_output_linked(struct udev_seat *seat, struct weston_output *output) +{ + if (seat && output->seat_data.seat && + (&seat->base == output->seat_data.seat)) { + weston_log("output seatname (%s) is linked already with seat\n", + output->seat_data.seatname); + return 1; + } + return 0; +} + +int +udev_seat_link_output(struct udev_seat *seat, struct weston_output *output) +{ + if (udev_seat_is_output_linked(seat, output)) return 1; + + if (!seat || !output || !seat->base.seat_name || + !output->seat_data.seatname || + strcmp(seat->base.seat_name, output->seat_data.seatname) != 0) { + return 0; + } + + weston_log("link output to seat %s\n", seat->base.seat_name); + free(output->seat_data.seatname); + output->seat_data.seatname = strdup(seat->base.seat_name); + output->seat_data.seat = &seat->base; + return 1; +} + static void notify_output_create(struct wl_listener *listener, void *data) { struct udev_seat *seat = container_of(listener, struct udev_seat, output_create_listener); - struct evdev_device *device; + struct evdev_device *device, *next; struct weston_output *output = data; - wl_list_for_each(device, &seat->devices_list, link) { - if (device->output_name && + weston_log("notify received for output created for seat %s\n", + seat->base.seat_name); + if (!udev_seat_link_output(seat, output)) + return; + + wl_list_for_each_safe(device, next, &seat->devices_list, link) { + if (device->output_name && output->name && strcmp(output->name, device->output_name) == 0) { evdev_device_set_output(device, output); } @@ -369,9 +415,8 @@ notify_output_create(struct wl_listener *listener, void *data) } static struct udev_seat * -udev_seat_create(struct udev_input *input, const char *seat_name) +udev_seat_create(struct weston_compositor *c, const char *seat_name) { - struct weston_compositor *c = input->compositor; struct udev_seat *seat; seat = zalloc(sizeof *seat); @@ -386,29 +431,31 @@ udev_seat_create(struct udev_input *input, const char *seat_name) &seat->output_create_listener); wl_list_init(&seat->devices_list); + weston_log("created seat with name %s\n", seat_name); + return seat; } static void udev_seat_destroy(struct udev_seat *seat) { + weston_log("seat destroyed with name %s\n", seat->base.seat_name); weston_seat_release(&seat->base); wl_list_remove(&seat->output_create_listener.link); free(seat); } struct udev_seat * -udev_seat_get_named(struct udev_input *input, const char *seat_name) +udev_seat_get_named(struct weston_compositor *c, const char *seat_name) { - struct weston_compositor *c = input->compositor; - struct udev_seat *seat; + struct udev_seat *seat, *next; - wl_list_for_each(seat, &c->seat_list, base.link) { + wl_list_for_each_safe(seat, next, &c->seat_list, base.link) { if (strcmp(seat->base.seat_name, seat_name) == 0) return seat; } - seat = udev_seat_create(input, seat_name); + seat = udev_seat_create(c, seat_name); if (!seat) return NULL; diff --git a/src/udev-seat.h b/src/udev-seat.h index e388f13..5227afe 100644 --- a/src/udev-seat.h +++ b/src/udev-seat.h @@ -29,12 +29,6 @@ #include "compositor.h" -struct udev_seat { - struct weston_seat base; - struct wl_list devices_list; - struct wl_listener output_create_listener; -}; - struct udev_input { struct udev *udev; struct udev_monitor *udev_monitor; @@ -44,6 +38,13 @@ struct udev_input { int enabled; }; +struct udev_seat { + struct weston_seat base; + struct udev_input input; + struct wl_list devices_list; + struct wl_listener output_create_listener; +}; + int udev_input_enable(struct udev_input *input); void udev_input_disable(struct udev_input *input); int udev_input_init(struct udev_input *input, @@ -52,6 +53,10 @@ int udev_input_init(struct udev_input *input, const char *seat_id); void udev_input_destroy(struct udev_input *input); -struct udev_seat *udev_seat_get_named(struct udev_input *input, +struct udev_seat *udev_seat_get_named(struct weston_compositor *c, const char *seat_name); + +int udev_seat_link_output(struct udev_seat *seat, + struct weston_output *output); + #endif -- 2.7.4