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