Hi,

On 28-10-16 07:08, Peter Hutterer wrote:
Not all mice have a click angle with integer degrees. The new
MOUSE_WHEEL_CLICK_COUNT property specifies how many clicks per full rotation,
the angle can be calculated from that.

See https://github.com/systemd/systemd/pull/4440 for more information

CLICK_COUNT overrides CLICK_ANGLE, so we check for the former first and then
fall back to the angle if need be. No changes to the user-facing API.

Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/evdev.c                                  | 51 +++++++++++++++---
 src/libinput-private.h                       |  2 +-
 src/libinput-util.c                          | 32 ++++++++++++
 src/libinput-util.h                          |  1 +
 test/Makefile.am                             |  1 +
 test/litest-device-mouse-wheel-click-count.c | 77 ++++++++++++++++++++++++++++
 test/litest.c                                |  2 +
 test/litest.h                                |  1 +
 test/misc.c                                  | 30 +++++++++++
 test/pointer.c                               | 49 +++++++++++++++---
 10 files changed, 229 insertions(+), 17 deletions(-)
 create mode 100644 test/litest-device-mouse-wheel-click-count.c

diff --git a/src/evdev.c b/src/evdev.c
index d49b391..1c46534 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -2008,7 +2008,7 @@ evdev_device_init_pointer_acceleration(struct 
evdev_device *device,
 static inline bool
 evdev_read_wheel_click_prop(struct evdev_device *device,
                            const char *prop,
-                           int *angle)
+                           double *angle)
 {
        int val;

@@ -2032,18 +2032,53 @@ evdev_read_wheel_click_prop(struct evdev_device *device,
        return false;
 }

+static inline bool
+evdev_read_wheel_click_count_prop(struct evdev_device *device,
+                                 const char *prop,
+                                 double *angle)
+{
+       int val;
+
+       prop = udev_device_get_property_value(device->udev_device, prop);
+       if (!prop)
+               return false;
+
+       val = parse_mouse_wheel_click_angle_property(prop);
+       if (val) {
+               *angle = 360.0/val;
+               return true;
+       }
+
+       log_error(evdev_libinput_context(device),
+                 "Mouse wheel click count '%s' is present but invalid, "
+                 "using %d degrees for angle instead instead\n",
+                 device->devname,
+                 DEFAULT_WHEEL_CLICK_ANGLE);
+       *angle = DEFAULT_WHEEL_CLICK_ANGLE;
+
+       return false;
+}
+

This is almost a 100% copy of evdev_read_wheel_click_prop
how about giving evdev_read_wheel_click_prop an extra
"bool count" argument and then doing:

        if (val) {
                if (count)
                        *angle = 360.0 / val;
                else
                        *angle = val;
                return true;
        }

Then we do not need the almost identical function.

 static inline struct wheel_angle
 evdev_read_wheel_click_props(struct evdev_device *device)
 {
        struct wheel_angle angles;

-       evdev_read_wheel_click_prop(device,
-                                   "MOUSE_WHEEL_CLICK_ANGLE",
-                                   &angles.x);
-       if (!evdev_read_wheel_click_prop(device,
-                                        "MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL",
-                                        &angles.y))
-               angles.y = angles.x;
+       /* CLICK_COUNT overrides CLICK_ANGLE */
+       if (!evdev_read_wheel_click_count_prop(device,
+                                             "MOUSE_WHEEL_CLICK_COUNT",
+                                             &angles.x))
+               evdev_read_wheel_click_prop(device,
+                                           "MOUSE_WHEEL_CLICK_ANGLE",
+                                           &angles.x);
+       if (!evdev_read_wheel_click_count_prop(device,
+                                             
"MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL",
+                                             &angles.y)) {
+               if (!evdev_read_wheel_click_prop(device,
+                                                
"MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL",
+                                                &angles.y))
+                       angles.y = angles.x;
+       }

        return angles;
 }
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 28656e0..2044cdd 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -73,7 +73,7 @@ struct normalized_range_coords {

 /* A pair of angles in degrees */
 struct wheel_angle {
-       int x, y;
+       double x, y;
 };

 /* A pair of angles in degrees */
diff --git a/src/libinput-util.c b/src/libinput-util.c
index 4b90fbb..6c051c3 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -176,6 +176,38 @@ parse_mouse_dpi_property(const char *prop)
 }

 /**
+ * Helper function to parse the MOUSE_WHEEL_CLICK_COUNT property from udev.
+ * Property is of the form:
+ * MOUSE_WHEEL_CLICK_COUNT=<integer>
+ * Where the number indicates the number of wheel clicks per 360 deg
+ * rotation.
+ *
+ * We skip preceding whitespaces and parse the first number seen. If
+ * multiple numbers are specified, we ignore those.
+ *
+ * @param prop The value of the udev property (without the 
MOUSE_WHEEL_CLICK_COUNT=)
+ * @return The click count of the wheel (may be negative) or 0 on error.
+ */
+int
+parse_mouse_wheel_click_count_property(const char *prop)
+{
+       int count = 0,
+           nread = 0;
+
+       while(*prop != 0 && *prop == ' ')
+               prop++;
+
+       sscanf(prop, "%d%n", &count, &nread);
+       if (nread == 0 || count == 0 || abs(count) > 360)
+               return 0;
+       if (prop[nread] != ' ' && prop[nread] != '\0')
+               return 0;
+
+        return count;
+}
+
+/**
+ *

This is a 1:1 copy off parse_mouse_wheel_click_angle_property (with
s/angle/count/ but that does not change the functionality), please drop.

  * Helper function to parse the MOUSE_WHEEL_CLICK_ANGLE property from udev.
  * Property is of the form:
  * MOUSE_WHEEL_CLICK_ANGLE=<integer>
diff --git a/src/libinput-util.h b/src/libinput-util.h
index e31860d..b7bef80 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -370,6 +370,7 @@ enum ratelimit_state ratelimit_test(struct ratelimit *r);

 int parse_mouse_dpi_property(const char *prop);
 int parse_mouse_wheel_click_angle_property(const char *prop);
+int parse_mouse_wheel_click_count_property(const char *prop);
 double parse_trackpoint_accel_property(const char *prop);
 bool parse_dimension_property(const char *prop, size_t *width, size_t *height);

diff --git a/test/Makefile.am b/test/Makefile.am
index 7ff12e4..f4a9252 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -35,6 +35,7 @@ liblitest_la_SOURCES = \
        litest-device-mouse-roccat.c \
        litest-device-mouse-low-dpi.c \
        litest-device-mouse-wheel-click-angle.c \
+       litest-device-mouse-wheel-click-count.c \
        litest-device-ms-surface-cover.c \
        litest-device-protocol-a-touch-screen.c \
        litest-device-qemu-usb-tablet.c \
diff --git a/test/litest-device-mouse-wheel-click-count.c 
b/test/litest-device-mouse-wheel-click-count.c
new file mode 100644
index 0000000..419b702
--- /dev/null
+++ b/test/litest-device-mouse-wheel-click-count.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+
+static void litest_mouse_setup(void)
+{
+       struct litest_device *d = 
litest_create_device(LITEST_MOUSE_WHEEL_CLICK_COUNT);
+       litest_set_current_device(d);
+}
+
+static struct input_id input_id = {
+       .bustype = 0x3,
+       .vendor = 0x1234,
+       .product = 0x5678,
+};
+
+static int events[] = {
+       EV_KEY, BTN_LEFT,
+       EV_KEY, BTN_RIGHT,
+       EV_KEY, BTN_MIDDLE,
+       EV_REL, REL_X,
+       EV_REL, REL_Y,
+       EV_REL, REL_WHEEL,
+       -1 , -1,
+};
+
+static const char udev_rule[] =
+"ACTION==\"remove\", GOTO=\"wheel_click_count_end\"\n"
+"KERNEL!=\"event*\", GOTO=\"wheel_click_count_end\"\n"
+"\n"
+"ATTRS{name}==\"litest Wheel Click Count Mouse*\",\\\n"
+"    ENV{MOUSE_WHEEL_CLICK_ANGLE}=\"-15\",\n"
+"    ENV{MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL}=\"13\",\n\\"
+"    ENV{MOUSE_WHEEL_CLICK_COUNT}=\"-14\",\n"
+"    ENV{MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL}=\"27\"\\\n"
+"\n"
+"LABEL=\"wheel_click_count_end\"";
+
+struct litest_test_device litest_mouse_wheel_click_count_device = {
+       .type = LITEST_MOUSE_WHEEL_CLICK_COUNT,
+       .features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
+       .shortname = "mouse-wheelclickcount",
+       .setup = litest_mouse_setup,
+       .interface = NULL,
+
+       .name = "Wheel Click Count Mouse",
+       .id = &input_id,
+       .absinfo = NULL,
+       .events = events,
+       .udev_rule = udev_rule,
+};
diff --git a/test/litest.c b/test/litest.c
index fd62d21..515eb18 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -402,6 +402,7 @@ extern struct litest_test_device 
litest_wacom_cintiq_13hdt_finger_device;
 extern struct litest_test_device litest_wacom_cintiq_13hdt_pen_device;
 extern struct litest_test_device litest_wacom_cintiq_13hdt_pad_device;
 extern struct litest_test_device litest_wacom_hid4800_tablet_device;
+extern struct litest_test_device litest_mouse_wheel_click_count_device;

 struct litest_test_device* devices[] = {
        &litest_synaptics_clickpad_device,
@@ -458,6 +459,7 @@ struct litest_test_device* devices[] = {
        &litest_wacom_cintiq_13hdt_pen_device,
        &litest_wacom_cintiq_13hdt_pad_device,
        &litest_wacom_hid4800_tablet_device,
+       &litest_mouse_wheel_click_count_device,
        NULL,
 };

diff --git a/test/litest.h b/test/litest.h
index 4602355..d52ebd2 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -224,6 +224,7 @@ enum litest_device_type {
        LITEST_WACOM_CINTIQ_13HDT_PAD,
        LITEST_WACOM_CINTIQ_13HDT_FINGER,
        LITEST_WACOM_HID4800_PEN,
+       LITEST_MOUSE_WHEEL_CLICK_COUNT,
 };

 enum litest_device_feature {
diff --git a/test/misc.c b/test/misc.c
index 582d4fc..4afd4d0 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -750,6 +750,35 @@ START_TEST(wheel_click_parser)
 }
 END_TEST

+START_TEST(wheel_click_count_parser)
+{
+       struct parser_test tests[] = {
+               { "1", 1 },
+               { "10", 10 },
+               { "-12", -12 },
+               { "360", 360 },
+               { "66 ", 66 },
+               { "   100 ", 100 },
+
+               { "0", 0 },
+               { "-0", 0 },
+               { "a", 0 },
+               { "10a", 0 },
+               { "10-", 0 },
+               { "sadfasfd", 0 },
+               { "361", 0 },
+               { NULL, 0 }
+       };
+
+       int i, angle;
+
+       for (i = 0; tests[i].tag != NULL; i++) {
+               angle = parse_mouse_wheel_click_count_property(tests[i].tag);
+               ck_assert_int_eq(angle, tests[i].expected_value);
+       }
+}
+END_TEST
+
 struct parser_test_float {
        char *tag;
        double expected_value;
@@ -956,6 +985,7 @@ litest_setup_tests_misc(void)
        litest_add_no_device("misc:ratelimit", ratelimit_helpers);
        litest_add_no_device("misc:parser", dpi_parser);
        litest_add_no_device("misc:parser", wheel_click_parser);
+       litest_add_no_device("misc:parser", wheel_click_count_parser);
        litest_add_no_device("misc:parser", trackpoint_accel_parser);
        litest_add_no_device("misc:parser", dimension_prop_parser);
        litest_add_no_device("misc:time", time_conversion);
diff --git a/test/pointer.c b/test/pointer.c
index 175cb3b..4f33de5 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -473,14 +473,45 @@ START_TEST(pointer_button_auto_release)
 }
 END_TEST

-static inline int
+static inline double
+wheel_click_count(struct litest_device *dev, int which)
+{
+       struct udev_device *d;
+       const char *prop = NULL;
+       int count;
+       double angle = 0.0;
+
+       d = libinput_device_get_udev_device(dev->libinput_device);
+       litest_assert_ptr_notnull(d);
+
+       if (which == REL_HWHEEL)
+               prop = udev_device_get_property_value(d, 
"MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL");
+       if(!prop)
+               prop = udev_device_get_property_value(d, 
"MOUSE_WHEEL_CLICK_COUNT");
+       if (!prop)
+               goto out;
+
+       count = parse_mouse_wheel_click_count_property(prop);
+       angle = 360.0/count;
+
+out:
+       udev_device_unref(d);
+       return angle;
+}
+
+static inline double
 wheel_click_angle(struct litest_device *dev, int which)
 {
        struct udev_device *d;
        const char *prop = NULL;
        const int default_angle = 15;
-       int angle = default_angle;
+       double angle;

+       angle = wheel_click_count(dev, which);
+       if (angle != 0.0)
+               return angle;
+
+       angle = default_angle;
        d = libinput_device_get_udev_device(dev->libinput_device);
        litest_assert_ptr_notnull(d);

@@ -492,7 +523,7 @@ wheel_click_angle(struct litest_device *dev, int which)
                goto out;

        angle = parse_mouse_wheel_click_angle_property(prop);
-       if (angle == 0)
+       if (angle == 0.0)
                angle = default_angle;

 out:
@@ -508,7 +539,7 @@ test_wheel_event(struct litest_device *dev, int which, int 
amount)
        struct libinput_event_pointer *ptrev;
        enum libinput_pointer_axis axis;

-       int scroll_step, expected, discrete;;
+       double scroll_step, expected, discrete;

        scroll_step = wheel_click_angle(dev, which);
        expected = amount * scroll_step;
@@ -535,10 +566,12 @@ test_wheel_event(struct litest_device *dev, int which, 
int amount)
                                     axis,
                                     LIBINPUT_POINTER_AXIS_SOURCE_WHEEL);

-       litest_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev, axis),
-                        expected);
-       
litest_assert_int_eq(libinput_event_pointer_get_axis_value_discrete(ptrev, 
axis),
-                            discrete);
+       litest_assert_double_eq(
+                       libinput_event_pointer_get_axis_value(ptrev, axis),
+                       expected);
+       litest_assert_double_eq(
+                       libinput_event_pointer_get_axis_value_discrete(ptrev, 
axis),
+                       discrete);
        libinput_event_destroy(event);
 }




Regards,

Hans
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to