evdev: Reference count input device's seat capabilities
authorJonas Ådahl <jadahl@gmail.com>
Thu, 17 Oct 2013 21:04:05 +0000 (23:04 +0200)
committerKristian Høgsberg <krh@bitplanet.net>
Mon, 21 Oct 2013 20:45:03 +0000 (13:45 -0700)
When the only input device of a certain seat capability is unplugged,
stop advertising the capability.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
src/compositor.h
src/evdev.c
src/evdev.h
src/input.c

index d8a6a73..5ed348b 100644 (file)
@@ -461,6 +461,9 @@ struct weston_seat {
        struct weston_pointer *pointer;
        struct weston_keyboard *keyboard;
        struct weston_touch *touch;
+       int pointer_device_count;
+       int keyboard_device_count;
+       int touch_device_count;
 
        struct weston_output *output; /* constraint */
 
@@ -1124,11 +1127,17 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
                 const char *seat_name);
 void
 weston_seat_init_pointer(struct weston_seat *seat);
+void
+weston_seat_release_pointer(struct weston_seat *seat);
 int
 weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap);
 void
+weston_seat_release_keyboard(struct weston_seat *seat);
+void
 weston_seat_init_touch(struct weston_seat *seat);
 void
+weston_seat_release_touch(struct weston_seat *seat);
+void
 weston_seat_repick(struct weston_seat *seat);
 
 void
index 7397ea1..eb7631a 100644 (file)
@@ -565,6 +565,7 @@ evdev_configure_device(struct evdev_device *device)
        if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) &&
            (device->caps & EVDEV_BUTTON)) {
                weston_seat_init_pointer(device->seat);
+               device->seat_caps |= EVDEV_SEAT_POINTER;
                weston_log("input device %s, %s is a pointer caps =%s%s%s\n",
                           device->devname, device->devnode,
                           device->caps & EVDEV_MOTION_ABS ? " absolute-motion" : "",
@@ -574,11 +575,13 @@ evdev_configure_device(struct evdev_device *device)
        if ((device->caps & EVDEV_KEYBOARD)) {
                if (weston_seat_init_keyboard(device->seat, NULL) < 0)
                        return -1;
+               device->seat_caps |= EVDEV_SEAT_KEYBOARD;
                weston_log("input device %s, %s is a keyboard\n",
                           device->devname, device->devnode);
        }
        if ((device->caps & EVDEV_TOUCH)) {
                weston_seat_init_touch(device->seat);
+               device->seat_caps |= EVDEV_SEAT_TOUCH;
                weston_log("input device %s, %s is a touch device\n",
                           device->devname, device->devnode);
        }
@@ -602,6 +605,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd)
                container_of(ec->output_list.next, struct weston_output, link);
 
        device->seat = seat;
+       device->seat_caps = 0;
        device->is_mt = 0;
        device->mtdev = NULL;
        device->devnode = strdup(path);
@@ -649,6 +653,13 @@ evdev_device_destroy(struct evdev_device *device)
 {
        struct evdev_dispatch *dispatch;
 
+       if (device->seat_caps & EVDEV_SEAT_POINTER)
+               weston_seat_release_pointer(device->seat);
+       if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
+               weston_seat_release_keyboard(device->seat);
+       if (device->seat_caps & EVDEV_SEAT_TOUCH)
+               weston_seat_release_touch(device->seat);
+
        dispatch = device->dispatch;
        if (dispatch)
                dispatch->interface->destroy(dispatch);
index 5e4d11a..e146d1a 100644 (file)
@@ -49,6 +49,12 @@ enum evdev_device_capability {
        EVDEV_TOUCH = (1 << 4),
 };
 
+enum evdev_device_seat_capability {
+       EVDEV_SEAT_POINTER = (1 << 0),
+       EVDEV_SEAT_KEYBOARD = (1 << 1),
+       EVDEV_SEAT_TOUCH = (1 << 2)
+};
+
 struct evdev_device {
        struct weston_seat *seat;
        struct wl_list link;
@@ -80,6 +86,7 @@ struct evdev_device {
 
        enum evdev_event_type pending_event;
        enum evdev_device_capability caps;
+       enum evdev_device_seat_capability seat_caps;
 
        int is_mt;
 };
index cd2d3bc..d1acd92 100644 (file)
@@ -447,11 +447,11 @@ seat_send_updated_caps(struct weston_seat *seat)
        enum wl_seat_capability caps = 0;
        struct wl_resource *resource;
 
-       if (seat->pointer)
+       if (seat->pointer_device_count > 0)
                caps |= WL_SEAT_CAPABILITY_POINTER;
-       if (seat->keyboard)
+       if (seat->keyboard_device_count > 0)
                caps |= WL_SEAT_CAPABILITY_KEYBOARD;
-       if (seat->touch)
+       if (seat->touch_device_count > 0)
                caps |= WL_SEAT_CAPABILITY_TOUCH;
 
        wl_resource_for_each(resource, &seat->base_resource_list) {
@@ -1630,8 +1630,12 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
 {
        struct weston_keyboard *keyboard;
 
-       if (seat->keyboard)
+       if (seat->keyboard) {
+               seat->keyboard_device_count += 1;
+               if (seat->keyboard_device_count == 1)
+                       seat_send_updated_caps(seat);
                return 0;
+       }
 
 #ifdef ENABLE_XKBCOMMON
        if (seat->compositor->use_xkbcommon) {
@@ -1663,6 +1667,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
        }
 
        seat->keyboard = keyboard;
+       seat->keyboard_device_count = 1;
        keyboard->seat = seat;
 
        seat_send_updated_caps(seat);
@@ -1671,42 +1676,81 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap)
 }
 
 WL_EXPORT void
+weston_seat_release_keyboard(struct weston_seat *seat)
+{
+       seat->keyboard_device_count--;
+       if (seat->keyboard_device_count == 0) {
+               seat_send_updated_caps(seat);
+       }
+}
+
+WL_EXPORT void
 weston_seat_init_pointer(struct weston_seat *seat)
 {
        struct weston_pointer *pointer;
 
-       if (seat->pointer)
+       if (seat->pointer) {
+               seat->pointer_device_count += 1;
+               if (seat->pointer_device_count == 1)
+                       seat_send_updated_caps(seat);
                return;
+       }
 
        pointer = weston_pointer_create();
        if (pointer == NULL)
                return;
 
        seat->pointer = pointer;
-               pointer->seat = seat;
+       seat->pointer_device_count = 1;
+       pointer->seat = seat;
 
        seat_send_updated_caps(seat);
 }
 
 WL_EXPORT void
+weston_seat_release_pointer(struct weston_seat *seat)
+{
+       struct weston_pointer *pointer = seat->pointer;
+
+       seat->pointer_device_count--;
+       if (seat->pointer_device_count == 0) {
+               seat_send_updated_caps(seat);
+       }
+}
+
+WL_EXPORT void
 weston_seat_init_touch(struct weston_seat *seat)
 {
        struct weston_touch *touch;
 
-       if (seat->touch)
+       if (seat->touch) {
+               seat->touch_device_count += 1;
+               if (seat->touch_device_count == 1)
+                       seat_send_updated_caps(seat);
                return;
+       }
 
        touch = weston_touch_create();
        if (touch == NULL)
                return;
 
        seat->touch = touch;
+       seat->touch_device_count = 1;
        touch->seat = seat;
 
        seat_send_updated_caps(seat);
 }
 
 WL_EXPORT void
+weston_seat_release_touch(struct weston_seat *seat)
+{
+       seat->touch_device_count--;
+       if (seat->touch_device_count == 0) {
+               seat_send_updated_caps(seat);
+       }
+}
+
+WL_EXPORT void
 weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
                 const char *seat_name)
 {