[PATCH weston 4/4] input: Detect keyboard capabilities
Derek Foreman
derekf at osg.samsung.com
Tue May 5 13:01:54 PDT 2015
Some devices (power buttons, acpi video bus driver) are considered
keyboards but you can't type with them.
As of libinput 0.15 we can query a keyboard to see which key events it
can generate. We use this to detect if a keyboard can type letters or
digits.
The wayland protocol doesn't propagate these capabilites, so
weston_seat_send_dirty_caps() will differentiate between dirty keyboards
(which generate the weston signal) and dirty seats (which generate a
wayland event) and only send the appropriate updates.
Functions are provided for backends that don't use libinput to force these
capabilities to a sensible state.
Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---
configure.ac | 2 +-
src/compositor-headless.c | 1 +
src/compositor-rdp.c | 1 +
src/compositor-wayland.c | 1 +
src/compositor-x11.c | 1 +
src/compositor.h | 8 ++++++++
src/input.c | 29 +++++++++++++++++++++++++++--
src/libinput-device.c | 32 +++++++++++++++++++++++++++++++-
src/libinput-device.h | 4 +++-
src/libinput-seat.c | 27 +++++++++++++++++++++++++++
src/screen-share.c | 1 +
11 files changed, 102 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index d9d8d8f..4e9ae20 100644
--- a/configure.ac
+++ b/configure.ac
@@ -155,7 +155,7 @@ if test x$enable_drm_compositor = xyes; then
fi
-PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0])
+PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.15.0])
PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES])
AC_ARG_ENABLE(wayland-compositor, [ --enable-wayland-compositor],,
diff --git a/src/compositor-headless.c b/src/compositor-headless.c
index 0ddb26e..0b461c6 100644
--- a/src/compositor-headless.c
+++ b/src/compositor-headless.c
@@ -184,6 +184,7 @@ headless_input_create(struct headless_compositor *c)
if (weston_seat_init_keyboard(&c->fake_seat, NULL) < 0)
return -1;
+ weston_seat_override_keyboard_caps(&c->fake_seat, true, true);
weston_seat_send_dirty_caps(&c->fake_seat);
return 0;
diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c
index 5b50382..b6e3876 100644
--- a/src/compositor-rdp.c
+++ b/src/compositor-rdp.c
@@ -842,6 +842,7 @@ xf_peer_post_connect(freerdp_peer* client)
}
weston_seat_init_keyboard(&peerCtx->item.seat, keymap);
weston_seat_init_pointer(&peerCtx->item.seat);
+ weston_seat_override_keyboard_caps(&peerCtx->item.seat, true, true);
weston_seat_send_dirty_caps(&peerCtx->item.seat);
peerCtx->item.flags |= RDP_PEER_ACTIVATED;
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index 53159c4..1e33697 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -1463,6 +1463,7 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format,
else
weston_seat_init_keyboard(&input->base, keymap);
+ weston_seat_override_keyboard_caps(&input->base, true, true);
weston_seat_send_dirty_caps(&input->base);
xkb_keymap_unref(keymap);
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 4a3b10e..69e3a14 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -336,6 +336,7 @@ x11_input_create(struct x11_compositor *c, int no_input)
return -1;
xkb_keymap_unref(keymap);
+ weston_seat_override_keyboard_caps(&c->core_seat, true, true);
weston_seat_send_dirty_caps(&c->core_seat);
x11_compositor_setup_xkb(c);
diff --git a/src/compositor.h b/src/compositor.h
index e05b262..da6d126 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -451,6 +451,10 @@ weston_touch_start_drag(struct weston_touch *touch,
struct wl_client *client);
void
weston_seat_send_dirty_caps(struct weston_seat *seat);
+void
+weston_seat_override_keyboard_caps(struct weston_seat *seat,
+ bool has_letters,
+ bool has_digits);
struct weston_xkb_info {
struct xkb_keymap *keymap;
@@ -505,6 +509,10 @@ struct weston_keyboard {
enum weston_led leds;
} xkb_state;
struct xkb_keymap *pending_keymap;
+
+ bool has_digits;
+ bool has_letters;
+ bool caps_dirty;
};
struct weston_seat {
diff --git a/src/input.c b/src/input.c
index c37bd20..3a0adc3 100644
--- a/src/input.c
+++ b/src/input.c
@@ -601,14 +601,16 @@ weston_touch_destroy(struct weston_touch *touch)
/* Send seat capability updates if necessary
*
- * Checks if the seat capabilities (WL_SEAT_CAPABILITY_*) have changed
- * and propagates updates appropriately.
+ * Checks if the seat capabilities (WL_SEAT_CAPABILITY_*) or the keyboard
+ * capabilities (has_digits, has_letters) have changed and propagates
+ * updates appropriately.
*
* \param seat These seat to send capabilities changes for
*/
WL_EXPORT void
weston_seat_send_dirty_caps(struct weston_seat *seat)
{
+ struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
enum wl_seat_capability caps = 0;
struct wl_resource *resource;
@@ -622,8 +624,15 @@ weston_seat_send_dirty_caps(struct weston_seat *seat)
wl_resource_for_each(resource, &seat->base_resource_list)
wl_seat_send_capabilities(resource, caps);
+ }
+
+ if (seat->caps_dirty || (keyboard && keyboard->caps_dirty)) {
wl_signal_emit(&seat->updated_caps_signal, seat);
}
+
+ if (keyboard)
+ keyboard->caps_dirty = false;
+
seat->caps_dirty = false;
}
@@ -2230,6 +2239,22 @@ weston_seat_release_keyboard(struct weston_seat *seat)
}
}
+void
+weston_seat_override_keyboard_caps(struct weston_seat *seat,
+ bool has_letters,
+ bool has_digits)
+{
+ struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
+
+ if (!keyboard)
+ return;
+
+ keyboard->caps_dirty = has_digits ^ keyboard->has_digits ||
+ has_letters ^ keyboard->has_letters;
+ keyboard->has_digits = has_digits;
+ keyboard->has_letters = has_letters;
+}
+
WL_EXPORT void
weston_seat_init_pointer(struct weston_seat *seat)
{
diff --git a/src/libinput-device.c b/src/libinput-device.c
index 3fb507f..983665c 100644
--- a/src/libinput-device.c
+++ b/src/libinput-device.c
@@ -480,6 +480,36 @@ configure_device(struct evdev_device *device)
evdev_device_set_calibration(device);
}
+static enum evdev_device_seat_capability
+keyboard_caps(struct libinput_device *dev)
+{
+ bool letters = true, digits = true;
+ uint32_t alpha_keys[] = {
+ KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F,
+ KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
+ KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R,
+ KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X,
+ KEY_Y, KEY_Z, KEY_RESERVED
+ };
+ uint32_t digit_keys[] = {
+ KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6,
+ KEY_7, KEY_8, KEY_9, KEY_0, KEY_RESERVED
+ };
+ int i;
+
+ for (i = 0; letters && alpha_keys[i] != KEY_RESERVED; i++)
+ letters &= libinput_device_keyboard_has_key(dev,
+ alpha_keys[i]);
+
+ for (i = 0; digits && digit_keys[i] != KEY_RESERVED; i++)
+ digits &= libinput_device_keyboard_has_key(dev,
+ digit_keys[i]);
+
+ return EVDEV_SEAT_KEYBOARD |
+ (letters ? EVDEV_SEAT_KEYBOARD_LETTERS : 0) |
+ (digits ? EVDEV_SEAT_KEYBOARD_DIGITS : 0);
+}
+
struct evdev_device *
evdev_device_create(struct libinput_device *libinput_device,
struct weston_seat *seat)
@@ -497,7 +527,7 @@ evdev_device_create(struct libinput_device *libinput_device,
if (libinput_device_has_capability(libinput_device,
LIBINPUT_DEVICE_CAP_KEYBOARD)) {
weston_seat_init_keyboard(seat, NULL);
- device->seat_caps |= EVDEV_SEAT_KEYBOARD;
+ device->seat_caps |= keyboard_caps(libinput_device);
}
if (libinput_device_has_capability(libinput_device,
LIBINPUT_DEVICE_CAP_POINTER)) {
diff --git a/src/libinput-device.h b/src/libinput-device.h
index 0775743..70591c2 100644
--- a/src/libinput-device.h
+++ b/src/libinput-device.h
@@ -34,7 +34,9 @@
enum evdev_device_seat_capability {
EVDEV_SEAT_POINTER = (1 << 0),
EVDEV_SEAT_KEYBOARD = (1 << 1),
- EVDEV_SEAT_TOUCH = (1 << 2)
+ EVDEV_SEAT_TOUCH = (1 << 2),
+ EVDEV_SEAT_KEYBOARD_DIGITS = (1 << 3),
+ EVDEV_SEAT_KEYBOARD_LETTERS = (1 << 4)
};
struct evdev_device {
diff --git a/src/libinput-seat.c b/src/libinput-seat.c
index f0fcd51..af695a6 100644
--- a/src/libinput-seat.c
+++ b/src/libinput-seat.c
@@ -45,6 +45,30 @@ udev_seat_create(struct udev_input *input, const char *seat_name);
static void
udev_seat_destroy(struct udev_seat *seat);
+static void
+seat_rescan_keyboard_caps(struct udev_seat *udev_seat)
+{
+ struct evdev_device *dev;
+ struct weston_seat *weston_seat = &udev_seat->base;
+ struct weston_keyboard *keyboard = weston_seat->keyboard_resource;
+ bool has_letters = false, has_digits = false;
+
+ keyboard = weston_seat_get_keyboard(weston_seat);
+ if (!keyboard)
+ return;
+
+ wl_list_for_each(dev, &udev_seat->devices_list, link) {
+ has_letters = has_letters || (dev->seat_caps & EVDEV_SEAT_KEYBOARD_LETTERS);
+ has_digits = has_digits || (dev->seat_caps & EVDEV_SEAT_KEYBOARD_DIGITS);
+ }
+
+ if (has_letters != keyboard->has_letters || has_digits != keyboard->has_digits) {
+ keyboard->has_letters = has_letters;
+ keyboard->has_digits = has_digits;
+ keyboard->caps_dirty = true;
+ }
+}
+
static struct udev_seat *
get_udev_seat(struct udev_input *input, struct libinput_device *device)
{
@@ -81,6 +105,8 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device)
udev_seat = (struct udev_seat *) seat;
wl_list_insert(udev_seat->devices_list.prev, &device->link);
+ seat_rescan_keyboard_caps(udev_seat);
+
pointer = weston_seat_get_pointer(seat);
if (seat->output && pointer)
weston_pointer_clamp(pointer,
@@ -117,6 +143,7 @@ device_removed(struct udev_input *input, struct libinput_device *libinput_device
device = libinput_device_get_user_data(libinput_device);
evdev_device_destroy(device);
+ seat_rescan_keyboard_caps(udev_seat);
weston_seat_send_dirty_caps(&udev_seat->base);
}
diff --git a/src/screen-share.c b/src/screen-share.c
index 597ad9b..3e92d61 100644
--- a/src/screen-share.c
+++ b/src/screen-share.c
@@ -214,6 +214,7 @@ ss_seat_handle_keymap(void *data, struct wl_keyboard *keyboard,
else
weston_seat_init_keyboard(&seat->base, keymap);
+ weston_seat_override_keyboard_caps(&seat->base, true, true);
weston_seat_send_dirty_caps(&seat->base);
xkb_keymap_unref(keymap);
--
2.1.4
More information about the wayland-devel
mailing list