2 * Copyright © 2013 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 #include "libinput-util.h"
37 test_relative_event(struct litest_device *dev, int dx, int dy)
39 struct libinput *li = dev->libinput;
40 struct libinput_event *event;
41 struct libinput_event_pointer *ptrev;
44 double expected_length;
48 /* Send two deltas, as the first one may be eaten up by an
49 * acceleration filter. */
50 litest_event(dev, EV_REL, REL_X, dx);
51 litest_event(dev, EV_REL, REL_Y, dy);
52 litest_event(dev, EV_SYN, SYN_REPORT, 0);
53 litest_event(dev, EV_REL, REL_X, dx);
54 litest_event(dev, EV_REL, REL_Y, dy);
55 litest_event(dev, EV_SYN, SYN_REPORT, 0);
57 libinput_dispatch(li);
59 event = libinput_get_event(li);
60 ck_assert(event != NULL);
61 ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_MOTION);
63 ptrev = libinput_event_get_pointer_event(event);
64 ck_assert(ptrev != NULL);
66 expected_length = sqrt(4 * dx*dx + 4 * dy*dy);
67 expected_dir = atan2(dx, dy);
69 ev_dx = libinput_event_pointer_get_dx(ptrev);
70 ev_dy = libinput_event_pointer_get_dy(ptrev);
71 actual_length = sqrt(ev_dx*ev_dx + ev_dy*ev_dy);
72 actual_dir = atan2(ev_dx, ev_dy);
74 /* Check the length of the motion vector (tolerate 1.0 indifference). */
75 ck_assert(fabs(expected_length) >= actual_length);
77 /* Check the direction of the motion vector (tolerate 2π/4 radians
79 ck_assert(fabs(expected_dir - actual_dir) < M_PI_2);
81 libinput_event_destroy(event);
83 litest_drain_events(dev->libinput);
86 START_TEST(pointer_motion_relative)
88 struct litest_device *dev = litest_current_device();
90 litest_drain_events(dev->libinput);
92 test_relative_event(dev, 1, 0);
93 test_relative_event(dev, 1, 1);
94 test_relative_event(dev, 1, -1);
95 test_relative_event(dev, 0, 1);
97 test_relative_event(dev, -1, 0);
98 test_relative_event(dev, -1, 1);
99 test_relative_event(dev, -1, -1);
100 test_relative_event(dev, 0, -1);
105 test_button_event(struct litest_device *dev, unsigned int button, int state)
107 struct libinput *li = dev->libinput;
108 struct libinput_event *event;
109 struct libinput_event_pointer *ptrev;
111 litest_event(dev, EV_KEY, button, state);
112 litest_event(dev, EV_SYN, SYN_REPORT, 0);
114 libinput_dispatch(li);
116 event = libinput_get_event(li);
117 ck_assert(event != NULL);
118 ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_BUTTON);
120 ptrev = libinput_event_get_pointer_event(event);
121 ck_assert(ptrev != NULL);
122 ck_assert_int_eq(libinput_event_pointer_get_button(ptrev), button);
123 ck_assert_int_eq(libinput_event_pointer_get_button_state(ptrev),
125 LIBINPUT_BUTTON_STATE_PRESSED :
126 LIBINPUT_BUTTON_STATE_RELEASED);
127 libinput_event_destroy(event);
130 START_TEST(pointer_button)
132 struct litest_device *dev = litest_current_device();
134 litest_drain_events(dev->libinput);
136 test_button_event(dev, BTN_LEFT, 1);
137 test_button_event(dev, BTN_LEFT, 0);
139 /* press it twice for good measure */
140 test_button_event(dev, BTN_LEFT, 1);
141 test_button_event(dev, BTN_LEFT, 0);
143 if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_RIGHT)) {
144 test_button_event(dev, BTN_RIGHT, 1);
145 test_button_event(dev, BTN_RIGHT, 0);
148 if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) {
149 test_button_event(dev, BTN_MIDDLE, 1);
150 test_button_event(dev, BTN_MIDDLE, 0);
155 START_TEST(pointer_button_auto_release)
157 struct libinput *libinput;
158 struct litest_device *dev;
159 struct libinput_event *event;
160 enum libinput_event_type type;
161 struct libinput_event_pointer *pevent;
166 { .code = BTN_LEFT, },
167 { .code = BTN_MIDDLE, },
168 { .code = BTN_EXTRA, },
169 { .code = BTN_SIDE, },
170 { .code = BTN_BACK, },
171 { .code = BTN_FORWARD, },
174 int events[2 * (ARRAY_LENGTH(buttons) + 1)];
179 /* Enable all tested buttons on the device */
180 for (i = 0; i < 2 * ARRAY_LENGTH(buttons);) {
181 button = buttons[i / 2].code;
182 events[i++] = EV_KEY;
183 events[i++] = button;
188 libinput = litest_create_context();
189 dev = litest_add_device_with_overrides(libinput,
194 litest_drain_events(libinput);
196 /* Send pressed events, without releasing */
197 for (i = 0; i < ARRAY_LENGTH(buttons); ++i) {
198 test_button_event(dev, buttons[i].code, 1);
201 litest_drain_events(libinput);
203 /* "Disconnect" device */
204 litest_delete_device(dev);
206 /* Mark all released buttons until device is removed */
208 event = libinput_get_event(libinput);
209 ck_assert_notnull(event);
210 type = libinput_event_get_type(event);
212 if (type == LIBINPUT_EVENT_DEVICE_REMOVED) {
213 libinput_event_destroy(event);
217 ck_assert_int_eq(type, LIBINPUT_EVENT_POINTER_BUTTON);
218 pevent = libinput_event_get_pointer_event(event);
219 ck_assert_int_eq(libinput_event_pointer_get_button_state(pevent),
220 LIBINPUT_BUTTON_STATE_RELEASED);
221 button = libinput_event_pointer_get_button(pevent);
224 for (i = 0; i < ARRAY_LENGTH(buttons); ++i) {
225 if (buttons[i].code == button) {
226 ck_assert_int_eq(buttons[i].released, 0);
227 buttons[i].released = 1;
231 ck_assert_int_eq(valid_code, 1);
232 libinput_event_destroy(event);
235 /* Check that all pressed buttons has been released. */
236 for (i = 0; i < ARRAY_LENGTH(buttons); ++i) {
237 ck_assert_int_eq(buttons[i].released, 1);
240 libinput_unref(libinput);
245 test_wheel_event(struct litest_device *dev, int which, int amount)
247 struct libinput *li = dev->libinput;
248 struct libinput_event *event;
249 struct libinput_event_pointer *ptrev;
251 /* the current evdev implementation scales the scroll wheel events
253 const int scroll_step = 10;
254 int expected = amount * scroll_step;
256 /* mouse scroll wheels are 'upside down' */
257 if (which == REL_WHEEL)
259 litest_event(dev, EV_REL, which, amount);
260 litest_event(dev, EV_SYN, SYN_REPORT, 0);
262 libinput_dispatch(li);
264 event = libinput_get_event(li);
265 ck_assert(event != NULL);
266 ck_assert_int_eq(libinput_event_get_type(event),
267 LIBINPUT_EVENT_POINTER_AXIS);
269 ptrev = libinput_event_get_pointer_event(event);
270 ck_assert(ptrev != NULL);
271 ck_assert_int_eq(libinput_event_pointer_get_axis(ptrev),
273 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL :
274 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
275 ck_assert_int_eq(libinput_event_pointer_get_axis_value(ptrev), expected);
276 libinput_event_destroy(event);
279 START_TEST(pointer_scroll_wheel)
281 struct litest_device *dev = litest_current_device();
283 litest_drain_events(dev->libinput);
285 test_wheel_event(dev, REL_WHEEL, -1);
286 test_wheel_event(dev, REL_WHEEL, 1);
288 test_wheel_event(dev, REL_WHEEL, -5);
289 test_wheel_event(dev, REL_WHEEL, 6);
291 if (libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL)) {
292 test_wheel_event(dev, REL_HWHEEL, -1);
293 test_wheel_event(dev, REL_HWHEEL, 1);
295 test_wheel_event(dev, REL_HWHEEL, -5);
296 test_wheel_event(dev, REL_HWHEEL, 6);
301 START_TEST(pointer_seat_button_count)
303 const int num_devices = 4;
304 struct litest_device *devices[num_devices];
305 struct libinput *libinput;
306 struct libinput_event *ev;
307 struct libinput_event_pointer *tev;
309 int seat_button_count;
310 int expected_seat_button_count = 0;
311 char device_name[255];
313 libinput = litest_create_context();
314 for (i = 0; i < num_devices; ++i) {
315 sprintf(device_name, "litest Generic mouse (%d)", i);
316 devices[i] = litest_add_device_with_overrides(libinput,
322 for (i = 0; i < num_devices; ++i)
323 litest_button_click(devices[i], BTN_LEFT, true);
325 libinput_dispatch(libinput);
326 while ((ev = libinput_get_event(libinput))) {
327 if (libinput_event_get_type(ev) !=
328 LIBINPUT_EVENT_POINTER_BUTTON) {
329 libinput_event_destroy(ev);
330 libinput_dispatch(libinput);
334 tev = libinput_event_get_pointer_event(ev);
335 ck_assert_notnull(tev);
336 ck_assert_int_eq(libinput_event_pointer_get_button(tev),
338 ck_assert_int_eq(libinput_event_pointer_get_button_state(tev),
339 LIBINPUT_BUTTON_STATE_PRESSED);
341 ++expected_seat_button_count;
343 libinput_event_pointer_get_seat_button_count(tev);
344 ck_assert_int_eq(expected_seat_button_count, seat_button_count);
346 libinput_event_destroy(ev);
347 libinput_dispatch(libinput);
350 ck_assert_int_eq(seat_button_count, num_devices);
352 for (i = 0; i < num_devices; ++i)
353 litest_button_click(devices[i], BTN_LEFT, false);
355 libinput_dispatch(libinput);
356 while ((ev = libinput_get_event(libinput))) {
357 if (libinput_event_get_type(ev) !=
358 LIBINPUT_EVENT_POINTER_BUTTON) {
359 libinput_event_destroy(ev);
360 libinput_dispatch(libinput);
364 tev = libinput_event_get_pointer_event(ev);
365 ck_assert_notnull(tev);
366 ck_assert_int_eq(libinput_event_pointer_get_button(tev),
368 ck_assert_int_eq(libinput_event_pointer_get_button_state(tev),
369 LIBINPUT_BUTTON_STATE_RELEASED);
371 --expected_seat_button_count;
373 libinput_event_pointer_get_seat_button_count(tev);
374 ck_assert_int_eq(expected_seat_button_count, seat_button_count);
376 libinput_event_destroy(ev);
377 libinput_dispatch(libinput);
380 ck_assert_int_eq(seat_button_count, 0);
382 for (i = 0; i < num_devices; ++i)
383 litest_delete_device(devices[i]);
384 libinput_unref(libinput);
388 int main (int argc, char **argv) {
390 litest_add("pointer:motion", pointer_motion_relative, LITEST_POINTER, LITEST_ANY);
391 litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
392 litest_add_no_device("pointer:button_auto_release", pointer_button_auto_release);
393 litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_ANY);
394 litest_add_no_device("pointer:seat button count", pointer_seat_button_count);
396 return litest_run(argc, argv);