Multiseat support for drm/wayland backends 52/30652/2 accepted/tizen/common/20141126.172851 accepted/tizen/mobile/20141128.015213 submit/tizen/20141126.141815
authorImran Zaman <imran.zaman@intel.com>
Tue, 18 Nov 2014 15:03:42 +0000 (17:03 +0200)
committerImran Zaman <imran.zaman@intel.com>
Wed, 26 Nov 2014 13:32:16 +0000 (15:32 +0200)
Change-Id: I04f04df98c2f76cf09b5d4d14867f918919aeb15
Signed-off-by: Imran Zaman <imran.zaman@intel.com>
14 files changed:
configure.ac
fullscreen-shell/fullscreen-shell.c
packaging/weston.spec
src/compositor-drm.c
src/compositor-rdp.c
src/compositor-wayland.c
src/compositor.c
src/compositor.h
src/input.c
src/launcher-util.c
src/libinput-seat.c
src/libinput-seat.h
src/udev-seat.c
src/udev-seat.h

index abaa945..d2b125e 100644 (file)
@@ -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
index 25932d4..57ef641 100644 (file)
 #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,
index 428b37b..9781f10 100644 (file)
 %define extra_config_options3 --enable-sys-uid
 %endif
 
+%if "%{profile}" == "ivi"
+%define extra_config_options4 --enable-multiseat
+%endif
+
 Name:           weston
 Version:        1.6.0
 Release:        0
@@ -25,8 +29,7 @@ Url:            http://weston.freedesktop.org/
 #Git-Clone:    git://anongit.freedesktop.org/wayland/weston
 #Git-Web:      http://cgit.freedesktop.org/wayland/weston/
 Source0:        %name-%version.tar.xz
-Source1:        %name.target
-Source1001:    %name.manifest
+Source1001:     %name.manifest
 BuildRequires: autoconf >= 2.64, automake >= 1.11
 BuildRequires:  expat-devel
 BuildRequires:  libjpeg-devel
@@ -121,7 +124,8 @@ cp %{SOURCE1001} .
          --with-cairo=glesv2 \
          %{?extra_config_options1:%extra_config_options1} \
          %{?extra_config_options2:%extra_config_options2} \
-         %{?extra_config_options3:%extra_config_options3}
+         %{?extra_config_options3:%extra_config_options3} \
+         %{?extra_config_options4:%extra_config_options4}
 
 make %{?_smp_mflags}
 
@@ -152,8 +156,6 @@ install -m 755 weston-transformed %{buildroot}%{_bindir}
 install -m 755 weston-fullscreen %{buildroot}%{_bindir}
 
 
-install -d %{buildroot}%{_unitdir_user}
-install -m 644 %{SOURCE1} %{buildroot}%{_unitdir_user}/weston.target
 # The weston.service unit file must be provided by the weston-startup
 # virtual package, i.e. "Provide: weston-startup".  The weston-startup
 # virtual package requirement is intended to force Tizen profile
@@ -188,7 +190,6 @@ getent group weston-launch >/dev/null || %{_sbindir}/groupadd -o -r weston-launc
 %{_libdir}/weston/wayland-backend.so
 %{_libdir}/weston/gl-renderer.so
 %{_datadir}/weston
-%{_unitdir_user}/weston.target
 
 %files devel
 %manifest %{name}.manifest
index 6732c1b..d558f7d 100644 (file)
@@ -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;
 }
index 6af37b0..df66738 100644 (file)
@@ -46,6 +46,7 @@
 #include <winpr/input.h>
 
 #include "compositor.h"
+#include "../shared/str-util.h"
 #include "pixman-renderer.h"
 
 #define MAX_FREERDP_FDS 32
index 5f73c78..3b0dd83 100644 (file)
@@ -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);
index a219766..5547ab2 100644 (file)
@@ -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;
index ec9b9e5..f7b5823 100644 (file)
@@ -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;
 
index 530904d..2181415 100644 (file)
@@ -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
index fdf4967..14f7c36 100644 (file)
@@ -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)
index ef2d804..4724d54 100644 (file)
@@ -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);
 }
index c448da0..d2bc54e 100644 (file)
 
 #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
index 8e7405d..4ae8592 100644 (file)
 #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;
index e388f13..5227afe 100644 (file)
 
 #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