[PATCH weston 1/4] evdev: Reference count input device's seat capabilities

Jonas Ådahl jadahl at gmail.com
Thu Oct 17 23:04:05 CEST 2013


When the only input device of a certain seat capability is unplugged,
stop advertising the capability.

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
 src/compositor.h |  9 +++++++++
 src/evdev.c      | 11 +++++++++++
 src/evdev.h      |  7 +++++++
 src/input.c      | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 4 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/src/compositor.h b/src/compositor.h
index a19d966..8ce2229 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -460,6 +460,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 */
 
@@ -1109,11 +1112,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
diff --git a/src/evdev.c b/src/evdev.c
index 48e5470..89015f5 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -558,6 +558,7 @@ evdev_configure_device(struct evdev_device *device)
 	if ((device->caps &
 	     (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | 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" : "",
@@ -567,11 +568,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);
 	}
@@ -595,6 +598,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);
@@ -642,6 +646,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);
diff --git a/src/evdev.h b/src/evdev.h
index 5e4d11a..e146d1a 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -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;
 };
diff --git a/src/input.c b/src/input.c
index 1313b52..a5cad7c 100644
--- a/src/input.c
+++ b/src/input.c
@@ -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) {
@@ -1628,8 +1628,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) {
@@ -1661,6 +1665,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);
@@ -1669,42 +1674,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)
 {
-- 
1.8.1.2



More information about the wayland-devel mailing list