[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