[PATCH libinput] tools: add a tool for printing pointer acceleration parameters

Peter Hutterer peter.hutterer at who-t.net
Thu Apr 9 22:37:15 PDT 2015


Prints the various pointer accel behaviors into a format understood by
gnuplot, which then provides prettiness.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
This was a tool I used last year, I dug it up and added a couple of newer
bits to it. Hans' patch can be visualized running this before/after:
    for i in -1.0 -0.75 -0.5 -0.25 0.0 0.25 0.5 0.75 1.0; do
        ./ptraccel-debug --mode=accel --speed=$i > $1.$i.out
    done

then compare the various .out files in gnuplot.

 src/Makefile.am        |  10 +-
 tools/.gitignore       |   1 +
 tools/Makefile.am      |   6 +-
 tools/ptraccel-debug.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 314 insertions(+), 2 deletions(-)
 create mode 100644 tools/ptraccel-debug.c

diff --git a/src/Makefile.am b/src/Makefile.am
index ff65ff7..0f180cc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,6 @@
 lib_LTLIBRARIES = libinput.la
-noinst_LTLIBRARIES = libinput-util.la
+noinst_LTLIBRARIES = libinput-util.la \
+		     libfilter.la
 
 include_HEADERS =			\
 	libinput.h
@@ -48,6 +49,13 @@ libinput_util_la_CFLAGS = -I$(top_srcdir)/include \
 			  $(LIBUDEV_CFLAGS) \
 			  $(GCC_CFLAGS)
 
+libfilter_la_SOURCES = \
+	filter.c \
+	filter.h \
+	filter-private.h
+libfilter_la_LIBADD =
+libfilter_la_CFLAGS =
+
 libinput_la_LDFLAGS = -version-info $(LIBINPUT_LT_VERSION) -shared \
 		      -Wl,--version-script=$(srcdir)/libinput.sym
 
diff --git a/tools/.gitignore b/tools/.gitignore
index cf348a6..6d530e6 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -1,2 +1,3 @@
 event-debug
 event-gui
+ptraccel-debug
diff --git a/tools/Makefile.am b/tools/Makefile.am
index cebcd72..34d5ab0 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,4 +1,4 @@
-noinst_PROGRAMS = event-debug
+noinst_PROGRAMS = event-debug ptraccel-debug
 noinst_LTLIBRARIES = libshared.la
 
 AM_CPPFLAGS = -I$(top_srcdir)/include \
@@ -14,6 +14,10 @@ event_debug_LDADD = ../src/libinput.la libshared.la $(LIBUDEV_LIBS)
 event_debug_LDFLAGS = -no-install
 event_debug_CFLAGS = $(LIBUDEV_CFLAGS)
 
+ptraccel_debug_SOURCES = ptraccel-debug.c
+ptraccel_debug_LDADD = ../src/libfilter.la
+ptraccel_debug_LDFLAGS = -no-install
+
 if BUILD_EVENTGUI
 noinst_PROGRAMS += event-gui
 
diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c
new file mode 100644
index 0000000..d00e8f3
--- /dev/null
+++ b/tools/ptraccel-debug.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright © 2015 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.
+ */
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <filter.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+print_ptraccel_deltas(struct motion_filter *filter, double step)
+{
+	struct normalized_coords motion;
+	uint64_t time = 0;
+	double i;
+
+	printf("# gnuplot:\n");
+	printf("# set xlabel dx unaccelerated\n");
+	printf("# set ylabel dx accelerated\n");
+	printf("# set style data lines\n");
+	printf("# plot \"gnuplot.data\" using 1:2 title \"step %.2f\"\n", step);
+	printf("#\n");
+
+	/* Accel flattens out after 15 and becomes linear */
+	for (i = 0.0; i < 15.0; i += step) {
+		motion.x = i;
+		motion.y = 0;
+		time += 12; /* pretend 80Hz data */
+
+		motion = filter_dispatch(filter, &motion, NULL, time);
+
+		printf("%.2f	%.3f\n", i, motion.x);
+	}
+}
+
+static void
+print_ptraccel_movement(struct motion_filter *filter,
+			int nevents,
+			double max_dx,
+			double step)
+{
+	struct normalized_coords motion;
+	uint64_t time = 0;
+	double dx;
+	int i;
+
+	printf("# gnuplot:\n");
+	printf("# set xlabel \"event number\"\n");
+	printf("# set ylabel \"delta motion\"\n");
+	printf("# set style data lines\n");
+	printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n");
+	printf("#      \"gnuplot.data\" using 1:3 title \"dx in\"\n");
+	printf("#\n");
+
+	if (nevents == 0) {
+		if (step > 1.0)
+			nevents = max_dx;
+		else
+			nevents = 1.0 * max_dx/step + 0.5;
+
+		/* Print more events than needed so we see the curve
+		 * flattening out */
+		nevents *= 1.5;
+	}
+
+	dx = 0;
+
+	for (i = 0; i < nevents; i++) {
+		motion.x = dx;
+		motion.y = 0;
+		time += 12; /* pretend 80Hz data */
+
+		filter_dispatch(filter, &motion, NULL, time);
+
+		printf("%d	%.3f	%.3f\n", i, motion.x, dx);
+
+		if (dx < max_dx)
+			dx += step;
+	}
+}
+
+static void
+print_ptraccel_sequence(struct motion_filter *filter,
+			int nevents,
+			double *deltas)
+{
+	struct normalized_coords motion;
+	uint64_t time = 0;
+	double *dx;
+	int i;
+
+	printf("# gnuplot:\n");
+	printf("# set xlabel \"event number\"\n");
+	printf("# set ylabel \"delta motion\"\n");
+	printf("# set style data lines\n");
+	printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n");
+	printf("#      \"gnuplot.data\" using 1:3 title \"dx in\"\n");
+	printf("#\n");
+
+	dx = deltas;
+
+	for (i = 0; i < nevents; i++, dx++) {
+		motion.x = *dx;
+		motion.y = 0;
+		time += 12; /* pretend 80Hz data */
+
+		filter_dispatch(filter, &motion, NULL, time);
+
+		printf("%d	%.3f	%.3f\n", i, motion.x, *dx);
+	}
+}
+
+static void
+print_accel_func(struct motion_filter *filter)
+{
+	double vel;
+
+	printf("# gnuplot:\n");
+	printf("# set xlabel \"speed\"\n");
+	printf("# set ylabel \"raw accel factor\"\n");
+	printf("# set style data lines\n");
+	printf("# plot \"gnuplot.data\" using 1:2\n");
+	for (vel = 0.0; vel < 3.0; vel += .0001) {
+		double result = pointer_accel_profile_linear(filter,
+                                                             NULL,
+                                                             vel,
+                                                             0 /* time */);
+		printf("%.4f\t%.4f\n", vel, result);
+	}
+}
+
+static void
+usage(void)
+{
+	printf("Usage: %s [options] [dx1] [dx2] [...] > gnuplot.data\n", program_invocation_short_name);
+	printf("\n"
+	       "Options:\n"
+	       "--mode=<motion|accel|delta|sequence> \n"
+	       "	motion   ... print motion to accelerated motion (default)\n"
+	       "	delta    ... print delta to accelerated delta\n"
+	       "	accel    ... print accel factor\n"
+	       "	sequence ... print motion for custom delta sequence\n"
+	       "--maxdx=<double>\n  ... in motion mode only. Stop increasing dx at maxdx\n"
+	       "--steps=<double>\n  ... in motion and delta modes only. Increase dx by step each round\n"
+	       "--speed=<double>\n  ... accel speed [-1, 1], default 0\n"
+	       "\n"
+	       "If extra arguments are present and mode is not given, mode defaults to 'sequence'\n"
+	       "and the arguments are interpreted as sequence of delta x coordinates\n"
+	       "\n"
+	       "If stdin is a pipe, mode defaults to 'sequence' and the pipe is read \n"
+	       "for delta coordinates\n"
+	       "\n"
+	       "Output best viewed with gnuplot. See output for gnuplot commands\n");
+}
+
+int
+main(int argc, char **argv) {
+	struct motion_filter *filter;
+	double step = 0.1,
+	       max_dx = 10;
+	int nevents = 0;
+	bool print_accel = false,
+	     print_motion = true,
+	     print_delta = false,
+	     print_sequence = false;
+	double custom_deltas[1024];
+	double speed = 0.0;
+	enum {
+		OPT_MODE = 1,
+		OPT_NEVENTS,
+		OPT_MAXDX,
+		OPT_STEP,
+		OPT_SPEED,
+	};
+
+	filter = create_pointer_accelerator_filter(pointer_accel_profile_linear);
+	assert(filter != NULL);
+
+	while (1) {
+		int c;
+		int option_index = 0;
+		static struct option long_options[] = {
+			{"mode", 1, 0, OPT_MODE },
+			{"nevents", 1, 0, OPT_NEVENTS },
+			{"maxdx", 1, 0, OPT_MAXDX },
+			{"step", 1, 0, OPT_STEP },
+			{"speed", 1, 0, OPT_SPEED },
+			{0, 0, 0, 0}
+		};
+
+		c = getopt_long(argc, argv, "",
+				long_options, &option_index);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case OPT_MODE:
+			if (strcmp(optarg, "accel") == 0)
+				print_accel = true;
+			else if (strcmp(optarg, "motion") == 0)
+				print_motion = true;
+			else if (strcmp(optarg, "delta") == 0)
+				print_delta = true;
+			else if (strcmp(optarg, "sequence") == 0)
+				print_sequence = true;
+			else {
+				usage();
+				return 1;
+			}
+			break;
+		case OPT_NEVENTS:
+			nevents = atoi(optarg);
+			if (nevents == 0) {
+				usage();
+				return 1;
+			}
+			break;
+		case OPT_MAXDX:
+			max_dx = strtod(optarg, NULL);
+			if (max_dx == 0.0) {
+				usage();
+				return 1;
+			}
+			break;
+		case OPT_STEP:
+			step = strtod(optarg, NULL);
+			if (step == 0.0) {
+				usage();
+				return 1;
+			}
+			break;
+		case OPT_SPEED:
+			speed = strtod(optarg, NULL);
+			break;
+		default:
+			usage();
+			exit(1);
+			break;
+		}
+	}
+
+	filter_set_speed(filter, speed);
+
+	if (!isatty(STDIN_FILENO)) {
+		char buf[12];
+		print_sequence = true;
+		print_motion = false;
+		nevents = 0;
+		memset(custom_deltas, 0, sizeof(custom_deltas));
+
+		while(fgets(buf, sizeof(buf), stdin) && nevents < 1024) {
+			custom_deltas[nevents++] = strtod(buf, NULL);
+		}
+	} else if (optind < argc) {
+		print_sequence = true;
+		print_motion = false;
+		nevents = 0;
+		memset(custom_deltas, 0, sizeof(custom_deltas));
+		while (optind < argc)
+			custom_deltas[nevents++] = strtod(argv[optind++], NULL);
+	}
+
+	if (print_accel)
+		print_accel_func(filter);
+	else if (print_delta)
+		print_ptraccel_deltas(filter, step);
+	else if (print_motion)
+		print_ptraccel_movement(filter, nevents, max_dx, step);
+	else if (print_sequence)
+		print_ptraccel_sequence(filter, nevents, custom_deltas);
+
+	filter_destroy(filter);
+
+	return 0;
+}
-- 
2.3.4



More information about the wayland-devel mailing list