summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2018-05-02 10:50:20 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2018-05-03 13:39:44 +1000
commit8bf2c5ae16c068b01573ae03a9ceb0421b2e4471 (patch)
tree945825bf34e0305f461e54f56b87fb0c8f953ac5 /tools
parent1e4c5a93a895cbda18a6b48ed2435a81a33f2624 (diff)
tools: libinput-record: print tablet events in --with-libinput
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'tools')
-rwxr-xr-xtools/libinput-record-verify-yaml.py187
-rw-r--r--tools/libinput-record.c396
2 files changed, 582 insertions, 1 deletions
diff --git a/tools/libinput-record-verify-yaml.py b/tools/libinput-record-verify-yaml.py
index 97149082..fb90481c 100755
--- a/tools/libinput-record-verify-yaml.py
+++ b/tools/libinput-record-verify-yaml.py
@@ -230,6 +230,10 @@ class TestYaml(unittest.TestCase):
'GESTURE_SWIPE_BEGIN', 'GESTURE_SWIPE_UPDATE',
'GESTURE_SWIPE_END', 'GESTURE_PINCH_BEGIN',
'GESTURE_PINCH_UPDATE', 'GESTURE_PINCH_END',
+ 'TABLET_TOOL_AXIS', 'TABLET_TOOL_PROXIMITY',
+ 'TABLET_TOOL_BUTTON', 'TABLET_TOOL_TIP',
+ 'TABLET_PAD_STRIP', 'TABLET_PAD_RING',
+ 'TABLET_PAD_BUTTON'
]
for e in self.libinput_events():
self.assertIn('type', e)
@@ -428,6 +432,189 @@ class TestYaml(unittest.TestCase):
for d in unaccel:
self.assertTrue(isinstance(d, float))
+ def test_events_libinput_tablet_pad_button(self):
+ keys = ['type', 'time', 'button', 'state', 'mode', 'is-toggle']
+
+ for e in self.libinput_events('TABLET_PAD_BUTTON'):
+ self.dict_key_crosscheck(e, keys)
+
+ b = e['button']
+ self.assertTrue(isinstance(b, int))
+ self.assertGreaterEqual(b, 0)
+ self.assertLessEqual(b, 16)
+
+ state = e['state']
+ self.assertIn(state, ['pressed', 'released'])
+
+ m = e['mode']
+ self.assertTrue(isinstance(m, int))
+ self.assertGreaterEqual(m, 0)
+ self.assertLessEqual(m, 3)
+
+ t = e['is-toggle']
+ self.assertTrue(isinstance(t, bool))
+
+ def test_events_libinput_tablet_pad_ring(self):
+ keys = ['type', 'time', 'number', 'position', 'source', 'mode']
+
+ for e in self.libinput_events('TABLET_PAD_RING'):
+ self.dict_key_crosscheck(e, keys)
+
+ n = e['number']
+ self.assertTrue(isinstance(n, int))
+ self.assertGreaterEqual(n, 0)
+ self.assertLessEqual(n, 4)
+
+ p = e['position']
+ self.assertTrue(isinstance(p, float))
+ if p != -1.0: # special 'end' case
+ self.assertGreaterEqual(p, 0.0)
+ self.assertLess(p, 360.0)
+
+ m = e['mode']
+ self.assertTrue(isinstance(m, int))
+ self.assertGreaterEqual(m, 0)
+ self.assertLessEqual(m, 3)
+
+ s = e['source']
+ self.assertIn(s, ['finger', 'unknown'])
+
+ def test_events_libinput_tablet_pad_strip(self):
+ keys = ['type', 'time', 'number', 'position', 'source', 'mode']
+
+ for e in self.libinput_events('TABLET_PAD_STRIP'):
+ self.dict_key_crosscheck(e, keys)
+
+ n = e['number']
+ self.assertTrue(isinstance(n, int))
+ self.assertGreaterEqual(n, 0)
+ self.assertLessEqual(n, 4)
+
+ p = e['position']
+ self.assertTrue(isinstance(p, float))
+ if p != -1.0: # special 'end' case
+ self.assertGreaterEqual(p, 0.0)
+ self.assertLessEqual(p, 1.0)
+
+ m = e['mode']
+ self.assertTrue(isinstance(m, int))
+ self.assertGreaterEqual(m, 0)
+ self.assertLessEqual(m, 3)
+
+ s = e['source']
+ self.assertIn(s, ['finger', 'unknown'])
+
+ def test_events_libinput_tablet_tool_proximity(self):
+ keys = ['type', 'time', 'proximity', 'tool-type', 'serial', 'axes']
+
+ for e in self.libinput_events('TABLET_TOOL_PROXIMITY'):
+ for k in keys:
+ self.assertIn(k, e)
+
+ p = e['proximity']
+ self.assertIn(p, ['in', 'out'])
+
+ p = e['tool-type']
+ self.assertIn(p, ['pen', 'eraser', 'brush', 'airbrush', 'mouse',
+ 'lens', 'unknown'])
+
+ s = e['serial']
+ self.assertTrue(isinstance(s, int))
+ self.assertGreaterEqual(s, 0)
+
+ a = e['axes']
+ for ax in e['axes']:
+ self.assertIn(a, 'pdtrsw')
+
+ def test_events_libinput_tablet_tool(self):
+ keys = ['type', 'time', 'tip']
+
+ for e in self.libinput_events(['TABLET_TOOL_AXIS',
+ 'TABLET_TOOL_TIP']):
+ for k in keys:
+ self.assertIn(k, e)
+
+ t = e['tip']
+ self.assertIn(t, ['down', 'up'])
+
+ def test_events_libinput_tablet_tool_button(self):
+ keys = ['type', 'time', 'button', 'state']
+
+ for e in self.libinput_events('TABLET_TOOL_BUTTON'):
+ self.dict_key_crosscheck(e, keys)
+
+ b = e['button']
+ # STYLUS, STYLUS2, STYLUS3
+ self.assertIn(b, [0x14b, 0x14c, 0x139])
+
+ s = e['state']
+ self.assertIn(s, ['pressed', 'released'])
+
+ def test_events_libinput_tablet_tool_axes(self):
+ for e in self.libinput_events(['TABLET_TOOL_PROXIMITY',
+ 'TABLET_TOOL_AXIS',
+ 'TABLET_TOOL_TIP']):
+
+ point = e['point']
+ self.assertTrue(isinstance(point, list))
+ self.assertEqual(len(point), 2)
+ for p in point:
+ self.assertTrue(isinstance(p, float))
+ self.assertGreater(p, 0.0)
+
+ try:
+ tilt = e['tilt']
+ self.assertTrue(isinstance(tilt, list))
+ self.assertEqual(len(tilt), 2)
+ for t in tilt:
+ self.assertTrue(isinstance(t, float))
+ except KeyError:
+ pass
+
+ try:
+ d = e['distance']
+ self.assertTrue(isinstance(d, float))
+ self.assertGreaterEqual(d, 0.0)
+ self.assertNotIn('pressure', e)
+ except KeyError:
+ pass
+
+ try:
+ p = e['pressure']
+ self.assertTrue(isinstance(p, float))
+ self.assertGreaterEqual(p, 0.0)
+ self.assertNotIn('distance', e)
+ except KeyError:
+ pass
+
+ try:
+ r = e['rotation']
+ self.assertTrue(isinstance(r, float))
+ self.assertGreaterEqual(r, 0.0)
+ except KeyError:
+ pass
+
+ try:
+ s = e['slider']
+ self.assertTrue(isinstance(s, float))
+ self.assertGreaterEqual(s, 0.0)
+ except KeyError:
+ pass
+
+ try:
+ w = e['wheel']
+ self.assertTrue(isinstance(w, float))
+ self.assertGreaterEqual(w, 0.0)
+ self.assertIn('wheel-discrete', e)
+ wd = e['wheel-discrete']
+ self.assertTrue(isinstance(wd, 1))
+ self.assertGreaterEqual(wd, 0.0)
+
+ def sign(x): (1, -1)[x < 0]
+ self.assertTrue(sign(w), sign(wd))
+ except KeyError:
+ pass
+
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Verify a YAML recording')
diff --git a/tools/libinput-record.c b/tools/libinput-record.c
index 33bb47fb..a2c00cf2 100644
--- a/tools/libinput-record.c
+++ b/tools/libinput-record.c
@@ -24,6 +24,7 @@
#include "config.h"
#include <errno.h>
+#include <inttypes.h>
#include <linux/input.h>
#include <libevdev/libevdev.h>
#include <libudev.h>
@@ -49,7 +50,7 @@ static const int FILE_VERSION_NUMBER = 1;
* cache our events. Simplest way to do this is to just cache the printf
* output */
struct li_event {
- char msg[128];
+ char msg[256];
};
enum event_type {
@@ -712,6 +713,382 @@ buffer_gesture_event(struct record_context *ctx,
}
}
+static char *
+buffer_tablet_axes(struct libinput_event_tablet_tool *t)
+{
+ struct libinput_tablet_tool *tool;
+ char *s = NULL;
+ int idx = 0;
+ int len;
+ double x, y;
+ char **strv;
+
+ tool = libinput_event_tablet_tool_get_tool(t);
+
+ strv = zalloc(10 * sizeof *strv);
+
+ x = libinput_event_tablet_tool_get_x(t);
+ y = libinput_event_tablet_tool_get_y(t);
+ len = xasprintf(&strv[idx++], "point: [%.2f, %.2f]", x, y);
+ if (len <= 0)
+ goto out;
+
+ if (libinput_tablet_tool_has_tilt(tool)) {
+ x = libinput_event_tablet_tool_get_tilt_x(t);
+ y = libinput_event_tablet_tool_get_tilt_y(t);
+ len = xasprintf(&strv[idx++], "tilt: [%.2f, %.2f]", x, y);
+ if (len <= 0)
+ goto out;
+ }
+
+ if (libinput_tablet_tool_has_distance(tool) ||
+ libinput_tablet_tool_has_pressure(tool)) {
+ double dist, pressure;
+
+ dist = libinput_event_tablet_tool_get_distance(t);
+ pressure = libinput_event_tablet_tool_get_pressure(t);
+ if (dist)
+ len = xasprintf(&strv[idx++], "distance: %.2f", dist);
+ else
+ len = xasprintf(&strv[idx++], "pressure: %.2f", pressure);
+ if (len <= 0)
+ goto out;
+ }
+
+ if (libinput_tablet_tool_has_rotation(tool)) {
+ double rotation;
+
+ rotation = libinput_event_tablet_tool_get_rotation(t);
+ len = xasprintf(&strv[idx++], "rotation: %.2f", rotation);
+ if (len <= 0)
+ goto out;
+ }
+
+ if (libinput_tablet_tool_has_slider(tool)) {
+ double slider;
+
+ slider = libinput_event_tablet_tool_get_slider_position(t);
+ len = xasprintf(&strv[idx++], "slider: %.2f", slider);
+ if (len <= 0)
+ goto out;
+
+ }
+
+ if (libinput_tablet_tool_has_wheel(tool)) {
+ double wheel;
+ int delta;
+
+ wheel = libinput_event_tablet_tool_get_wheel_delta(t);
+ len = xasprintf(&strv[idx++], "wheel: %.2f", wheel);
+ if (len <= 0)
+ goto out;
+
+ delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t);
+ len = xasprintf(&strv[idx++], "wheel-discrete: %d", delta);
+ if (len <= 0)
+ goto out;
+ }
+
+ s = strv_join(strv, ", ");
+out:
+ strv_free(strv);
+ return s;
+}
+
+static void
+buffer_tablet_tool_proximity_event(struct record_context *ctx,
+ struct libinput_event *e,
+ struct event *event)
+{
+ struct libinput_event_tablet_tool *t =
+ libinput_event_get_tablet_tool_event(e);
+ struct libinput_tablet_tool *tool =
+ libinput_event_tablet_tool_get_tool(t);
+ uint64_t time;
+ const char *type, *tool_type;
+ char *axes;
+ char caps[10] = {0};
+ enum libinput_tablet_tool_proximity_state prox;
+ size_t idx;
+
+ switch (libinput_event_get_type(e)) {
+ case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
+ type = "TABLET_TOOL_PROXIMITY";
+ break;
+ default:
+ abort();
+ }
+
+ switch (libinput_tablet_tool_get_type(tool)) {
+ case LIBINPUT_TABLET_TOOL_TYPE_PEN:
+ tool_type = "pen";
+ break;
+ case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
+ tool_type = "eraser";
+ break;
+ case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
+ tool_type = "brush";
+ break;
+ case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
+ tool_type = "brush";
+ break;
+ case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
+ tool_type = "airbrush";
+ break;
+ case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
+ tool_type = "mouse";
+ break;
+ case LIBINPUT_TABLET_TOOL_TYPE_LENS:
+ tool_type = "lens";
+ break;
+ default:
+ tool_type = "unknown";
+ break;
+ }
+
+ prox = libinput_event_tablet_tool_get_proximity_state(t);
+
+ time = ctx->offset ?
+ libinput_event_tablet_tool_get_time_usec(t) - ctx->offset : 0;
+
+ axes = buffer_tablet_axes(t);
+
+ idx = 0;
+ if (libinput_tablet_tool_has_pressure(tool))
+ caps[idx++] = 'p';
+ if (libinput_tablet_tool_has_distance(tool))
+ caps[idx++] = 'd';
+ if (libinput_tablet_tool_has_tilt(tool))
+ caps[idx++] = 't';
+ if (libinput_tablet_tool_has_rotation(tool))
+ caps[idx++] = 'r';
+ if (libinput_tablet_tool_has_slider(tool))
+ caps[idx++] = 's';
+ if (libinput_tablet_tool_has_wheel(tool))
+ caps[idx++] = 'w';
+ assert(idx <= ARRAY_LENGTH(caps));
+
+ event->time = time;
+ snprintf(event->u.libinput.msg,
+ sizeof(event->u.libinput.msg),
+ "{time: %ld.%06ld, type: %s, proximity: %s, tool-type: %s, serial: %" PRIu64 ", axes: %s, %s}",
+ time / (int)1e6,
+ time % (int)1e6,
+ type,
+ prox ? "in" : "out",
+ tool_type,
+ libinput_tablet_tool_get_serial(tool),
+ caps,
+ axes);
+ free(axes);
+}
+
+static void
+buffer_tablet_tool_button_event(struct record_context *ctx,
+ struct libinput_event *e,
+ struct event *event)
+{
+ struct libinput_event_tablet_tool *t =
+ libinput_event_get_tablet_tool_event(e);
+ uint64_t time;
+ const char *type;
+ uint32_t button;
+ enum libinput_button_state state;
+
+ switch(libinput_event_get_type(e)) {
+ case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
+ type = "TABLET_TOOL_BUTTON";
+ break;
+ default:
+ abort();
+ }
+
+
+ button = libinput_event_tablet_tool_get_button(t);
+ state = libinput_event_tablet_tool_get_button_state(t);
+
+ time = ctx->offset ?
+ libinput_event_tablet_tool_get_time_usec(t) - ctx->offset : 0;
+
+ event->time = time;
+ snprintf(event->u.libinput.msg,
+ sizeof(event->u.libinput.msg),
+ "{time: %ld.%06ld, type: %s, button: %d, state: %s}",
+ time / (int)1e6,
+ time % (int)1e6,
+ type,
+ button,
+ state ? "pressed" : "released");
+}
+
+static void
+buffer_tablet_tool_event(struct record_context *ctx,
+ struct libinput_event *e,
+ struct event *event)
+{
+ struct libinput_event_tablet_tool *t =
+ libinput_event_get_tablet_tool_event(e);
+ uint64_t time;
+ const char *type;
+ char *axes;
+ enum libinput_tablet_tool_tip_state tip;
+ char btn_buffer[30] = {0};
+
+ switch(libinput_event_get_type(e)) {
+ case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
+ type = "TABLET_TOOL_AXIS";
+ break;
+ case LIBINPUT_EVENT_TABLET_TOOL_TIP:
+ type = "TABLET_TOOL_TIP";
+ break;
+ case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
+ type = "TABLET_TOOL_BUTTON";
+ break;
+ default:
+ abort();
+ }
+
+ if (libinput_event_get_type(e) == LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
+ uint32_t button;
+ enum libinput_button_state state;
+
+ button = libinput_event_tablet_tool_get_button(t);
+ state = libinput_event_tablet_tool_get_button_state(t);
+ snprintf(btn_buffer, sizeof(btn_buffer),
+ ", button: %d, state: %s\n",
+ button,
+ state ? "pressed" : "released");
+ }
+
+ tip = libinput_event_tablet_tool_get_tip_state(t);
+
+ time = ctx->offset ?
+ libinput_event_tablet_tool_get_time_usec(t) - ctx->offset : 0;
+
+ axes = buffer_tablet_axes(t);
+
+ event->time = time;
+ snprintf(event->u.libinput.msg,
+ sizeof(event->u.libinput.msg),
+ "{time: %ld.%06ld, type: %s%s, tip: %s, %s}",
+ time / (int)1e6,
+ time % (int)1e6,
+ type,
+ btn_buffer, /* may be empty string */
+ tip ? "down" : "up",
+ axes);
+ free(axes);
+}
+
+static void
+buffer_tablet_pad_button_event(struct record_context *ctx,
+ struct libinput_event *e,
+ struct event *event)
+{
+ struct libinput_event_tablet_pad *p =
+ libinput_event_get_tablet_pad_event(e);
+ struct libinput_tablet_pad_mode_group *group;
+ enum libinput_button_state state;
+ unsigned int button, mode;
+ const char *type;
+ uint64_t time;
+
+ switch(libinput_event_get_type(e)) {
+ case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+ type = "TABLET_PAD_BUTTON";
+ break;
+ default:
+ abort();
+ }
+
+ time = ctx->offset ?
+ libinput_event_tablet_pad_get_time_usec(p) - ctx->offset : 0;
+
+ button = libinput_event_tablet_pad_get_button_number(p),
+ state = libinput_event_tablet_pad_get_button_state(p);
+ mode = libinput_event_tablet_pad_get_mode(p);
+ group = libinput_event_tablet_pad_get_mode_group(p);
+
+ event->time = time;
+ snprintf(event->u.libinput.msg,
+ sizeof(event->u.libinput.msg),
+ "{time: %ld.%06ld, type: %s, button: %d, state: %s, mode: %d, is-toggle: %s}",
+ time / (int)1e6,
+ time % (int)1e6,
+ type,
+ button,
+ state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
+ mode,
+ libinput_tablet_pad_mode_group_button_is_toggle(group, button) ? "true" : "false"
+ );
+
+
+}
+
+static void
+buffer_tablet_pad_ringstrip_event(struct record_context *ctx,
+ struct libinput_event *e,
+ struct event *event)
+{
+ struct libinput_event_tablet_pad *p =
+ libinput_event_get_tablet_pad_event(e);
+ const char *source = NULL;
+ unsigned int mode, number;
+ const char *type;
+ uint64_t time;
+ double pos;
+
+ switch(libinput_event_get_type(e)) {
+ case LIBINPUT_EVENT_TABLET_PAD_RING:
+ type = "TABLET_PAD_RING";
+ number = libinput_event_tablet_pad_get_ring_number(p);
+ pos = libinput_event_tablet_pad_get_ring_position(p);
+
+ switch (libinput_event_tablet_pad_get_ring_source(p)) {
+ case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
+ source = "finger";
+ break;
+ case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
+ source = "unknown";
+ break;
+ }
+ break;
+ case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+ type = "TABLET_PAD_STRIP";
+ number = libinput_event_tablet_pad_get_strip_number(p);
+ pos = libinput_event_tablet_pad_get_strip_position(p);
+
+ switch (libinput_event_tablet_pad_get_strip_source(p)) {
+ case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
+ source = "finger";
+ break;
+ case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
+ source = "unknown";
+ break;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ time = ctx->offset ?
+ libinput_event_tablet_pad_get_time_usec(p) - ctx->offset : 0;
+
+ mode = libinput_event_tablet_pad_get_mode(p);
+
+ event->time = time;
+ snprintf(event->u.libinput.msg,
+ sizeof(event->u.libinput.msg),
+ "{time: %ld.%06ld, type: %s, number: %d, position: %.2f, source: %s, mode: %d}",
+ time / (int)1e6,
+ time % (int)1e6,
+ type,
+ number,
+ pos,
+ source,
+ mode);
+}
+
static void
buffer_libinput_event(struct record_context *ctx,
struct libinput_event *e,
@@ -754,6 +1131,23 @@ buffer_libinput_event(struct record_context *ctx,
case LIBINPUT_EVENT_GESTURE_SWIPE_END:
buffer_gesture_event(ctx, e, event);
break;
+ case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
+ buffer_tablet_tool_proximity_event(ctx, e, event);
+ break;
+ case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
+ case LIBINPUT_EVENT_TABLET_TOOL_TIP:
+ buffer_tablet_tool_event(ctx, e, event);
+ break;
+ case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
+ buffer_tablet_tool_button_event(ctx, e, event);
+ break;
+ case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
+ buffer_tablet_pad_button_event(ctx, e, event);
+ break;
+ case LIBINPUT_EVENT_TABLET_PAD_RING:
+ case LIBINPUT_EVENT_TABLET_PAD_STRIP:
+ buffer_tablet_pad_ringstrip_event(ctx, e, event);
+ break;
default:
break;
}