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

Hans de Goede hdegoede at redhat.com
Thu Apr 9 23:54:11 PDT 2015


Hi,

On 10-04-15 07:37, Peter Hutterer wrote:
> 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>

Looks good:

Reviewed-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans


> ---
> 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;
> +}
>


More information about the wayland-devel mailing list