summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2016-07-04 10:26:03 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2016-07-04 10:26:03 +1000
commit35a6ebc5369ec907a3745f61ef8a8e5b2ba6e065 (patch)
treeb0739817621199dc4b89f78a5746bb8de9e150a3 /src
parent0526044f6d4ebb614699d87f23de3d3256a568ff (diff)
parent30bc86f47e17a78bcb83410cf6a4da77d7a7af32 (diff)
Merge branch 'wip/tablet-pad-modes-v3'
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/evdev-tablet-pad-leds.c177
-rw-r--r--src/evdev-tablet-pad.c76
-rw-r--r--src/evdev-tablet-pad.h12
-rw-r--r--src/evdev.h16
-rw-r--r--src/libinput-private.h28
-rw-r--r--src/libinput-util.h21
-rw-r--r--src/libinput.c181
-rw-r--r--src/libinput.h576
-rw-r--r--src/libinput.sym15
10 files changed, 952 insertions, 151 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 39c22c21..48e704a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,6 +22,7 @@ libinput_la_SOURCES = \
evdev-tablet.h \
evdev-tablet-pad.c \
evdev-tablet-pad.h \
+ evdev-tablet-pad-leds.c \
filter.c \
filter.h \
filter-private.h \
diff --git a/src/evdev-tablet-pad-leds.c b/src/evdev-tablet-pad-leds.c
new file mode 100644
index 00000000..8b162a61
--- /dev/null
+++ b/src/evdev-tablet-pad-leds.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "evdev-tablet-pad.h"
+
+struct pad_led_group {
+ struct libinput_tablet_pad_mode_group base;
+};
+
+static void
+pad_led_group_destroy(struct libinput_tablet_pad_mode_group *g)
+{
+ struct pad_led_group *group = (struct pad_led_group *)g;
+
+ free(group);
+}
+
+static struct pad_led_group *
+pad_group_new_basic(struct pad_dispatch *pad,
+ unsigned int group_index,
+ int nleds)
+{
+ struct pad_led_group *group;
+
+ group = zalloc(sizeof *group);
+ if (!group)
+ return NULL;
+
+ group->base.device = &pad->device->base;
+ group->base.refcount = 1;
+ group->base.index = group_index;
+ group->base.current_mode = 0;
+ group->base.num_modes = nleds;
+ group->base.destroy = pad_led_group_destroy;
+
+ return group;
+}
+
+static inline struct libinput_tablet_pad_mode_group *
+pad_get_mode_group(struct pad_dispatch *pad, unsigned int index)
+{
+ struct libinput_tablet_pad_mode_group *group;
+
+ list_for_each(group, &pad->modes.mode_group_list, link) {
+ if (group->index == index)
+ return group;
+ }
+
+ return NULL;
+}
+
+static int
+pad_init_fallback_group(struct pad_dispatch *pad)
+{
+ struct pad_led_group *group;
+
+ group = pad_group_new_basic(pad, 0, 1);
+ if (!group)
+ return 1;
+
+ /* If we only have one group, all buttons/strips/rings are part of
+ * that group. We rely on the other layers to filter out invalid
+ * indices */
+ group->base.button_mask = -1;
+ group->base.strip_mask = -1;
+ group->base.ring_mask = -1;
+ group->base.toggle_button_mask = 0;
+
+ list_insert(&pad->modes.mode_group_list, &group->base.link);
+
+ return 0;
+}
+
+int
+pad_init_leds(struct pad_dispatch *pad,
+ struct evdev_device *device)
+{
+ int rc = 1;
+
+ list_init(&pad->modes.mode_group_list);
+
+ if (pad->nbuttons > 32) {
+ log_bug_libinput(device->base.seat->libinput,
+ "Too many pad buttons for modes %d\n",
+ pad->nbuttons);
+ return rc;
+ }
+
+ /* Eventually we slot the libwacom-based led detection in here. That
+ * requires getting the kernel ready first. For now we just init the
+ * fallback single-mode group.
+ */
+ rc = pad_init_fallback_group(pad);
+
+ return rc;
+}
+
+void
+pad_destroy_leds(struct pad_dispatch *pad)
+{
+ struct libinput_tablet_pad_mode_group *group, *tmpgrp;
+
+ list_for_each_safe(group, tmpgrp, &pad->modes.mode_group_list, link)
+ libinput_tablet_pad_mode_group_unref(group);
+}
+
+void
+pad_button_update_mode(struct libinput_tablet_pad_mode_group *g,
+ unsigned int button_index,
+ enum libinput_button_state state)
+{
+ struct pad_led_group *group = (struct pad_led_group*)g;
+
+ if (state != LIBINPUT_BUTTON_STATE_PRESSED)
+ return;
+
+ if (!libinput_tablet_pad_mode_group_button_is_toggle(g, button_index))
+ return;
+
+ log_bug_libinput(group->base.device->seat->libinput,
+ "Button %d should not be a toggle button",
+ button_index);
+}
+
+int
+evdev_device_tablet_pad_get_num_mode_groups(struct evdev_device *device)
+{
+ struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
+ struct libinput_tablet_pad_mode_group *group;
+ int num_groups = 0;
+
+ if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
+ return -1;
+
+ list_for_each(group, &pad->modes.mode_group_list, link)
+ num_groups++;
+
+ return num_groups;
+}
+
+struct libinput_tablet_pad_mode_group *
+evdev_device_tablet_pad_get_mode_group(struct evdev_device *device,
+ unsigned int index)
+{
+ struct pad_dispatch *pad = (struct pad_dispatch*)device->dispatch;
+
+ if (!(device->seat_caps & EVDEV_DEVICE_TABLET_PAD))
+ return NULL;
+
+ return pad_get_mode_group(pad, index);
+}
diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c
index b7a2950e..0e95408c 100644
--- a/src/evdev-tablet-pad.c
+++ b/src/evdev-tablet-pad.c
@@ -209,12 +209,45 @@ pad_handle_strip(struct pad_dispatch *pad,
return pos;
}
+static inline struct libinput_tablet_pad_mode_group *
+pad_ring_get_mode_group(struct pad_dispatch *pad,
+ unsigned int ring)
+{
+ struct libinput_tablet_pad_mode_group *group;
+
+ list_for_each(group, &pad->modes.mode_group_list, link) {
+ if (libinput_tablet_pad_mode_group_has_ring(group, ring))
+ return group;
+ }
+
+ assert(!"Unable to find ring mode group");
+
+ return NULL;
+}
+
+static inline struct libinput_tablet_pad_mode_group *
+pad_strip_get_mode_group(struct pad_dispatch *pad,
+ unsigned int strip)
+{
+ struct libinput_tablet_pad_mode_group *group;
+
+ list_for_each(group, &pad->modes.mode_group_list, link) {
+ if (libinput_tablet_pad_mode_group_has_strip(group, strip))
+ return group;
+ }
+
+ assert(!"Unable to find strip mode group");
+
+ return NULL;
+}
+
static void
pad_check_notify_axes(struct pad_dispatch *pad,
struct evdev_device *device,
uint64_t time)
{
struct libinput_device *base = &device->base;
+ struct libinput_tablet_pad_mode_group *group;
double value;
bool send_finger_up = false;
@@ -229,11 +262,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
+ group = pad_ring_get_mode_group(pad, 0);
tablet_pad_notify_ring(base,
time,
0,
value,
- LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
+ LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
+ group);
}
if (pad->changed_axes & PAD_AXIS_RING2) {
@@ -241,11 +276,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
+ group = pad_ring_get_mode_group(pad, 1);
tablet_pad_notify_ring(base,
time,
1,
value,
- LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
+ LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
+ group);
}
if (pad->changed_axes & PAD_AXIS_STRIP1) {
@@ -253,11 +290,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
+ group = pad_strip_get_mode_group(pad, 0);
tablet_pad_notify_strip(base,
time,
0,
value,
- LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
+ LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
+ group);
}
if (pad->changed_axes & PAD_AXIS_STRIP2) {
@@ -265,11 +304,13 @@ pad_check_notify_axes(struct pad_dispatch *pad,
if (send_finger_up)
value = -1.0;
+ group = pad_strip_get_mode_group(pad, 1);
tablet_pad_notify_strip(base,
time,
1,
value,
- LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
+ LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
+ group);
}
pad->changed_axes = PAD_AXIS_NONE;
@@ -288,6 +329,22 @@ pad_process_key(struct pad_dispatch *pad,
pad_button_set_down(pad, button, is_press);
}
+static inline struct libinput_tablet_pad_mode_group *
+pad_button_get_mode_group(struct pad_dispatch *pad,
+ unsigned int button)
+{
+ struct libinput_tablet_pad_mode_group *group;
+
+ list_for_each(group, &pad->modes.mode_group_list, link) {
+ if (libinput_tablet_pad_mode_group_has_button(group, button))
+ return group;
+ }
+
+ assert(!"Unable to find button mode group\n");
+
+ return NULL;
+}
+
static void
pad_notify_button_mask(struct pad_dispatch *pad,
struct evdev_device *device,
@@ -296,6 +353,7 @@ pad_notify_button_mask(struct pad_dispatch *pad,
enum libinput_button_state state)
{
struct libinput_device *base = &device->base;
+ struct libinput_tablet_pad_mode_group *group;
int32_t code;
unsigned int i;
@@ -315,8 +373,11 @@ pad_notify_button_mask(struct pad_dispatch *pad,
continue;
map = pad->button_map[code - 1];
- if (map != -1)
- tablet_pad_notify_button(base, time, map, state);
+ if (map != -1) {
+ group = pad_button_get_mode_group(pad, map);
+ pad_button_update_mode(group, map, state);
+ tablet_pad_notify_button(base, time, map, state, group);
+ }
}
}
}
@@ -437,6 +498,7 @@ pad_destroy(struct evdev_dispatch *dispatch)
{
struct pad_dispatch *pad = (struct pad_dispatch*)dispatch;
+ pad_destroy_leds(pad);
free(pad);
}
@@ -500,6 +562,8 @@ pad_init(struct pad_dispatch *pad, struct evdev_device *device)
pad_init_buttons(pad, device);
pad_init_left_handed(device);
+ if (pad_init_leds(pad, device) != 0)
+ return 1;
return 0;
}
diff --git a/src/evdev-tablet-pad.h b/src/evdev-tablet-pad.h
index 84324bcb..9002fca9 100644
--- a/src/evdev-tablet-pad.h
+++ b/src/evdev-tablet-pad.h
@@ -64,6 +64,10 @@ struct pad_dispatch {
struct libinput_device_config_send_events config;
enum libinput_config_send_events_mode current_mode;
} sendevents;
+
+ struct {
+ struct list mode_group_list;
+ } modes;
};
static inline struct libinput *
@@ -72,4 +76,12 @@ pad_libinput_context(const struct pad_dispatch *pad)
return evdev_libinput_context(pad->device);
}
+int
+pad_init_leds(struct pad_dispatch *pad, struct evdev_device *device);
+void
+pad_destroy_leds(struct pad_dispatch *pad);
+void
+pad_button_update_mode(struct libinput_tablet_pad_mode_group *g,
+ unsigned int pressed_button,
+ enum libinput_button_state state);
#endif
diff --git a/src/evdev.h b/src/evdev.h
index 2b60faaf..939a0b86 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -389,6 +389,22 @@ evdev_device_tablet_pad_get_num_rings(struct evdev_device *device);
int
evdev_device_tablet_pad_get_num_strips(struct evdev_device *device);
+int
+evdev_device_tablet_pad_get_num_mode_groups(struct evdev_device *device);
+
+struct libinput_tablet_pad_mode_group *
+evdev_device_tablet_pad_get_mode_group(struct evdev_device *device,
+ unsigned int index);
+
+unsigned int
+evdev_device_tablet_pad_mode_group_get_button_target(
+ struct libinput_tablet_pad_mode_group *g,
+ unsigned int button_index);
+
+struct libinput_tablet_pad_led *
+evdev_device_tablet_pad_get_led(struct evdev_device *device,
+ unsigned int led);
+
double
evdev_device_transform_x(struct evdev_device *device,
double x,
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 10522125..b3257073 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -329,6 +329,25 @@ struct libinput_tablet_tool {
bool has_pressure_offset;
};
+struct libinput_tablet_pad_mode_group {
+ struct libinput_device *device;
+ struct list link;
+ int refcount;
+ void *user_data;
+
+ unsigned int index;
+ unsigned int num_modes;
+ unsigned int current_mode;
+
+ uint32_t button_mask;
+ uint32_t ring_mask;
+ uint32_t strip_mask;
+
+ uint32_t toggle_button_mask;
+
+ void (*destroy)(struct libinput_tablet_pad_mode_group *group);
+};
+
struct libinput_event {
enum libinput_event_type type;
struct libinput_device *device;
@@ -566,19 +585,22 @@ void
tablet_pad_notify_button(struct libinput_device *device,
uint64_t time,
int32_t button,
- enum libinput_button_state state);
+ enum libinput_button_state state,
+ struct libinput_tablet_pad_mode_group *group);
void
tablet_pad_notify_ring(struct libinput_device *device,
uint64_t time,
unsigned int number,
double value,
- enum libinput_tablet_pad_ring_axis_source source);
+ enum libinput_tablet_pad_ring_axis_source source,
+ struct libinput_tablet_pad_mode_group *group);
void
tablet_pad_notify_strip(struct libinput_device *device,
uint64_t time,
unsigned int number,
double value,
- enum libinput_tablet_pad_strip_axis_source source);
+ enum libinput_tablet_pad_strip_axis_source source,
+ struct libinput_tablet_pad_mode_group *group);
static inline uint64_t
libinput_now(struct libinput *libinput)
diff --git a/src/libinput-util.h b/src/libinput-util.h
index 701fe078..a7ebc308 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -27,6 +27,7 @@
#include <assert.h>
#include <unistd.h>
+#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -86,6 +87,7 @@ int list_empty(const struct list *list);
pos = tmp, \
tmp = container_of(pos->member.next, tmp, member))
+#define NBITS(b) (b * 8)
#define LONG_BITS (sizeof(long) * 8)
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
@@ -399,4 +401,23 @@ us2ms(uint64_t us)
return (uint32_t)(us / 1000);
}
+static inline bool
+safe_atoi(const char *str, int *val)
+{
+ char *endptr;
+ long v;
+
+ v = strtol(str, &endptr, 10);
+ if (str == endptr)
+ return false;
+ if (*str != '\0' && *endptr != '\0')
+ return false;
+
+ if (v > INT_MAX || v < INT_MIN)
+ return false;
+
+ *val = v;
+ return true;
+}
+
#endif /* LIBINPUT_UTIL_H */
diff --git a/src/libinput.c b/src/libinput.c
index 6ff4e9a1..cf0ed5bf 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -140,6 +140,8 @@ struct libinput_event_tablet_tool {
struct libinput_event_tablet_pad {
struct libinput_event base;
+ unsigned int mode;
+ struct libinput_tablet_pad_mode_group *mode_group;
uint64_t time;
struct {
uint32_t number;
@@ -1666,6 +1668,12 @@ libinput_event_tablet_tool_destroy(struct libinput_event_tablet_tool *event)
libinput_tablet_tool_unref(event->tool);
}
+static void
+libinput_event_tablet_pad_destroy(struct libinput_event_tablet_pad *event)
+{
+ libinput_tablet_pad_mode_group_unref(event->mode_group);
+}
+
LIBINPUT_EXPORT void
libinput_event_destroy(struct libinput_event *event)
{
@@ -1680,6 +1688,13 @@ libinput_event_destroy(struct libinput_event *event)
libinput_event_tablet_tool_destroy(
libinput_event_get_tablet_tool_event(event));
break;
+ case LIBINPUT_EVENT_TABLET_PAD_RING:
+ case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+ case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+ case LIBINPUT_EVENT_TABLET_PAD_MODE:
+ libinput_event_tablet_pad_destroy(
+ libinput_event_get_tablet_pad_event(event));
+ break;
default:
break;
}
@@ -2400,18 +2415,24 @@ void
tablet_pad_notify_button(struct libinput_device *device,
uint64_t time,
int32_t button,
- enum libinput_button_state state)
+ enum libinput_button_state state,
+ struct libinput_tablet_pad_mode_group *group)
{
struct libinput_event_tablet_pad *button_event;
+ unsigned int mode;
button_event = zalloc(sizeof *button_event);
if (!button_event)
return;
+ mode = libinput_tablet_pad_mode_group_get_mode(group);
+
*button_event = (struct libinput_event_tablet_pad) {
.time = time,
.button.number = button,
.button.state = state,
+ .mode_group = libinput_tablet_pad_mode_group_ref(group),
+ .mode = mode,
};
post_device_event(device,
@@ -2425,19 +2446,25 @@ tablet_pad_notify_ring(struct libinput_device *device,
uint64_t time,
unsigned int number,
double value,
- enum libinput_tablet_pad_ring_axis_source source)
+ enum libinput_tablet_pad_ring_axis_source source,
+ struct libinput_tablet_pad_mode_group *group)
{
struct libinput_event_tablet_pad *ring_event;
+ unsigned int mode;
ring_event = zalloc(sizeof *ring_event);
if (!ring_event)
return;
+ mode = libinput_tablet_pad_mode_group_get_mode(group);
+
*ring_event = (struct libinput_event_tablet_pad) {
.time = time,
.ring.number = number,
.ring.position = value,
.ring.source = source,
+ .mode_group = libinput_tablet_pad_mode_group_ref(group),
+ .mode = mode,
};
post_device_event(device,
@@ -2451,19 +2478,25 @@ tablet_pad_notify_strip(struct libinput_device *device,
uint64_t time,
unsigned int number,
double value,
- enum libinput_tablet_pad_strip_axis_source source)
+ enum libinput_tablet_pad_strip_axis_source source,
+ struct libinput_tablet_pad_mode_group *group)
{
struct libinput_event_tablet_pad *strip_event;
+ unsigned int mode;
strip_event = zalloc(sizeof *strip_event);
if (!strip_event)
return;
+ mode = libinput_tablet_pad_mode_group_get_mode(group);
+
*strip_event = (struct libinput_event_tablet_pad) {
.time = time,
.strip.number = number,
.strip.position = value,
.strip.source = source,
+ .mode_group = libinput_tablet_pad_mode_group_ref(group),
+ .mode = mode,
};
post_device_event(device,
@@ -2580,6 +2613,7 @@ event_type_to_str(enum libinput_event_type type)
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
+ CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_MODE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
@@ -2829,6 +2863,121 @@ libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
return evdev_device_tablet_pad_get_num_strips((struct evdev_device *)device);
}
+LIBINPUT_EXPORT int
+libinput_device_tablet_pad_get_num_mode_groups(struct libinput_device *device)
+{
+ return evdev_device_tablet_pad_get_num_mode_groups((struct evdev_device *)device);
+}
+
+LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group*
+libinput_device_tablet_pad_get_mode_group(struct libinput_device *device,
+ unsigned int index)
+{
+ return evdev_device_tablet_pad_get_mode_group((struct evdev_device *)device,
+ index);
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_tablet_pad_mode_group_get_num_modes(
+ struct libinput_tablet_pad_mode_group *group)
+{
+ return group->num_modes;
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_tablet_pad_mode_group_get_mode(struct libinput_tablet_pad_mode_group *group)
+{
+ return group->current_mode;
+}
+
+LIBINPUT_EXPORT unsigned int
+libinput_tablet_pad_mode_group_get_index(struct libinput_tablet_pad_mode_group *group)
+{
+ return group->index;
+}
+
+LIBINPUT_EXPORT int
+libinput_tablet_pad_mode_group_has_button(struct libinput_tablet_pad_mode_group *group,
+ unsigned int button)
+{
+ if ((int)button >=
+ libinput_device_tablet_pad_get_num_buttons(group->device))
+ return 0;
+
+ return !!(group->button_mask & (1 << button));
+}
+
+LIBINPUT_EXPORT int
+libinput_tablet_pad_mode_group_has_ring(struct libinput_tablet_pad_mode_group *group,
+ unsigned int ring)
+{
+ if ((int)ring >=
+ libinput_device_tablet_pad_get_num_rings(group->device))
+ return 0;
+
+ return !!(group->ring_mask & (1 << ring));
+}
+
+LIBINPUT_EXPORT int
+libinput_tablet_pad_mode_group_has_strip(struct libinput_tablet_pad_mode_group *group,
+ unsigned int strip)
+{
+ if ((int)strip >=
+ libinput_device_tablet_pad_get_num_strips(group->device))
+ return 0;
+
+ return !!(group->strip_mask & (1 << strip));
+}
+
+LIBINPUT_EXPORT int
+libinput_tablet_pad_mode_group_button_is_toggle(struct libinput_tablet_pad_mode_group *group,
+ unsigned int button)
+{
+ if ((int)button >=
+ libinput_device_tablet_pad_get_num_buttons(group->device))
+ return 0;
+
+ return !!(group->toggle_button_mask & (1 << button));
+}
+
+LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
+libinput_tablet_pad_mode_group_ref(
+ struct libinput_tablet_pad_mode_group *group)
+{
+ group->refcount++;
+ return group;
+}
+
+LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
+libinput_tablet_pad_mode_group_unref(
+ struct libinput_tablet_pad_mode_group *group)
+{
+ assert(group->refcount > 0);
+
+ group->refcount--;
+ if (group->refcount > 0)
+ return group;
+
+ list_remove(&group->link);
+ group->destroy(group);
+ return NULL;
+}
+
+LIBINPUT_EXPORT void
+libinput_tablet_pad_mode_group_set_user_data(
+ struct libinput_tablet_pad_mode_group *group,
+ void *user_data)
+{
+ group->user_data = user_data;
+}
+
+LIBINPUT_EXPORT void *
+libinput_tablet_pad_mode_group_get_user_data(
+ struct libinput_tablet_pad_mode_group *group)
+{
+ return group->user_data;
+}
+
LIBINPUT_EXPORT struct libinput_event *
libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event)
{
@@ -2989,6 +3138,32 @@ libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *eve
return event->button.state;
}
+LIBINPUT_EXPORT unsigned int
+libinput_event_tablet_pad_get_mode(struct libinput_event_tablet_pad *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_TABLET_PAD_RING,
+ LIBINPUT_EVENT_TABLET_PAD_STRIP,
+ LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+ return event->mode;
+}
+
+LIBINPUT_EXPORT struct libinput_tablet_pad_mode_group *
+libinput_event_tablet_pad_get_mode_group(struct libinput_event_tablet_pad *event)
+{
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ NULL,
+ LIBINPUT_EVENT_TABLET_PAD_RING,
+ LIBINPUT_EVENT_TABLET_PAD_STRIP,
+ LIBINPUT_EVENT_TABLET_PAD_BUTTON);
+
+ return event->mode_group;
+}
+
LIBINPUT_EXPORT uint32_t
libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event)
{
diff --git a/src/libinput.h b/src/libinput.h
index abc737e5..491eee30 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -39,6 +39,132 @@ extern "C" {
/**
* @ingroup base
+ * @struct libinput
+ *
+ * A handle for accessing libinput. This struct is refcounted, use
+ * libinput_ref() and libinput_unref().
+ */
+struct libinput;
+
+/**
+ * @ingroup device
+ * @struct libinput_device
+ *
+ * A base handle for accessing libinput devices. This struct is
+ * refcounted, use libinput_device_ref() and libinput_device_unref().
+ */
+struct libinput_device;
+
+/**
+ * @ingroup device
+ * @struct libinput_device_group
+ *
+ * A base handle for accessing libinput device groups. This struct is
+ * refcounted, use libinput_device_group_ref() and
+ * libinput_device_group_unref().
+ */
+struct libinput_device_group;
+
+/**
+ * @ingroup seat
+ * @struct libinput_seat
+ *
+ * The base handle for accessing libinput seats. This struct is
+ * refcounted, use libinput_seat_ref() and libinput_seat_unref().
+ */
+struct libinput_seat;
+
+/**
+ * @ingroup device
+ * @struct libinput_tablet_tool
+ *
+ * An object representing a tool being used by a device with the @ref
+ * LIBINPUT_DEVICE_CAP_TABLET_TOOL capability.
+ *
+ * Tablet events generated by such a device are bound to a specific tool
+ * rather than coming from the device directly. Depending on the hardware it
+ * is possible to track the same physical tool across multiple
+ * struct libinput_device devices, see @ref tablet-serial-numbers.
+ *
+ * This struct is refcounted, use libinput_tablet_tool_ref() and
+ * libinput_tablet_tool_unref().
+ */
+struct libinput_tablet_tool;
+
+/**
+ * @ingroup event
+ * @struct libinput_event
+ *
+ * The base event type. Use libinput_event_get_pointer_event() or similar to
+ * get the actual event type.
+ *
+ * @warning Unlike other structs events are considered transient and
+ * <b>not</b> refcounted.
+ */
+struct libinput_event;
+
+/**
+ * @ingroup event
+ * @struct libinput_event_device_notify
+ *
+ * An event notifying the caller of a device being added or removed.
+ */
+struct libinput_event_device_notify;
+
+/**
+ * @ingroup event_keyboard
+ * @struct libinput_event_keyboard
+ *
+ * A keyboard event representing a key press/release.
+ */
+struct libinput_event_keyboard;
+
+/**
+ * @ingroup event_pointer
+ * @struct libinput_event_pointer
+ *
+ * A pointer event representing relative or absolute pointer movement,
+ * a button press/release or scroll axis events.
+ */
+struct libinput_event_pointer;
+
+/**
+ * @ingroup event_touch
+ * @struct libinput_event_touch
+ *
+ * Touch event representing a touch down, move or up, as well as a touch
+ * cancel and touch frame events. Valid event types for this event are @ref
+ * LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_MOTION, @ref
+ * LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_CANCEL and @ref
+ * LIBINPUT_EVENT_TOUCH_FRAME.
+ */
+struct libinput_event_touch;
+
+/**
+ * @ingroup event_tablet
+ * @struct libinput_event_tablet_tool
+ *
+ * Tablet tool event representing an axis update, button press, or tool
+ * update. Valid event types for this event are @ref
+ * LIBINPUT_EVENT_TABLET_TOOL_AXIS, @ref
+ * LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY and @ref
+ * LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
+ */
+struct libinput_event_tablet_tool;
+
+/**
+ * @ingroup event_tablet_pad
+ * @struct libinput_event_tablet_pad
+ *
+ * Tablet pad event representing a button press, or ring/strip update on
+ * the tablet pad itself. Valid event types for this event are @ref
+ * LIBINPUT_EVENT_TABLET_PAD_BUTTON, @ref LIBINPUT_EVENT_TABLET_PAD_RING and
+ * @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.
+ */
+struct libinput_event_tablet_pad;
+
+/**
+ * @ingroup base
*
* Log priority for internal logging messages.
*/
@@ -136,7 +262,7 @@ enum libinput_pointer_axis_source {
};
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* The source for a @ref LIBINPUT_EVENT_TABLET_PAD_RING event. See
* libinput_event_tablet_pad_get_ring_source() for details.
@@ -151,7 +277,7 @@ enum libinput_tablet_pad_ring_axis_source {
};
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* The source for a @ref LIBINPUT_EVENT_TABLET_PAD_STRIP event. See
* libinput_event_tablet_pad_get_strip_source() for details.
@@ -167,23 +293,6 @@ enum libinput_tablet_pad_strip_axis_source {
/**
* @ingroup device
- * @struct libinput_tablet_tool
- *
- * An object representing a tool being used by a device with the @ref
- * LIBINPUT_DEVICE_CAP_TABLET_TOOL capability.
- *
- * Tablet events generated by such a device are bound to a specific tool
- * rather than coming from the device directly. Depending on the hardware it
- * is possible to track the same physical tool across multiple
- * struct libinput_device devices, see @ref tablet-serial-numbers.
- *
- * This struct is refcounted, use libinput_tablet_tool_ref() and
- * libinput_tablet_tool_unref().
- */
-struct libinput_tablet_tool;
-
-/**
- * @ingroup device
*
* Available tool types for a device with the @ref
* LIBINPUT_DEVICE_CAP_TABLET_TOOL capability. The tool type defines the default
@@ -247,6 +356,236 @@ enum libinput_tablet_tool_tip_state {
};
/**
+ * @defgroup tablet_pad_modes Tablet pad modes
+ *
+ * Handling the virtual mode groups of buttons, strips and rings on tablet
+ * pad devices. See @ref tablet-pad-modes for details.
+ */
+
+/**
+ * @ingroup tablet_pad_modes
+ * @struct libinput_tablet_pad_mode_group
+ *
+ * A mode on a tablet pad is a virtual grouping of functionality, usually
+ * based on some visual feedback like LEDs on the pad. The set of buttons,
+ * rings and strips that share the same mode are a "mode group". Whenever
+ * the mode changes, all buttons, rings and strips within this mode group
+ * are affected. See @ref tablet-pad-modes for detail.
+ *
+ * Most tablets only have a single mode group, some tablets provide multiple
+ * mode groups through independent banks of LEDs (e.g. the Wacom Cintiq
+ * 24HD). libinput guarantees that at least one mode group is always
+ * available.
+ *
+ * This struct is refcounted, use libinput_tablet_pad_mode_group_ref() and
+ * libinput_tablet_pad_mode_group_unref().
+ */
+struct libinput_tablet_pad_mode_group;
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Most devices only provide a single mode group, however devices such as
+ * the Wacom Cintiq 22HD provide two mode groups. If multiple mode groups
+ * are available, a caller should use
+ * libinput_tablet_pad_mode_group_has_button(),
+ * libinput_tablet_pad_mode_group_has_ring() and
+ * libinput_tablet_pad_mode_group_has_strip() to associate each button,
+ * ring and strip with the correct mode group.
+ *
+ * @return the number of mode groups available on this device
+ */
+int
+libinput_device_tablet_pad_get_num_mode_groups(struct libinput_device *device);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * The returned mode group is not refcounted and may become invalid after
+ * the next call to libinput. Use libinput_tablet_pad_mode_group_ref() and
+ * libinput_tablet_pad_mode_group_unref() to continue using the handle
+ * outside of the immediate scope.
+ *
+ * While at least one reference is kept by the caller, the returned mode
+ * group will be identical for each subsequent call of this function with
+ * the same index and that same struct is returned from
+ * libinput_event_tablet_pad_get_mode_group(), provided the event was
+ * generated by this mode group.
+ *
+ * @param device A device with the @ref LIBINPUT_DEVICE_CAP_TABLET_PAD
+ * capability
+ * @param index A mode group index
+ * @return the mode group with the given index or NULL if an invalid index
+ * is given.
+ */
+struct libinput_tablet_pad_mode_group*
+libinput_device_tablet_pad_get_mode_group(struct libinput_device *device,
+ unsigned int index);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * The returned number is the same index as passed to
+ * libinput_device_tablet_pad_get_mode_group(). For tablets with only one
+ * mode this number is always 0.
+ *
+ * @param group A previously obtained mode group
+ * @return the numeric index this mode group represents, starting at 0
+ */
+unsigned int
+libinput_tablet_pad_mode_group_get_index(struct libinput_tablet_pad_mode_group *group);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Query the mode group for the number of available modes. This number is
+ * usually decided by the number of physical LEDs available on the device.
+ * Different mode groups may have a different number of modes.
+ * Use libinput_tablet_pad_mode_group_get_mode() to get the currently active
+ * mode.
+ *
+ * libinput guarantees that at least one mode is available. A device without
+ * mode switching capability has a single mode group and a single mode.
+ *
+ * @param group A previously obtained mode group
+ * @return the number of modes available in this mode group
+ */
+unsigned int
+libinput_tablet_pad_mode_group_get_num_modes(struct libinput_tablet_pad_mode_group *group);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Return the current mode this mode group is in. Note that the returned
+ * mode is the mode valid as of completing the last libinput_dispatch().
+ * The returned mode may thus be different to the mode returned by
+ * libinput_event_tablet_pad_get_mode().
+ *
+ * For example, if the mode was toggled three times between the call to
+ * libinput_dispatch(), this function returns the third mode but the events
+ * in the event queue will return the modes 1, 2 and 3, respectively.
+ *
+ * @param group A previously obtained mode group
+ * @return the numeric index of the current mode in this group, starting at 0
+ *
+ * @see libinput_event_tablet_pad_get_mode
+ */
+unsigned int
+libinput_tablet_pad_mode_group_get_mode(struct libinput_tablet_pad_mode_group *group);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Devices without mode switching capabilities return true for every button.
+ *
+ * @param group A previously obtained mode group
+ * @param button A button index, starting at 0
+ * @return true if the given button index is part of this mode group or
+ * false otherwise
+ */
+int
+libinput_tablet_pad_mode_group_has_button(struct libinput_tablet_pad_mode_group *group,
+ unsigned int button);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Devices without mode switching capabilities return true for every ring.
+ *
+ * @param group A previously obtained mode group
+ * @param ring A ring index, starting at 0
+ * @return true if the given ring index is part of this mode group or
+ * false otherwise
+ */
+int
+libinput_tablet_pad_mode_group_has_ring(struct libinput_tablet_pad_mode_group *group,
+ unsigned int ring);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Devices without mode switching capabilities return true for every strip.
+ *
+ * @param group A previously obtained mode group
+ * @param strip A strip index, starting at 0
+ * @return true if the given strip index is part of this mode group or
+ * false otherwise
+ */
+int
+libinput_tablet_pad_mode_group_has_strip(struct libinput_tablet_pad_mode_group *group,
+ unsigned int strip);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Devices without mode switching capabilities return false for every button.
+ *
+ * @param group A previously obtained mode group
+ * @param button A button index, starting at 0
+ * @retval non-zero if the button is a mode toggle button for this group, or
+ * zero otherwise
+ */
+int
+libinput_tablet_pad_mode_group_button_is_toggle(struct libinput_tablet_pad_mode_group *group,
+ unsigned int button);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Increase the refcount of the mode group. A mode device group will be
+ * freed whenever the refcount reaches 0.
+ *
+ * @param group A previously obtained mode group
+ * @return The passed mode group
+ */
+struct libinput_tablet_pad_mode_group *
+libinput_tablet_pad_mode_group_ref(
+ struct libinput_tablet_pad_mode_group *group);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Decrease the refcount of the mode group. A mode device group will be
+ * freed whenever the refcount reaches 0.
+ *
+ * @param group A previously obtained mode group
+ * @return NULL if the group was destroyed, otherwise the passed mode group
+ */
+struct libinput_tablet_pad_mode_group *
+libinput_tablet_pad_mode_group_unref(
+ struct libinput_tablet_pad_mode_group *group);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Set caller-specific data associated with this mode group. libinput does
+ * not manage, look at, or modify this data. The caller must ensure the
+ * data is valid.
+ *
+ * @param group A previously obtained mode group
+ * @param user_data Caller-specific data pointer
+ * @see libinput_tablet_pad_mode_group_get_user_data
+ *
+ */
+void
+libinput_tablet_pad_mode_group_set_user_data(
+ struct libinput_tablet_pad_mode_group *group,
+ void *user_data);
+
+/**
+ * @ingroup tablet_pad_modes
+ *
+ * Get the caller-specific data associated with this input device, if any.
+ *
+ * @param group A previously obtained mode group
+ * @return Caller-specific data pointer or NULL if none was set
+ * @see libinput_tablet_pad_mode_group_set_user_data
+ */
+void *
+libinput_tablet_pad_mode_group_get_user_data(
+ struct libinput_tablet_pad_mode_group *group);
+
+/**
* @ingroup base
*
* Event type for events returned by libinput_get_event().
@@ -395,6 +734,19 @@ enum libinput_event_type {
*/
LIBINPUT_EVENT_TABLET_PAD_STRIP,
+ /**
+ * A mode change on a device with the @ref
+ * LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
+ *
+ * This event is triggered when the mode is changed through
+ * external means. The event reflects a mode change (see @ref
+ * tablet-pad-modes) occurring as a result other than that of
+ * pressing a mode toggle button.
+ *
+ * @note Support for this event is not yet implemented.
+ */
+ LIBINPUT_EVENT_TABLET_PAD_MODE,
+
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
LIBINPUT_EVENT_GESTURE_SWIPE_END,
@@ -404,115 +756,6 @@ enum libinput_event_type {
};
/**
- * @ingroup base
- * @struct libinput
- *
- * A handle for accessing libinput. This struct is refcounted, use
- * libinput_ref() and libinput_unref().
- */
-struct libinput;
-
-/**
- * @ingroup device
- * @struct libinput_device
- *
- * A base handle for accessing libinput devices. This struct is
- * refcounted, use libinput_device_ref() and libinput_device_unref().
- */
-struct libinput_device;
-
-/**
- * @ingroup device
- * @struct libinput_device_group
- *
- * A base handle for accessing libinput device groups. This struct is
- * refcounted, use libinput_device_group_ref() and
- * libinput_device_group_unref().
- */
-struct libinput_device_group;
-
-/**
- * @ingroup seat
- * @struct libinput_seat
- *
- * The base handle for accessing libinput seats. This struct is
- * refcounted, use libinput_seat_ref() and libinput_seat_unref().
- */
-struct libinput_seat;
-
-/**
- * @ingroup event
- * @struct libinput_event
- *
- * The base event type. Use libinput_event_get_pointer_event() or similar to
- * get the actual event type.
- *
- * @warning Unlike other structs events are considered transient and
- * <b>not</b> refcounted.
- */
-struct libinput_event;
-
-/**
- * @ingroup event
- * @struct libinput_event_device_notify
- *
- * An event notifying the caller of a device being added or removed.
- */
-struct libinput_event_device_notify;
-
-/**
- * @ingroup event_keyboard
- * @struct libinput_event_keyboard
- *
- * A keyboard event representing a key press/release.
- */
-struct libinput_event_keyboard;
-
-/**
- * @ingroup event_pointer
- * @struct libinput_event_pointer
- *
- * A pointer event representing relative or absolute pointer movement,
- * a button press/release or scroll axis events.
- */
-struct libinput_event_pointer;
-
-/**
- * @ingroup event_touch
- * @struct libinput_event_touch
- *
- * Touch event representing a touch down, move or up, as well as a touch
- * cancel and touch frame events. Valid event types for this event are @ref
- * LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_MOTION, @ref
- * LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_CANCEL and @ref
- * LIBINPUT_EVENT_TOUCH_FRAME.
- */
-struct libinput_event_touch;
-
-/**
- * @ingroup event_tablet
- * @struct libinput_event_tablet_tool
- *
- * Tablet tool event representing an axis update, button press, or tool
- * update. Valid event types for this event are @ref
- * LIBINPUT_EVENT_TABLET_TOOL_AXIS, @ref
- * LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY and @ref
- * LIBINPUT_EVENT_TABLET_TOOL_BUTTON.
- */
-struct libinput_event_tablet_tool;
-
-/**
- * @ingroup event_tablet
- * @struct libinput_event_tablet_pad
- *
- * Tablet pad event representing a button press, or ring/strip update on
- * the tablet pad itself. Valid event types for this event are @ref
- * LIBINPUT_EVENT_TABLET_PAD_BUTTON, @ref LIBINPUT_EVENT_TABLET_PAD_RING and
- * @ref LIBINPUT_EVENT_TABLET_PAD_STRIP.
- */
-struct libinput_event_tablet_pad;
-
-/**
* @defgroup event Accessing and destruction of events
*/
@@ -1449,7 +1692,8 @@ libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event);
/**
* @defgroup event_tablet Tablet events
*
- * Events that come from tools on or the pad of tablet devices.
+ * Events that come from tools on tablet devices. For events from the pad,
+ * see @ref event_tablet_pad.
*
* Events from tablet devices are exposed by two interfaces, tools and pads.
* Tool events originate (usually) from a stylus-like device, pad events
@@ -2212,7 +2456,14 @@ libinput_tablet_tool_set_user_data(struct libinput_tablet_tool *tool,
void *user_data);
/**
- * @ingroup event_tablet
+ * @defgroup event_tablet_pad Tablet pad events
+ *
+ * Events that come from the pad of tablet devices. For events from the
+ * tablet tools, see @ref event_tablet.
+ */
+
+/**
+ * @ingroup event_tablet_pad
*
* @return The generic libinput_event of this event
*/
@@ -2220,7 +2471,7 @@ struct libinput_event *
libinput_event_tablet_pad_get_base_event(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Returns the current position of the ring, in degrees counterclockwise
* from the northern-most point of the ring in the tablet's current logical
@@ -2243,7 +2494,7 @@ double
libinput_event_tablet_pad_get_ring_position(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Returns the number of the ring that has changed state, with 0 being the
* first ring. On tablets with only one ring, this function always returns
@@ -2260,7 +2511,7 @@ unsigned int
libinput_event_tablet_pad_get_ring_number(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Returns the source of the interaction with the ring. If the source is
* @ref LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, libinput sends a ring
@@ -2277,7 +2528,7 @@ enum libinput_tablet_pad_ring_axis_source
libinput_event_tablet_pad_get_ring_source(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Returns the current position of the strip, normalized to the range
* [0, 1], with 0 being the top/left-most point in the tablet's current
@@ -2300,7 +2551,7 @@ double
libinput_event_tablet_pad_get_strip_position(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Returns the number of the strip that has changed state, with 0 being the
* first strip. On tablets with only one strip, this function always returns
@@ -2317,7 +2568,7 @@ unsigned int
libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Returns the source of the interaction with the strip. If the source is
* @ref LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, libinput sends a strip
@@ -2334,7 +2585,7 @@ enum libinput_tablet_pad_strip_axis_source
libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Return the button number that triggered this event, starting at 0.
* For events that are not of type @ref LIBINPUT_EVENT_TABLET_PAD_BUTTON,
@@ -2355,7 +2606,7 @@ uint32_t
libinput_event_tablet_pad_get_button_number(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* Return the button state of the event.
*
@@ -2370,6 +2621,53 @@ enum libinput_button_state
libinput_event_tablet_pad_get_button_state(struct libinput_event_tablet_pad *event);
/**
+ * @ingroup event_tablet_pad
+ *
+ * Returns the current mode this button, ring, or strip is considered in.
+ * The mode is a virtual grouping of functionality, usually based on some
+ * visual feedback like LEDs on the pad. See @ref tablet-pad-modes for
+ * details. Mode indices start at 0, a device that does not support modes
+ * always returns 0.
+ *
+ * Mode switching is controlled by libinput and more than one mode may exist
+ * on the tablet. This function returns the mode that this event's button,
+ * ring or strip is logically grouped in. If the button is the mode toggle
+ * button and the button event caused a new mode to be toggled, the mode
+ * returned is the new mode the button is in.
+ *
+ * Note that the returned mode is the mode valid as of the time of the
+ * event. The returned mode may thus be different to the mode returned by
+ * libinput_tablet_pad_mode_group_get_mode(). See
+ * libinput_tablet_pad_mode_group_get_mode() for details.
+ *
+ * @param event The libinput tablet pad event
+ * @return the current 0-indexed mode of this button, ring or strip
+ *
+ * @see libinput_tablet_pad_mode_group_get_mode
+ */
+unsigned int
+libinput_event_tablet_pad_get_mode(struct libinput_event_tablet_pad *event);
+
+/**
+ * @ingroup event_tablet_pad
+ *
+ * Returns the current mode group this button, ring, or strip is considered in.
+ * The mode is a virtual grouping of functionality, usually based on some
+ * visual feedback like LEDs on the pad. See @ref tablet-pad-modes for
+ * details.
+ *
+ * The returned mode group is not refcounted and may become invalid after
+ * the next call to libinput. Use libinput_tablet_pad_mode_group_ref() and
+ * libinput_tablet_pad_mode_group_unref() to continue using the handle
+ * outside of the immediate scope.
+ *
+ * @param event The libinput tablet pad event
+ * @return the current 0-indexed mode of this button, ring or strip
+ */
+struct libinput_tablet_pad_mode_group *
+libinput_event_tablet_pad_get_mode_group(struct libinput_event_tablet_pad *event);
+
+/**
* @ingroup event_tablet
*
* @param event The libinput tablet pad event
@@ -2379,7 +2677,7 @@ uint32_t
libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event);
/**
- * @ingroup event_tablet
+ * @ingroup event_tablet_pad
*
* @param event The libinput tablet pad event
* @return The event time for this event in microseconds
diff --git a/src/libinput.sym b/src/libinput.sym
index c6a0e4c9..cb3f2b84 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -258,4 +258,19 @@ LIBINPUT_1.4 {
libinput_device_config_rotation_get_default_angle;
libinput_device_config_rotation_is_available;
libinput_device_config_rotation_set_angle;
+ libinput_device_tablet_pad_get_mode_group;
+ libinput_device_tablet_pad_get_num_mode_groups;
+ libinput_event_tablet_pad_get_mode;
+ libinput_event_tablet_pad_get_mode_group;
+ libinput_tablet_pad_mode_group_button_is_toggle;
+ libinput_tablet_pad_mode_group_get_index;
+ libinput_tablet_pad_mode_group_get_mode;
+ libinput_tablet_pad_mode_group_get_num_modes;
+ libinput_tablet_pad_mode_group_get_user_data;
+ libinput_tablet_pad_mode_group_has_button;
+ libinput_tablet_pad_mode_group_has_strip;
+ libinput_tablet_pad_mode_group_has_ring;
+ libinput_tablet_pad_mode_group_ref;
+ libinput_tablet_pad_mode_group_set_user_data;
+ libinput_tablet_pad_mode_group_unref;
} LIBINPUT_1.3;