mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-04 03:50:14 +01:00
Merge branch 'wip/trackball-rotation'
This commit is contained in:
commit
1c276f7f4a
12 changed files with 560 additions and 20 deletions
110
src/evdev.c
110
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.
|
||||
|
|
@ -1715,26 +1783,30 @@ evdev_read_model_flags(struct evdev_device *device)
|
|||
const char *property;
|
||||
enum evdev_device_model model;
|
||||
} model_map[] = {
|
||||
{ "LIBINPUT_MODEL_LENOVO_X230", EVDEV_MODEL_LENOVO_X230 },
|
||||
{ "LIBINPUT_MODEL_LENOVO_X220_TOUCHPAD_FW81", EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 },
|
||||
{ "LIBINPUT_MODEL_CHROMEBOOK", EVDEV_MODEL_CHROMEBOOK },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_BONOBO", EVDEV_MODEL_SYSTEM76_BONOBO },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_GALAGO", EVDEV_MODEL_SYSTEM76_GALAGO },
|
||||
{ "LIBINPUT_MODEL_SYSTEM76_KUDU", EVDEV_MODEL_SYSTEM76_KUDU },
|
||||
{ "LIBINPUT_MODEL_CLEVO_W740SU", EVDEV_MODEL_CLEVO_W740SU },
|
||||
{ "LIBINPUT_MODEL_APPLE_TOUCHPAD", EVDEV_MODEL_APPLE_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_WACOM_TOUCHPAD", EVDEV_MODEL_WACOM_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_ALPS_TOUCHPAD", EVDEV_MODEL_ALPS_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD", EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_JUMPING_SEMI_MT", EVDEV_MODEL_JUMPING_SEMI_MT },
|
||||
{ "LIBINPUT_MODEL_ELANTECH_TOUCHPAD", EVDEV_MODEL_ELANTECH_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD", EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD },
|
||||
{ "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },
|
||||
{ "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA },
|
||||
{ "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE },
|
||||
{ "LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD", EVDEV_MODEL_LENOVO_T450_TOUCHPAD },
|
||||
{ "LIBINPUT_MODEL_WOBBLY_TOUCHPAD", EVDEV_MODEL_WOBBLY_TOUCHPAD },
|
||||
#define MODEL(name) { "LIBINPUT_MODEL_" #name, EVDEV_MODEL_##name }
|
||||
MODEL(LENOVO_X230),
|
||||
MODEL(LENOVO_X230),
|
||||
MODEL(LENOVO_X220_TOUCHPAD_FW81),
|
||||
MODEL(CHROMEBOOK),
|
||||
MODEL(SYSTEM76_BONOBO),
|
||||
MODEL(SYSTEM76_GALAGO),
|
||||
MODEL(SYSTEM76_KUDU),
|
||||
MODEL(CLEVO_W740SU),
|
||||
MODEL(APPLE_TOUCHPAD),
|
||||
MODEL(WACOM_TOUCHPAD),
|
||||
MODEL(ALPS_TOUCHPAD),
|
||||
MODEL(SYNAPTICS_SERIAL_TOUCHPAD),
|
||||
MODEL(JUMPING_SEMI_MT),
|
||||
MODEL(ELANTECH_TOUCHPAD),
|
||||
MODEL(APPLE_INTERNAL_KEYBOARD),
|
||||
MODEL(CYBORG_RAT),
|
||||
MODEL(CYAPA),
|
||||
MODEL(ALPS_RUSHMORE),
|
||||
MODEL(LENOVO_T450_TOUCHPAD),
|
||||
MODEL(WOBBLY_TOUCHPAD),
|
||||
MODEL(TRACKBALL),
|
||||
{ NULL, EVDEV_MODEL_DEFAULT },
|
||||
#undef MODEL
|
||||
};
|
||||
const struct model_map *m = model_map;
|
||||
uint32_t model_flags = 0;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ enum evdev_device_model {
|
|||
EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16),
|
||||
EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
|
||||
EVDEV_MODEL_WOBBLY_TOUCHPAD = (1 << 18),
|
||||
EVDEV_MODEL_TRACKBALL = (1 << 19),
|
||||
};
|
||||
|
||||
struct mt_slot {
|
||||
|
|
@ -288,6 +289,13 @@ struct evdev_dispatch {
|
|||
struct evdev_dispatch_interface *interface;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 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
|
||||
|
|
|
|||
|
|
@ -252,3 +252,10 @@ LIBINPUT_1.3 {
|
|||
libinput_event_tablet_pad_get_time;
|
||||
libinput_event_tablet_pad_get_time_usec;
|
||||
} LIBINPUT_1.2;
|
||||
|
||||
LIBINPUT_1.4 {
|
||||
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_1.3;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ static int events[] = {
|
|||
|
||||
struct litest_test_device litest_logitech_trackball_device = {
|
||||
.type = LITEST_LOGITECH_TRACKBALL,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_TRACKBALL,
|
||||
.shortname = "logitech trackball",
|
||||
.setup = litest_logitech_trackball_setup,
|
||||
.interface = NULL,
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ enum litest_device_feature {
|
|||
LITEST_TABLET_PAD = 1 << 21,
|
||||
LITEST_RING = 1 << 22,
|
||||
LITEST_STRIP = 1 << 23,
|
||||
LITEST_TRACKBALL = 1 << 24,
|
||||
};
|
||||
|
||||
struct litest_device {
|
||||
|
|
|
|||
273
test/trackball.c
Normal file
273
test/trackball.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -146,3 +146,9 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrkudp1*
|
|||
##########################################
|
||||
libinput:touchpad:input:b0003v056Ap*
|
||||
LIBINPUT_MODEL_WACOM_TOUCHPAD=1
|
||||
|
||||
##########################################
|
||||
# Anything that has trackball in the name
|
||||
##########################################
|
||||
libinput:name:*Trackball*:dmi:*
|
||||
LIBINPUT_MODEL_TRACKBALL=1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue