On Tue, May 03, 2016 at 05:08:49PM -0500, Yong Bakos wrote:
> On May 3, 2016, at 4:13 PM, Peter Hutterer <peter.hutte...@who-t.net> wrote:
> > 
> > Trackballs are effectively stationary devices and can be positioned at any
> > rotation. They are also employed by users with impaired dexterity which
> > sometimes implies that they are positioned at an non-default angle to make 
> > the
> > buttons easier to reach.
> > 
> > Add a config option for rotation for trackball devices. Currently only
> > supported for 90-degree angles, if there is a need we can add more angles
> > later.
> > 
> > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
> 
> Hi,
> The first paragraph of the comment for 
> libinput_device_config_rotation_set_angle
> is a bit confusing, marked inline below.

whoops, thanks. fixed locally.

Cheers,
   Peter

> 
> yong
> 
> 
> > ---
> > I'm not 100% sure yet that this is the feature we should have. Rotation
> > itself is important for trackpoints, no doubt, but I'm contemplating whether
> > to make this a more generic form like a matrix. It makes decisions of
> > precedence a lot easier, especially if we need to add other options later
> > that may overlap or conflict with rotation (admittedly, it just shifts that
> > decision to the caller). but a matrix can also be misused easier and makes
> > it harder for libinput to detect what the caller wants to do. while this
> > doesn't have a use-case yet for this feature, sometimes knowing what the
> > caller wants to do allows us to modify other features.
> > 
> > src/evdev.c            |  68 ++++++++++++
> > src/evdev.h            |   7 ++
> > src/libinput-private.h |  10 ++
> > src/libinput-util.h    |  21 ++++
> > src/libinput.c         |  41 ++++++++
> > src/libinput.h         |  96 +++++++++++++++++
> > src/libinput.sym       |   4 +
> > test/Makefile.am       |   5 +
> > test/trackball.c       | 273 
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> > 9 files changed, 525 insertions(+)
> > create mode 100644 test/trackball.c
> > 
> > diff --git a/src/evdev.c b/src/evdev.c
> > index 7abd895..38ac3aa 100644
> > --- a/src/evdev.c
> > +++ b/src/evdev.c
> > @@ -370,6 +370,22 @@ evdev_filter_defuzz_touch(struct evdev_device *device, 
> > struct mt_slot *slot)
> >     return false;
> > }
> > 
> > +static inline void
> > +evdev_rotate_relative(struct evdev_device *device)
> > +{
> > +   struct evdev_dispatch *dispatch = device->dispatch;
> > +   struct device_coords rel = device->rel;
> > +
> > +   if (!device->base.config.rotation)
> > +           return;
> > +
> > +   /* loss of precision for non-90 degrees, but we only support 90 deg
> > +    * right now anyway */
> > +   matrix_mult_vec(&dispatch->rotation.matrix, &rel.x, &rel.y);
> > +
> > +   device->rel = rel;
> > +}
> > +
> > static void
> > evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
> > {
> > @@ -394,6 +410,8 @@ evdev_flush_pending_event(struct evdev_device *device, 
> > uint64_t time)
> >             if (!(device->seat_caps & EVDEV_DEVICE_POINTER))
> >                     break;
> > 
> > +           evdev_rotate_relative(device);
> > +
> >             normalize_delta(device, &device->rel, &unaccel);
> >             raw.x = device->rel.x;
> >             raw.y = device->rel.y;
> > @@ -1326,6 +1344,55 @@ evdev_init_natural_scroll(struct evdev_device 
> > *device)
> >     device->base.config.natural_scroll = &device->scroll.config_natural;
> > }
> > 
> > +static int
> > +evdev_rotation_config_is_available(struct libinput_device *device)
> > +{
> > +   /* This function only gets called when we support rotation */
> > +   return 1;
> > +}
> > +
> > +static enum libinput_config_status
> > +evdev_rotation_config_set_angle(struct libinput_device *device,
> > +                           unsigned int degrees_cw)
> > +{
> > +   struct evdev_dispatch *dispatch = ((struct 
> > evdev_device*)device)->dispatch;
> > +
> > +   dispatch->rotation.angle = degrees_cw;
> > +   matrix_init_rotate(&dispatch->rotation.matrix, degrees_cw);
> > +
> > +   return LIBINPUT_CONFIG_STATUS_SUCCESS;
> > +}
> > +
> > +static unsigned int
> > +evdev_rotation_config_get_angle(struct libinput_device *device)
> > +{
> > +   struct evdev_dispatch *dispatch = ((struct 
> > evdev_device*)device)->dispatch;
> > +
> > +   return dispatch->rotation.angle;
> > +}
> > +
> > +static unsigned int
> > +evdev_rotation_config_get_default_angle(struct libinput_device *device)
> > +{
> > +   return 0;
> > +}
> > +
> > +static void
> > +evdev_init_rotation(struct evdev_device *device,
> > +               struct evdev_dispatch *dispatch)
> > +{
> > +   if ((device->model_flags & EVDEV_MODEL_TRACKBALL) == 0)
> > +           return;
> > +
> > +   dispatch->rotation.config.is_available = 
> > evdev_rotation_config_is_available;
> > +   dispatch->rotation.config.set_angle = evdev_rotation_config_set_angle;
> > +   dispatch->rotation.config.get_angle = evdev_rotation_config_get_angle;
> > +   dispatch->rotation.config.get_default_angle = 
> > evdev_rotation_config_get_default_angle;
> > +   dispatch->rotation.is_enabled = false;
> > +   matrix_init_identity(&dispatch->rotation.matrix);
> > +   device->base.config.rotation = &dispatch->rotation.config;
> > +}
> > +
> > static struct evdev_dispatch *
> > fallback_dispatch_create(struct libinput_device *device)
> > {
> > @@ -1356,6 +1423,7 @@ fallback_dispatch_create(struct libinput_device 
> > *device)
> > 
> >     evdev_init_calibration(evdev_device, dispatch);
> >     evdev_init_sendevents(evdev_device, dispatch);
> > +   evdev_init_rotation(evdev_device, dispatch);
> > 
> >     /* BTN_MIDDLE is set on mice even when it's not present. So
> >      * we can only use the absence of BTN_MIDDLE to mean something, i.e.
> > diff --git a/src/evdev.h b/src/evdev.h
> > index 2607fd8..8dafc2b 100644
> > --- a/src/evdev.h
> > +++ b/src/evdev.h
> > @@ -290,6 +290,13 @@ struct evdev_dispatch {
> >     struct libinput_device_config_calibration calibration;
> > 
> >     struct {
> > +           bool is_enabled;
> > +           int angle;
> > +           struct matrix matrix;
> > +           struct libinput_device_config_rotation config;
> > +   } rotation;
> > +
> > +   struct {
> >             struct libinput_device_config_send_events config;
> >             enum libinput_config_send_events_mode current_mode;
> >     } sendevents;
> > diff --git a/src/libinput-private.h b/src/libinput-private.h
> > index b65ae93..1052212 100644
> > --- a/src/libinput-private.h
> > +++ b/src/libinput-private.h
> > @@ -258,6 +258,15 @@ struct libinput_device_config_dwt {
> >                      struct libinput_device *device);
> > };
> > 
> > +struct libinput_device_config_rotation {
> > +   int (*is_available)(struct libinput_device *device);
> > +   enum libinput_config_status (*set_angle)(
> > +                    struct libinput_device *device,
> > +                    unsigned int degrees_cw);
> > +   unsigned int (*get_angle)(struct libinput_device *device);
> > +   unsigned int (*get_default_angle)(struct libinput_device *device);
> > +};
> > +
> > struct libinput_device_config {
> >     struct libinput_device_config_tap *tap;
> >     struct libinput_device_config_calibration *calibration;
> > @@ -269,6 +278,7 @@ struct libinput_device_config {
> >     struct libinput_device_config_click_method *click_method;
> >     struct libinput_device_config_middle_emulation *middle_emulation;
> >     struct libinput_device_config_dwt *dwt;
> > +   struct libinput_device_config_rotation *rotation;
> > };
> > 
> > struct libinput_device_group {
> > diff --git a/src/libinput-util.h b/src/libinput-util.h
> > index 82ab2b1..701fe07 100644
> > --- a/src/libinput-util.h
> > +++ b/src/libinput-util.h
> > @@ -186,6 +186,12 @@ long_any_bit_set(unsigned long *array, size_t size)
> >     return 0;
> > }
> > 
> > +static inline double
> > +deg2rad(int degree)
> > +{
> > +   return M_PI * degree / 180.0;
> > +}
> > +
> > struct matrix {
> >     float val[3][3]; /* [row][col] */
> > };
> > @@ -227,6 +233,21 @@ matrix_init_translate(struct matrix *m, float x, float 
> > y)
> >     m->val[1][2] = y;
> > }
> > 
> > +static inline void
> > +matrix_init_rotate(struct matrix *m, int degrees)
> > +{
> > +   double s, c;
> > +
> > +   s = sin(deg2rad(degrees));
> > +   c = cos(deg2rad(degrees));
> > +
> > +   matrix_init_identity(m);
> > +   m->val[0][0] = c;
> > +   m->val[0][1] = -s;
> > +   m->val[1][0] = s;
> > +   m->val[1][1] = c;
> > +}
> > +
> > static inline int
> > matrix_is_identity(const struct matrix *m)
> > {
> > diff --git a/src/libinput.c b/src/libinput.c
> > index bcd0dcd..7a9199d 100644
> > --- a/src/libinput.c
> > +++ b/src/libinput.c
> > @@ -3688,3 +3688,44 @@ 
> > libinput_device_config_dwt_get_default_enabled(struct libinput_device 
> > *device)
> > 
> >     return device->config.dwt->get_default_enabled(device);
> > }
> > +
> > +LIBINPUT_EXPORT int
> > +libinput_device_config_rotation_is_available(struct libinput_device 
> > *device)
> > +{
> > +   if (!device->config.rotation)
> > +           return 0;
> > +
> > +   return device->config.rotation->is_available(device);
> > +}
> > +
> > +LIBINPUT_EXPORT enum libinput_config_status
> > +libinput_device_config_rotation_set_angle(struct libinput_device *device,
> > +                                     unsigned int degrees_cw)
> > +{
> > +   if (!libinput_device_config_rotation_is_available(device))
> > +           return degrees_cw ? LIBINPUT_CONFIG_STATUS_UNSUPPORTED :
> > +                               LIBINPUT_CONFIG_STATUS_SUCCESS;
> > +
> > +   if (degrees_cw >= 360 || degrees_cw % 90)
> > +           return LIBINPUT_CONFIG_STATUS_INVALID;
> > +
> > +   return device->config.rotation->set_angle(device, degrees_cw);
> > +}
> > +
> > +LIBINPUT_EXPORT unsigned int
> > +libinput_device_config_rotation_get_angle(struct libinput_device *device)
> > +{
> > +   if (!libinput_device_config_rotation_is_available(device))
> > +           return 0;
> > +
> > +   return device->config.rotation->get_angle(device);
> > +}
> > +
> > +LIBINPUT_EXPORT unsigned int
> > +libinput_device_config_rotation_get_default_angle(struct libinput_device 
> > *device)
> > +{
> > +   if (!libinput_device_config_rotation_is_available(device))
> > +           return 0;
> > +
> > +   return device->config.rotation->get_default_angle(device);
> > +}
> > diff --git a/src/libinput.h b/src/libinput.h
> > index a93676e..b880810 100644
> > --- a/src/libinput.h
> > +++ b/src/libinput.h
> > @@ -809,6 +809,9 @@ libinput_event_pointer_get_dy(struct 
> > libinput_event_pointer *event);
> >  * X resolution of the touchpad. See @ref motion_normalization for more
> >  * details.
> >  *
> > + * Any rotation applied to the device also applies to unaccelerated motion
> > + * (see libinput_device_config_rotation_set_angle()).
> > + *
> >  * @note It is an application bug to call this function for events other 
> > than
> >  * @ref LIBINPUT_EVENT_POINTER_MOTION.
> >  *
> > @@ -831,6 +834,9 @@ libinput_event_pointer_get_dx_unaccelerated(
> >  * X resolution of the touchpad. See @ref motion_normalization for more
> >  * details.
> >  *
> > + * Any rotation applied to the device also applies to unaccelerated motion
> > + * (see libinput_device_config_rotation_set_angle()).
> > + *
> >  * @note It is an application bug to call this function for events other 
> > than
> >  * @ref LIBINPUT_EVENT_POINTER_MOTION.
> >  *
> > @@ -1356,6 +1362,9 @@ libinput_event_gesture_get_dy(struct 
> > libinput_event_gesture *event);
> >  * details. Note that unaccelerated events are not equivalent to 'raw' 
> > events
> >  * as read from the device.
> >  *
> > + * Any rotation applied to the device also applies to gesture motion
> > + * (see libinput_device_config_rotation_set_angle()).
> > + *
> >  * @return the unaccelerated relative x movement since the last event
> >  */
> > double
> > @@ -1375,6 +1384,9 @@ libinput_event_gesture_get_dx_unaccelerated(
> >  * details. Note that unaccelerated events are not equivalent to 'raw' 
> > events
> >  * as read from the device.
> >  *
> > + * Any rotation applied to the device also applies to gesture motion
> > + * (see libinput_device_config_rotation_set_angle()).
> > + *
> >  * @return the unaccelerated relative y movement since the last event
> >  */
> > double
> > @@ -3337,6 +3349,7 @@ libinput_device_group_get_user_data(struct 
> > libinput_device_group *group);
> >  *    - libinput_device_config_scroll_set_natural_scroll_enabled()
> >  *    - libinput_device_config_left_handed_set()
> >  *    - libinput_device_config_middle_emulation_set_enabled()
> > + *    - libinput_device_config_rotation_set_angle()
> >  * - All devices:
> >  *    - libinput_device_config_send_events_set_mode()
> >  */
> > @@ -4649,6 +4662,89 @@ libinput_device_config_dwt_get_enabled(struct 
> > libinput_device *device);
> > enum libinput_config_dwt_state
> > libinput_device_config_dwt_get_default_enabled(struct libinput_device 
> > *device);
> > 
> > +/**
> > + * @ingroup config
> > + *
> > + * Check whether a device can have a custom rotation applied.
> > + *
> > + * @param device The device to configure
> > + * @return Non-zero if a device can be rotated, zero otherwise.
> > + *
> > + * @see libinput_device_config_rotation_set_angle
> > + * @see libinput_device_config_rotation_get_angle
> > + * @see libinput_device_config_rotation_get_default_angle
> > + */
> > +int
> > +libinput_device_config_rotation_is_available(struct libinput_device 
> > *device);
> > +
> > +/**
> > + * @ingroup config
> > + *
> > + * Set the rotation of a device in degrees clockwise off the logical 
> > neutral
> > + * position. Any subsequent motion events are adjusted according to the
> > + * given provided.
> 
> The last sentence here is confusing. Did you mean according to the angle?
> 
> 
> > + *
> > + * The angle has to be in the range of [0, 360[ degrees, otherwise this
> > + * function returns LIBINPUT_CONFIG_STATUS_INVALID. If the angle is a
> > + * multiple of 360 or negative, the caller must ensure the correct ranging
> > + * before calling this function.
> > + *
> > + * libinput guarantees that this function accepts multiples of 90 degrees.
> > + * If a value is within the [0, 360[ range but not a multiple of 90 
> > degrees,
> > + * this function may return LIBINPUT_CONFIG_STATUS_INVALID if the 
> > underlying
> > + * device or implementation does not support finer-grained rotation angles.
> > + *
> > + * The rotation angle is applied to all motion events emitted by the 
> > device.
> > + * Thus, rotating the device also changes the angle required or presented 
> > by
> > + * scrolling, gestures, etc.
> > + *
> > + * @param device The device to configure
> > + * @param degrees_cw The angle in degrees clockwise
> > + * @return A config status code. Setting a rotation of 0 degrees on a
> > + * device that does not support rotation always succeeds.
> > + *
> > + * @see libinput_device_config_rotation_is_available
> > + * @see libinput_device_config_rotation_get_angle
> > + * @see libinput_device_config_rotation_get_default_angle
> > + */
> > +enum libinput_config_status
> > +libinput_device_config_rotation_set_angle(struct libinput_device *device,
> > +                                     unsigned int degrees_cw);
> > +
> > +/**
> > + * @ingroup config
> > + *
> > + * Get the current rotation of a device in degrees clockwise off the 
> > logical
> > + * neutral position. If this device does not support rotation, the return
> > + * value is always 0.
> > + *
> > + * @param device The device to configure
> > + * @return The angle in degrees clockwise
> > + *
> > + * @see libinput_device_config_rotation_is_available
> > + * @see libinput_device_config_rotation_set_angle
> > + * @see libinput_device_config_rotation_get_default_angle
> > + */
> > +unsigned int
> > +libinput_device_config_rotation_get_angle(struct libinput_device *device);
> > +
> > +/**
> > + * @ingroup config
> > + *
> > + * Get the default rotation of a device in degrees clockwise off the 
> > logical
> > + * neutral position. If this device does not support rotation, the return
> > + * value is always 0.
> > + *
> > + * @param device The device to configure
> > + * @return The default angle in degrees clockwise
> > + *
> > + * @see libinput_device_config_rotation_is_available
> > + * @see libinput_device_config_rotation_set_angle
> > + * @see libinput_device_config_rotation_get_angle
> > + */
> > +unsigned int
> > +libinput_device_config_rotation_get_default_angle(struct libinput_device 
> > *device);
> > +
> > #ifdef __cplusplus
> > }
> > #endif
> > diff --git a/src/libinput.sym b/src/libinput.sym
> > index ca1baba..a373c8f 100644
> > --- a/src/libinput.sym
> > +++ b/src/libinput.sym
> > @@ -236,6 +236,10 @@ LIBINPUT_1.2 {
> > } LIBINPUT_1.1;
> > 
> > LIBINPUT_1.3 {
> > +   libinput_device_config_rotation_get_angle;
> > +   libinput_device_config_rotation_get_default_angle;
> > +   libinput_device_config_rotation_is_available;
> > +   libinput_device_config_rotation_set_angle;
> >     libinput_device_tablet_pad_get_num_buttons;
> >     libinput_device_tablet_pad_get_num_rings;
> >     libinput_device_tablet_pad_get_num_strips;
> > diff --git a/test/Makefile.am b/test/Makefile.am
> > index 9b67818..f0ac855 100644
> > --- a/test/Makefile.am
> > +++ b/test/Makefile.am
> > @@ -80,6 +80,7 @@ run_tests = \
> >     test-gestures \
> >     test-pointer \
> >     test-touch \
> > +   test-trackball \
> >     test-trackpoint \
> >     test-udev \
> >     test-path \
> > @@ -144,6 +145,10 @@ test_trackpoint_SOURCES = trackpoint.c
> > test_trackpoint_LDADD = $(TEST_LIBS)
> > test_trackpoint_LDFLAGS = -no-install
> > 
> > +test_trackball_SOURCES = trackball.c
> > +test_trackball_LDADD = $(TEST_LIBS)
> > +test_trackball_LDFLAGS = -no-install
> > +
> > test_misc_SOURCES = misc.c
> > test_misc_CFLAGS= $(AM_CFLAGS) 
> > -DLIBINPUT_LT_VERSION="\"$(LIBINPUT_LT_VERSION)\""
> > test_misc_LDADD = $(TEST_LIBS)
> > diff --git a/test/trackball.c b/test/trackball.c
> > new file mode 100644
> > index 0000000..d3238cf
> > --- /dev/null
> > +++ b/test/trackball.c
> > @@ -0,0 +1,273 @@
> > +/*
> > + * 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.
> > + */
> > +
> > +#include <config.h>
> > +
> > +#include <check.h>
> > +#include <errno.h>
> > +#include <fcntl.h>
> > +#include <libinput.h>
> > +#include <unistd.h>
> > +
> > +#include "libinput-util.h"
> > +#include "litest.h"
> > +
> > +START_TEST(trackball_rotation_config_defaults)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput_device *device = dev->libinput_device;
> > +   int angle;
> > +
> > +   ck_assert(libinput_device_config_rotation_is_available(device));
> > +
> > +   angle = libinput_device_config_rotation_get_angle(device);
> > +   ck_assert_int_eq(angle, 0);
> > +   angle = libinput_device_config_rotation_get_default_angle(device);
> > +   ck_assert_int_eq(angle, 0);
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_config_invalid_range)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput_device *device = dev->libinput_device;
> > +   enum libinput_config_status status;
> > +
> > +   status = libinput_device_config_rotation_set_angle(device, 360);
> > +   ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> > +   status = libinput_device_config_rotation_set_angle(device, 361);
> > +   ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> > +   status = libinput_device_config_rotation_set_angle(device, -1);
> > +   ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_config_no_rotation)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput_device *device = dev->libinput_device;
> > +   enum libinput_config_status status;
> > +   int angle;
> > +
> > +   ck_assert(!libinput_device_config_rotation_is_available(device));
> > +
> > +   angle = libinput_device_config_rotation_get_angle(device);
> > +   ck_assert_int_eq(angle, 0);
> > +   angle = libinput_device_config_rotation_get_default_angle(device);
> > +   ck_assert_int_eq(angle, 0);
> > +
> > +   /* 0 always succeeds */
> > +   status = libinput_device_config_rotation_set_angle(device, 0);
> > +   ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
> > +
> > +   for (angle = 1; angle < 360; angle++) {
> > +           if (angle % 90 == 0)
> > +                   continue;
> > +           status = libinput_device_config_rotation_set_angle(device,
> > +                                                              angle);
> > +           ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
> > +   }
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_config_right_angle)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput_device *device = dev->libinput_device;
> > +   enum libinput_config_status status;
> > +   int angle;
> > +
> > +   ck_assert(libinput_device_config_rotation_is_available(device));
> > +
> > +   for (angle = 0; angle < 360; angle += 90) {
> > +           status = libinput_device_config_rotation_set_angle(device,
> > +                                                              angle);
> > +           ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
> > +   }
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_config_odd_angle)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput_device *device = dev->libinput_device;
> > +   enum libinput_config_status status;
> > +   int angle;
> > +
> > +   ck_assert(libinput_device_config_rotation_is_available(device));
> > +
> > +   for (angle = 0; angle < 360; angle++) {
> > +           if (angle % 90 == 0)
> > +                   continue;
> > +           status = libinput_device_config_rotation_set_angle(device,
> > +                                                              angle);
> > +           ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
> > +   }
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_x)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput *li = dev->libinput;
> > +   struct libinput_device *device = dev->libinput_device;
> > +   struct libinput_event *event;
> > +   struct libinput_event_pointer *ptrev;
> > +   int angle;
> > +   double dx, dy;
> > +
> > +   litest_drain_events(li);
> > +
> > +   for (angle = 0; angle < 360; angle++) {
> > +           libinput_device_config_rotation_set_angle(device, angle);
> > +
> > +           litest_event(dev, EV_REL, REL_X, 1);
> > +           litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +           libinput_dispatch(li);
> > +
> > +           event = libinput_get_event(li);
> > +           ptrev = litest_is_motion_event(event);
> > +
> > +           /* Test unaccelerated because pointer accel may mangle the
> > +              other coords */
> > +           dx = libinput_event_pointer_get_dx_unaccelerated(ptrev);
> > +           dy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
> > +
> > +           switch (angle) {
> > +           case 0:
> > +                   ck_assert_double_eq(dx, 1.0);
> > +                   ck_assert_double_eq(dy, 0.0);
> > +                   break;
> > +           case 90:
> > +                   ck_assert_double_eq(dx, 0.0);
> > +                   ck_assert_double_eq(dy, 1.0);
> > +                   break;
> > +           case 180:
> > +                   ck_assert_double_eq(dx, -1.0);
> > +                   ck_assert_double_eq(dy, 0.0);
> > +                   break;
> > +           case 270:
> > +                   ck_assert_double_eq(dx, 0.0);
> > +                   ck_assert_double_eq(dy, -1.0);
> > +                   break;
> > +           }
> > +           libinput_event_destroy(event);
> > +   }
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_y)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput *li = dev->libinput;
> > +   struct libinput_device *device = dev->libinput_device;
> > +   struct libinput_event *event;
> > +   struct libinput_event_pointer *ptrev;
> > +   int angle;
> > +   double dx, dy;
> > +
> > +   litest_drain_events(li);
> > +
> > +   for (angle = 0; angle < 360; angle++) {
> > +           libinput_device_config_rotation_set_angle(device, angle);
> > +
> > +           litest_event(dev, EV_REL, REL_Y, 1);
> > +           litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +           libinput_dispatch(li);
> > +
> > +           event = libinput_get_event(li);
> > +           ptrev = litest_is_motion_event(event);
> > +
> > +           /* Test unaccelerated because pointer accel may mangle the
> > +              other coords */
> > +           dx = libinput_event_pointer_get_dx_unaccelerated(ptrev);
> > +           dy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
> > +
> > +           switch (angle) {
> > +           case 0:
> > +                   ck_assert_double_eq(dx, 0.0);
> > +                   ck_assert_double_eq(dy, 1.0);
> > +                   break;
> > +           case 90:
> > +                   ck_assert_double_eq(dx, -1.0);
> > +                   ck_assert_double_eq(dy, 0.0);
> > +                   break;
> > +           case 180:
> > +                   ck_assert_double_eq(dx, 0.0);
> > +                   ck_assert_double_eq(dy, -1.0);
> > +                   break;
> > +           case 270:
> > +                   ck_assert_double_eq(dx, 1.0);
> > +                   ck_assert_double_eq(dy, 0.0);
> > +                   break;
> > +           }
> > +           libinput_event_destroy(event);
> > +   }
> > +}
> > +END_TEST
> > +
> > +START_TEST(trackball_rotation_accel)
> > +{
> > +   struct litest_device *dev = litest_current_device();
> > +   struct libinput *li = dev->libinput;
> > +   struct libinput_device *device = dev->libinput_device;
> > +   struct libinput_event *event;
> > +   struct libinput_event_pointer *ptrev;
> > +   double dx, dy;
> > +
> > +   litest_drain_events(li);
> > +
> > +   /* Pointer accel mangles the coordinates, so we only test one angle
> > +    * and rely on the unaccelerated tests above to warn us when
> > +    * something's off */
> > +   libinput_device_config_rotation_set_angle(device, 90);
> > +
> > +   litest_event(dev, EV_REL, REL_Y, 1);
> > +   litest_event(dev, EV_REL, REL_X, 1);
> > +   litest_event(dev, EV_SYN, SYN_REPORT, 0);
> > +   libinput_dispatch(li);
> > +
> > +   event = libinput_get_event(li);
> > +   ptrev = litest_is_motion_event(event);
> > +
> > +   dx = libinput_event_pointer_get_dx(ptrev);
> > +   dy = libinput_event_pointer_get_dy(ptrev);
> > +
> > +   ck_assert_double_lt(dx, 0.0);
> > +   ck_assert_double_gt(dy, 0.0);
> > +   libinput_event_destroy(event);
> > +}
> > +END_TEST
> > +
> > +void
> > +litest_setup_tests(void)
> > +{
> > +   litest_add("trackball:rotation", trackball_rotation_config_defaults, 
> > LITEST_TRACKBALL, LITEST_ANY);
> > +   litest_add("trackball:rotation", 
> > trackball_rotation_config_invalid_range, LITEST_TRACKBALL, LITEST_ANY);
> > +   litest_add("trackball:rotation", trackball_rotation_config_no_rotation, 
> > LITEST_ANY, LITEST_TRACKBALL);
> > +   litest_add("trackball:rotation", trackball_rotation_config_right_angle, 
> > LITEST_TRACKBALL, LITEST_ANY);
> > +   litest_add("trackball:rotation", trackball_rotation_config_odd_angle, 
> > LITEST_TRACKBALL, LITEST_ANY);
> > +   litest_add("trackball:rotation", trackball_rotation_x, 
> > LITEST_TRACKBALL, LITEST_ANY);
> > +   litest_add("trackball:rotation", trackball_rotation_y, 
> > LITEST_TRACKBALL, LITEST_ANY);
> > +   litest_add("trackball:rotation", trackball_rotation_accel, 
> > LITEST_TRACKBALL, LITEST_ANY);
> > +}
> > -- 
> > 2.7.4
> > 
> > _______________________________________________
> > wayland-devel mailing list
> > wayland-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/wayland-devel
> 
> 
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to