test-touchpad.c 166 KB
Newer Older
1 2 3
/*
 * Copyright © 2014 Red Hat, Inc.
 *
4 5 6 7 8 9
 * 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:
10
 *
11 12 13 14 15 16 17 18 19 20 21
 * 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.
22 23 24 25 26 27 28 29 30 31 32 33 34
 */

#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"

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
static inline bool
has_disable_while_typing(struct litest_device *device)
{
	return libinput_device_config_dwt_is_available(device->libinput_device);
}

static inline struct litest_device *
dwt_init_paired_keyboard(struct libinput *li,
			 struct litest_device *touchpad)
{
	enum litest_device_type which = LITEST_KEYBOARD;

	if (libevdev_get_id_vendor(touchpad->evdev) == VENDOR_ID_APPLE)
		which = LITEST_APPLE_KEYBOARD;

	if (libevdev_get_id_vendor(touchpad->evdev) == VENDOR_ID_CHICONY)
		which = LITEST_ACER_HAWAII_KEYBOARD;

	return litest_add_device(li, which);
}

56 57 58 59 60 61 62
START_TEST(touchpad_1fg_motion)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;

63
	litest_disable_tap(dev->libinput_device);
64

65 66 67
	litest_drain_events(li);

	litest_touch_down(dev, 0, 50, 50);
68
	litest_touch_move_to(dev, 0, 50, 50, 80, 50, 20, 0);
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
	litest_touch_up(dev, 0);

	libinput_dispatch(li);

	event = libinput_get_event(li);
	ck_assert(event != NULL);

	while (event) {
		ck_assert_int_eq(libinput_event_get_type(event),
				 LIBINPUT_EVENT_POINTER_MOTION);

		ptrev = libinput_event_get_pointer_event(event);
		ck_assert_int_ge(libinput_event_pointer_get_dx(ptrev), 0);
		ck_assert_int_eq(libinput_event_pointer_get_dy(ptrev), 0);
		libinput_event_destroy(event);
		event = libinput_get_event(li);
	}
}
END_TEST

START_TEST(touchpad_2fg_no_motion)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;

95 96 97
	libinput_device_config_tap_set_enabled(dev->libinput_device,
					       LIBINPUT_CONFIG_TAP_DISABLED);

98 99
	litest_drain_events(li);

100 101
	litest_touch_down(dev, 0, 20, 20);
	litest_touch_down(dev, 1, 70, 20);
102 103
	litest_touch_move_to(dev, 0, 20, 20, 80, 80, 20, 0);
	litest_touch_move_to(dev, 1, 70, 20, 80, 50, 20, 0);
104
	litest_touch_up(dev, 1);
105
	litest_touch_up(dev, 0);
106 107 108 109 110 111 112 113 114 115 116 117 118

	libinput_dispatch(li);

	event = libinput_get_event(li);
	while (event) {
		ck_assert_int_ne(libinput_event_get_type(event),
				 LIBINPUT_EVENT_POINTER_MOTION);
		libinput_event_destroy(event);
		event = libinput_get_event(li);
	}
}
END_TEST

119
static void
120
test_2fg_scroll(struct litest_device *dev, double dx, double dy, int want_sleep)
121
{
122 123
	struct libinput *li = dev->libinput;

124 125
	litest_touch_down(dev, 0, 49, 50);
	litest_touch_down(dev, 1, 51, 50);
126

127
	litest_touch_move_two_touches(dev, 49, 50, 51, 50, dx, dy, 10, 0);
128

129
	/* Avoid a small scroll being seen as a tap */
130
	if (want_sleep) {
131
		libinput_dispatch(li);
132
		litest_timeout_tap();
133 134 135
		libinput_dispatch(li);
	}

136 137
	litest_touch_up(dev, 1);
	litest_touch_up(dev, 0);
138 139

	libinput_dispatch(li);
140 141 142 143 144 145 146
}

START_TEST(touchpad_2fg_scroll)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

147
	if (!litest_has_2fg_scroll(dev))
148 149
		return;

150
	litest_enable_2fg_scroll(dev);
151 152
	litest_drain_events(li);

153
	test_2fg_scroll(dev, 0.1, 40, 0);
154
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 10);
155
	test_2fg_scroll(dev, 0.1, -40, 0);
156
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -10);
157
	test_2fg_scroll(dev, 40, 0.1, 0);
158
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 10);
159
	test_2fg_scroll(dev, -40, 0.1, 0);
160
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -10);
161 162

	/* 2fg scroll smaller than the threshold should not generate events */
163
	test_2fg_scroll(dev, 0.1, 0.1, 1);
164
	litest_assert_empty_queue(li);
165 166 167
}
END_TEST

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
START_TEST(touchpad_2fg_scroll_diagonal)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;
	int i;

	if (!litest_has_2fg_scroll(dev))
		return;

	litest_enable_2fg_scroll(dev);
	litest_drain_events(li);

	litest_touch_down(dev, 0, 45, 30);
	litest_touch_down(dev, 1, 55, 30);

	litest_touch_move_two_touches(dev, 45, 30, 55, 30, 10, 10, 10, 0);
	libinput_dispatch(li);
	litest_wait_for_event_of_type(li,
				      LIBINPUT_EVENT_POINTER_AXIS,
				      -1);
	litest_drain_events(li);

	/* get rid of any touch history still adding x deltas sideways */
	for (i = 0; i < 5; i++)
		litest_touch_move(dev, 0, 55, 41 + i);
	litest_drain_events(li);

	for (i = 6; i < 10; i++) {
		litest_touch_move(dev, 0, 55, 41 + i);
		libinput_dispatch(li);

		event = libinput_get_event(li);
		ptrev = litest_is_axis_event(event,
				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
				LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
		ck_assert(!libinput_event_pointer_has_axis(ptrev,
				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL));
		libinput_event_destroy(event);
	}

	litest_touch_up(dev, 1);
	litest_touch_up(dev, 0);
	libinput_dispatch(li);
}
END_TEST

216 217 218 219 220 221
START_TEST(touchpad_2fg_scroll_slow_distance)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;
222 223
	double width, height;
	double y_move = 100;
224

225
	if (!litest_has_2fg_scroll(dev))
226 227
		return;

228
	/* We want to move > 5 mm. */
229 230 231 232
	ck_assert_int_eq(libinput_device_get_size(dev->libinput_device,
						  &width,
						  &height), 0);
	y_move = 100.0/height * 7;
233

234
	litest_enable_2fg_scroll(dev);
235 236
	litest_drain_events(li);

237 238
	litest_touch_down(dev, 0, 49, 50);
	litest_touch_down(dev, 1, 51, 50);
239
	litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, y_move, 100, 10);
240 241 242 243 244 245 246 247 248
	litest_touch_up(dev, 1);
	litest_touch_up(dev, 0);
	libinput_dispatch(li);

	event = libinput_get_event(li);
	ck_assert_notnull(event);

	/* last event is value 0, tested elsewhere */
	while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
249
		double axisval;
250 251 252 253
		ck_assert_int_eq(libinput_event_get_type(event),
				 LIBINPUT_EVENT_POINTER_AXIS);
		ptrev = libinput_event_get_pointer_event(event);

254 255 256
		axisval = libinput_event_pointer_get_axis_value(ptrev,
				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
		ck_assert(axisval > 0.0);
257 258 259 260

		/* this is to verify we test the right thing, if the value
		   is greater than scroll.threshold we triggered the wrong
		   condition */
261
		ck_assert(axisval < 5.0);
262 263 264 265 266 267 268 269 270 271

		libinput_event_destroy(event);
		event = libinput_get_event(li);
	}

	litest_assert_empty_queue(li);
	libinput_event_destroy(event);
}
END_TEST

272 273 274 275 276 277 278
START_TEST(touchpad_2fg_scroll_source)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;

279
	if (!litest_has_2fg_scroll(dev))
280 281
		return;

282
	litest_enable_2fg_scroll(dev);
283 284
	litest_drain_events(li);

285
	test_2fg_scroll(dev, 0, 30, 0);
286 287 288 289 290 291 292 293 294 295 296 297 298
	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);

	while ((event = libinput_get_event(li))) {
		ck_assert_int_eq(libinput_event_get_type(event),
				 LIBINPUT_EVENT_POINTER_AXIS);
		ptrev = libinput_event_get_pointer_event(event);
		ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
				 LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
		libinput_event_destroy(event);
	}
}
END_TEST

299 300 301 302 303
START_TEST(touchpad_2fg_scroll_semi_mt)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

304
	if (!litest_has_2fg_scroll(dev))
305 306
		return;

307
	litest_enable_2fg_scroll(dev);
308 309 310 311 312
	litest_drain_events(li);

	litest_touch_down(dev, 0, 20, 20);
	litest_touch_down(dev, 1, 30, 20);
	libinput_dispatch(li);
313 314 315 316 317
	litest_touch_move_two_touches(dev,
				      20, 20,
				      30, 20,
				      30, 40,
				      10, 1);
318 319 320 321 322

	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
}
END_TEST

323 324 325 326 327
START_TEST(touchpad_2fg_scroll_return_to_motion)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

328
	if (!litest_has_2fg_scroll(dev))
329 330
		return;

331
	litest_enable_2fg_scroll(dev);
332 333 334 335
	litest_drain_events(li);

	/* start with motion */
	litest_touch_down(dev, 0, 70, 70);
336
	litest_touch_move_to(dev, 0, 70, 70, 49, 50, 10, 0);
337 338 339
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);

	/* 2fg scroll */
340 341
	litest_touch_down(dev, 1, 51, 50);
	litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, 20, 5, 0);
342
	litest_touch_up(dev, 1);
343 344 345
	libinput_dispatch(li);
	litest_timeout_finger_switch();
	libinput_dispatch(li);
346 347
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);

348
	litest_touch_move_to(dev, 0, 49, 70, 49, 50, 10, 0);
349 350 351
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);

	/* back to 2fg scroll, lifting the other finger */
352 353
	litest_touch_down(dev, 1, 51, 50);
	litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, 20, 5, 0);
354
	litest_touch_up(dev, 0);
355 356 357
	libinput_dispatch(li);
	litest_timeout_finger_switch();
	libinput_dispatch(li);
358 359 360
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);

	/* move with second finger */
361
	litest_touch_move_to(dev, 1, 51, 70, 51, 50, 10, 0);
362 363 364 365 366 367 368
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);

	litest_touch_up(dev, 1);
	litest_assert_empty_queue(li);
}
END_TEST

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
START_TEST(touchpad_scroll_natural_defaults)
{
	struct litest_device *dev = litest_current_device();

	ck_assert_int_ge(libinput_device_config_scroll_has_natural_scroll(dev->libinput_device), 1);
	ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 0);
	ck_assert_int_eq(libinput_device_config_scroll_get_default_natural_scroll_enabled(dev->libinput_device), 0);
}
END_TEST

START_TEST(touchpad_scroll_natural_enable_config)
{
	struct litest_device *dev = litest_current_device();
	enum libinput_config_status status;

	status = libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
	ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 1);

	status = libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 0);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
	ck_assert_int_eq(libinput_device_config_scroll_get_natural_scroll_enabled(dev->libinput_device), 0);
}
END_TEST

394
START_TEST(touchpad_scroll_natural_2fg)
395 396 397 398
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

399
	if (!litest_has_2fg_scroll(dev))
400 401
		return;

402
	litest_enable_2fg_scroll(dev);
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
	litest_drain_events(li);

	libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);

	test_2fg_scroll(dev, 0.1, 40, 0);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -10);
	test_2fg_scroll(dev, 0.1, -40, 0);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 10);
	test_2fg_scroll(dev, 40, 0.1, 0);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -10);
	test_2fg_scroll(dev, -40, 0.1, 0);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 10);

}
END_TEST

419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
START_TEST(touchpad_scroll_natural_edge)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	litest_enable_edge_scroll(dev);
	litest_drain_events(li);

	libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1);

	litest_touch_down(dev, 0, 99, 20);
	litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -4);
	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 99, 80);
	litest_touch_move_to(dev, 0, 99, 80, 99, 20, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4);
	litest_assert_empty_queue(li);

}
END_TEST

448
START_TEST(touchpad_edge_scroll_vert)
449 450 451 452
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

453 454 455 456
	litest_touch_down(dev, 0, 99, 20);
	litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
	litest_touch_up(dev, 0);

457
	litest_drain_events(li);
458
	litest_enable_edge_scroll(dev);
459 460 461 462 463 464

	litest_touch_down(dev, 0, 99, 20);
	litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
465
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4);
466 467 468 469 470 471 472
	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 99, 80);
	litest_touch_move_to(dev, 0, 99, 80, 99, 20, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
473
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -4);
474
	litest_assert_empty_queue(li);
475 476 477
}
END_TEST

478 479 480 481 482 483 484 485
static int
touchpad_has_horiz_edge_scroll_size(struct litest_device *dev)
{
	double width, height;
	int rc;

	rc = libinput_device_get_size(dev->libinput_device, &width, &height);

486
	return rc == 0 && height >= 40;
487 488
}

489 490 491 492 493
START_TEST(touchpad_edge_scroll_horiz)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

494 495 496 497
	litest_touch_down(dev, 0, 99, 20);
	litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
	litest_touch_up(dev, 0);

498 499 500
	if (!touchpad_has_horiz_edge_scroll_size(dev))
		return;

501 502
	litest_drain_events(li);
	litest_enable_edge_scroll(dev);
503 504 505 506 507 508

	litest_touch_down(dev, 0, 20, 99);
	litest_touch_move_to(dev, 0, 20, 99, 70, 99, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
509
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 4);
510 511 512 513 514 515 516
	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 70, 99);
	litest_touch_move_to(dev, 0, 70, 99, 20, 99, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
517
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -4);
518 519 520 521
	litest_assert_empty_queue(li);
}
END_TEST

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
START_TEST(touchpad_edge_scroll_horiz_clickpad)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	litest_drain_events(li);
	litest_enable_edge_scroll(dev);

	litest_touch_down(dev, 0, 20, 99);
	litest_touch_move_to(dev, 0, 20, 99, 70, 99, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, 4);
	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 70, 99);
	litest_touch_move_to(dev, 0, 70, 99, 20, 99, 10, 0);
	litest_touch_up(dev, 0);

	libinput_dispatch(li);
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, -4);
	litest_assert_empty_queue(li);
}
END_TEST

START_TEST(touchpad_edge_scroll_no_horiz)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	if (touchpad_has_horiz_edge_scroll_size(dev))
		return;

	litest_drain_events(li);
	litest_enable_edge_scroll(dev);

	litest_touch_down(dev, 0, 20, 99);
	litest_touch_move_to(dev, 0, 20, 99, 70, 99, 10, 0);
	litest_touch_up(dev, 0);

	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);

	litest_touch_down(dev, 0, 70, 99);
	litest_touch_move_to(dev, 0, 70, 99, 20, 99, 10, 0);
	litest_touch_up(dev, 0);

	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
}
END_TEST

573 574 575 576 577 578 579
START_TEST(touchpad_scroll_defaults)
{
	struct litest_device *dev = litest_current_device();
	struct libinput_device *device = dev->libinput_device;
	struct libevdev *evdev = dev->evdev;
	enum libinput_config_scroll_method method, expected;
	enum libinput_config_status status;
580 581 582 583 584 585
	bool should_have_2fg = false;

	if (libevdev_get_num_slots(evdev) > 1 ||
	    (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_APPLE &&
	     libevdev_get_id_product(dev->evdev) == PRODUCT_ID_APPLE_APPLETOUCH))
		should_have_2fg = true;
586 587 588

	method = libinput_device_config_scroll_get_methods(device);
	ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE);
589
	if (should_have_2fg)
590
		ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG);
591 592
	else
		ck_assert((method & LIBINPUT_CONFIG_SCROLL_2FG) == 0);
593

594
	if (should_have_2fg)
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
		expected = LIBINPUT_CONFIG_SCROLL_2FG;
	else
		expected = LIBINPUT_CONFIG_SCROLL_EDGE;

	method = libinput_device_config_scroll_get_method(device);
	ck_assert_int_eq(method, expected);
	method = libinput_device_config_scroll_get_default_method(device);
	ck_assert_int_eq(method, expected);

	status = libinput_device_config_scroll_set_method(device,
					  LIBINPUT_CONFIG_SCROLL_EDGE);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
	status = libinput_device_config_scroll_set_method(device,
					  LIBINPUT_CONFIG_SCROLL_2FG);

610
	if (should_have_2fg)
611 612 613 614 615 616
		ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
	else
		ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
}
END_TEST

617
START_TEST(touchpad_edge_scroll_timeout)
618 619 620 621 622
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;
623
	double width = 0, height = 0;
624 625 626 627 628 629 630 631 632 633 634 635 636 637
	int nevents = 0;
	double mm; /* one mm in percent of the device */

	ck_assert_int_eq(libinput_device_get_size(dev->libinput_device,
						  &width,
						  &height), 0);
	mm = 100.0/height;

	/* timeout-based scrolling is disabled when software buttons are
	 * active, so switch to clickfinger. Not all test devices support
	 * that, hence the extra check. */
	if (libinput_device_config_click_get_methods(dev->libinput_device) &
	    LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER)
		litest_enable_clickfinger(dev);
638 639

	litest_drain_events(li);
640
	litest_enable_edge_scroll(dev);
641

642 643
	/* move 0.5mm, enough to load up the motion history, but less than
	 * the scroll threshold of 2mm */
644
	litest_touch_down(dev, 0, 99, 20);
645 646 647 648
	libinput_dispatch(li);
	litest_timeout_hysteresis();
	libinput_dispatch(li);

649
	litest_touch_move_to(dev, 0, 99, 20, 99, 20 + mm/2, 8, 0);
650
	libinput_dispatch(li);
651 652
	litest_assert_empty_queue(li);

653 654 655
	litest_timeout_edgescroll();
	libinput_dispatch(li);

656 657 658 659
	litest_assert_empty_queue(li);

	/* now move slowly up to the 2mm scroll threshold. we expect events */
	litest_touch_move_to(dev, 0, 99, 20 + mm/2, 99, 20 + mm * 2, 20, 0);
660 661 662
	litest_touch_up(dev, 0);
	libinput_dispatch(li);

663 664
	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);

665 666 667 668 669 670 671 672 673
	while ((event = libinput_get_event(li))) {
		double value;

		ptrev = litest_is_axis_event(event,
					     LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
					     0);
		value = libinput_event_pointer_get_axis_value(ptrev,
							      LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
		ck_assert_double_lt(value, 5.0);
674
		libinput_event_destroy(event);
675
		nevents++;
676 677
	}

678 679 680 681
	/* we sent 20 events but allow for some to be swallowed by rounding
	 * errors, the hysteresis, etc. */
	ck_assert_int_ge(nevents, 10);

682 683 684 685 686 687 688 689 690 691 692
	litest_assert_empty_queue(li);
	libinput_event_destroy(event);
}
END_TEST

START_TEST(touchpad_edge_scroll_no_motion)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	litest_drain_events(li);
693
	litest_enable_edge_scroll(dev);
694

695
	litest_touch_down(dev, 0, 99, 10);
696
	litest_touch_move_to(dev, 0, 99, 10, 99, 70, 12, 0);
697
	/* moving outside -> no motion event */
698
	litest_touch_move_to(dev, 0, 99, 70, 20, 70, 12, 0);
699
	/* moving down outside edge once scrolling had started -> scroll */
700
	litest_touch_move_to(dev, 0, 20, 70, 40, 99, 12, 0);
701 702 703
	litest_touch_up(dev, 0);
	libinput_dispatch(li);

704
	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 4);
705 706 707 708 709 710 711 712 713 714
	litest_assert_empty_queue(li);
}
END_TEST

START_TEST(touchpad_edge_scroll_no_edge_after_motion)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	litest_drain_events(li);
715
	litest_enable_edge_scroll(dev);
716 717 718

	/* moving into the edge zone must not trigger scroll events */
	litest_touch_down(dev, 0, 20, 20);
719 720
	litest_touch_move_to(dev, 0, 20, 20, 99, 20, 12, 0);
	litest_touch_move_to(dev, 0, 99, 20, 99, 80, 12, 0);
721 722 723 724 725 726 727 728
	litest_touch_up(dev, 0);
	libinput_dispatch(li);

	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
	litest_assert_empty_queue(li);
}
END_TEST

729 730 731 732 733 734 735 736
START_TEST(touchpad_edge_scroll_source)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;

	litest_drain_events(li);
737
	litest_enable_edge_scroll(dev);
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755

	litest_touch_down(dev, 0, 99, 20);
	litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0);
	litest_touch_up(dev, 0);

	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);

	while ((event = libinput_get_event(li))) {
		ck_assert_int_eq(libinput_event_get_type(event),
				 LIBINPUT_EVENT_POINTER_AXIS);
		ptrev = libinput_event_get_pointer_event(event);
		ck_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
				 LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
		libinput_event_destroy(event);
	}
}
END_TEST

756 757 758 759 760 761
START_TEST(touchpad_edge_scroll_no_2fg)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	litest_drain_events(li);
762
	litest_enable_edge_scroll(dev);
763

764 765 766
	litest_touch_down(dev, 0, 49, 50);
	litest_touch_down(dev, 1, 51, 50);
	litest_touch_move_two_touches(dev, 49, 50, 51, 50, 20, 30, 5, 0);
767 768 769 770 771 772 773 774 775
	libinput_dispatch(li);
	litest_touch_up(dev, 0);
	litest_touch_up(dev, 1);
	libinput_dispatch(li);

	litest_assert_empty_queue(li);
}
END_TEST

776 777 778 779 780
START_TEST(touchpad_edge_scroll_into_buttonareas)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

781 782
	litest_enable_buttonareas(dev);
	litest_enable_edge_scroll(dev);
783 784 785 786
	litest_drain_events(li);

	litest_touch_down(dev, 0, 99, 40);
	litest_touch_move_to(dev, 0, 99, 40, 99, 95, 10, 0);
787
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
788 789
	/* in the button zone now, make sure we still get events */
	litest_touch_move_to(dev, 0, 99, 95, 99, 100, 10, 0);
790
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
791 792 793

	/* and out of the zone again */
	litest_touch_move_to(dev, 0, 99, 100, 99, 70, 10, 0);
794
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
795 796 797

	/* still out of the zone */
	litest_touch_move_to(dev, 0, 99, 70, 99, 50, 10, 0);
798
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
799 800 801 802 803 804 805 806
}
END_TEST

START_TEST(touchpad_edge_scroll_within_buttonareas)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

807 808 809
	if (!touchpad_has_horiz_edge_scroll_size(dev))
		return;

810 811
	litest_enable_buttonareas(dev);
	litest_enable_edge_scroll(dev);
812 813 814 815 816 817
	litest_drain_events(li);

	litest_touch_down(dev, 0, 20, 99);

	/* within left button */
	litest_touch_move_to(dev, 0, 20, 99, 40, 99, 10, 0);
818
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
819 820 821

	/* over to right button */
	litest_touch_move_to(dev, 0, 40, 99, 60, 99, 10, 0);
822
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
823 824 825

	/* within right button */
	litest_touch_move_to(dev, 0, 60, 99, 80, 99, 10, 0);
826
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
827 828 829 830 831 832 833 834 835 836 837
}
END_TEST

START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;
	double val;

838 839 840
	if (!touchpad_has_horiz_edge_scroll_size(dev))
		return;

841 842
	litest_enable_buttonareas(dev);
	litest_enable_edge_scroll(dev);
843 844 845 846
	litest_drain_events(li);

	litest_touch_down(dev, 0, 20, 95);
	litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
847
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
848

849
	litest_button_click(dev, BTN_LEFT, true);
850 851 852 853 854 855 856 857 858 859 860 861
	libinput_dispatch(li);

	event = libinput_get_event(li);
	ptrev = litest_is_axis_event(event,
				     LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
				     LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
	val = libinput_event_pointer_get_axis_value(ptrev,
				    LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
	ck_assert(val == 0.0);
	libinput_event_destroy(event);

	event = libinput_get_event(li);
862 863 864
	litest_is_button_event(event,
			       BTN_RIGHT,
			       LIBINPUT_BUTTON_STATE_PRESSED);
865 866 867 868 869 870 871

	libinput_event_destroy(event);

	/* within button areas -> no movement */
	litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0);
	litest_assert_empty_queue(li);

872
	litest_button_click(dev, BTN_LEFT, false);
873

874
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
875 876 877 878 879 880 881 882 883 884 885 886 887

	litest_touch_up(dev, 0);
}
END_TEST

START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;
	struct libinput_event *event;
	struct libinput_event_pointer *ptrev;
	double val;

888 889 890
	if (!touchpad_has_horiz_edge_scroll_size(dev))
		return;

891 892
	litest_enable_clickfinger(dev);
	litest_enable_edge_scroll(dev);
893 894 895 896
	litest_drain_events(li);

	litest_touch_down(dev, 0, 20, 95);
	litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5);
897
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
898

899
	litest_button_click(dev, BTN_LEFT, true);
900 901 902 903 904 905 906 907 908 909 910 911
	libinput_dispatch(li);

	event = libinput_get_event(li);
	ptrev = litest_is_axis_event(event,
				     LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
				     LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
	val = libinput_event_pointer_get_axis_value(ptrev,
				    LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
	ck_assert(val == 0.0);
	libinput_event_destroy(event);

	event = libinput_get_event(li);
912 913 914
	litest_is_button_event(event,
			       BTN_LEFT,
			       LIBINPUT_BUTTON_STATE_PRESSED);
915 916 917 918 919

	libinput_event_destroy(event);

	/* clickfinger releases pointer -> expect movement */
	litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0);
920
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
921 922
	litest_assert_empty_queue(li);

923
	litest_button_click(dev, BTN_LEFT, false);
924

925
	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
926 927 928 929 930

	litest_touch_up(dev, 0);
}
END_TEST

931 932 933 934 935
START_TEST(touchpad_edge_scroll_into_area)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

936
	litest_enable_edge_scroll(dev);
937 938 939 940 941
	litest_drain_events(li);

	/* move into area, move vertically, move back to edge */

	litest_touch_down(dev, 0, 99, 20);
942 943
	litest_touch_move_to(dev, 0, 99, 20, 99, 50, 15, 2);
	litest_touch_move_to(dev, 0, 99, 50, 20, 50, 15, 2);
944 945
	litest_assert_only_typed_events(li,
					LIBINPUT_EVENT_POINTER_AXIS);
946 947
	litest_touch_move_to(dev, 0, 20, 50, 20, 20, 15, 2);
	litest_touch_move_to(dev, 0, 20, 20, 99, 20, 15, 2);
948 949
	litest_assert_empty_queue(li);

950
	litest_touch_move_to(dev, 0, 99, 20, 99, 50, 15, 2);
951 952 953 954 955
	litest_assert_only_typed_events(li,
					LIBINPUT_EVENT_POINTER_AXIS);
}
END_TEST

956 957 958 959
static int
touchpad_has_palm_detect_size(struct litest_device *dev)
{
	double width, height;
960
	unsigned int vendor;
961
	unsigned int bustype;
962
	int rc;
963

964
	vendor = libinput_device_get_id_vendor(dev->libinput_device);
965
	bustype = libevdev_get_id_bustype(dev->evdev);
966 967
	if (vendor == VENDOR_ID_WACOM)
		return 0;
968 969
	if (bustype == BUS_BLUETOOTH)
		return 0;
970
	if (vendor == VENDOR_ID_APPLE)
971 972
		return 1;

973
	rc = libinput_device_get_size(dev->libinput_device, &width, &height);
974

975
	return rc == 0 && width >= 70;
976 977
}

978 979 980 981 982
START_TEST(touchpad_palm_detect_at_edge)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

983
	if (!touchpad_has_palm_detect_size(dev) ||
984
	    !litest_has_2fg_scroll(dev))
985 986
		return;

987
	litest_enable_2fg_scroll(dev);
988

989
	litest_disable_tap(dev->libinput_device);
990

991 992 993
	litest_drain_events(li);

	litest_touch_down(dev, 0, 99, 50);
994
	litest_touch_move_to(dev, 0, 99, 50, 99, 70, 5, 0);
995 996 997 998 999
	litest_touch_up(dev, 0);

	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 5, 50);
1000
	litest_touch_move_to(dev, 0, 5, 50, 5, 70, 5, 0);
1001
	litest_touch_up(dev, 0);
1002 1003

	litest_assert_empty_queue(li);
1004 1005 1006
}
END_TEST

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
START_TEST(touchpad_palm_detect_at_top)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	if (!touchpad_has_palm_detect_size(dev))
		return;

	litest_disable_tap(dev->libinput_device);

	litest_drain_events(li);

	litest_touch_down(dev, 0, 20, 1);
	litest_touch_move_to(dev, 0, 20, 1, 70, 1, 10, 0);
	litest_touch_up(dev, 0);

	litest_assert_empty_queue(li);
}
END_TEST

1027 1028 1029 1030 1031 1032 1033 1034
START_TEST(touchpad_no_palm_detect_at_edge_for_edge_scrolling)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

	if (!touchpad_has_palm_detect_size(dev))
		return;

1035
	litest_enable_edge_scroll(dev);
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046

	litest_drain_events(li);

	litest_touch_down(dev, 0, 99, 50);
	litest_touch_move_to(dev, 0, 99, 50, 99, 70, 5, 0);
	litest_touch_up(dev, 0);

	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS);
}
END_TEST

1047 1048 1049 1050 1051
START_TEST(touchpad_palm_detect_at_bottom_corners)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

1052
	if (!touchpad_has_palm_detect_size(dev) ||
1053
	    !litest_has_2fg_scroll(dev))
1054 1055
		return;

1056
	litest_enable_2fg_scroll(dev);
1057

1058
	litest_disable_tap(dev->libinput_device);
1059

1060 1061 1062 1063 1064
	/* Run for non-clickpads only: make sure the bottom corners trigger
	   palm detection too */
	litest_drain_events(li);

	litest_touch_down(dev, 0, 99, 95);
1065
	litest_touch_move_to(dev, 0, 99, 95, 99, 99, 10, 0);
1066 1067 1068 1069 1070
	litest_touch_up(dev, 0);

	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 5, 95);
1071
	litest_touch_move_to(dev, 0, 5, 95, 5, 99, 5, 0);
1072 1073 1074 1075 1076 1077 1078 1079 1080
	litest_touch_up(dev, 0);
}
END_TEST

START_TEST(touchpad_palm_detect_at_top_corners)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;

1081
	if (!touchpad_has_palm_detect_size(dev) ||
1082
	    !litest_has_2fg_scroll(dev))
1083 1084
		return;

1085
	litest_enable_2fg_scroll(dev);
1086

1087
	litest_disable_tap(dev->libinput_device);
1088

1089 1090 1091 1092 1093
	/* Run for non-clickpads only: make sure the bottom corners trigger
	   palm detection too */
	litest_drain_events(li);

	litest_touch_down(dev, 0, 99, 5);
1094
	litest_touch_move_to(dev, 0, 99, 5, 99, 9, 10, 0);
1095 1096 1097 1098 1099
	litest_touch_up(dev, 0);

	litest_assert_empty_queue(li);

	litest_touch_down(dev, 0, 5, 5);
1100
	litest_touch_move_to(dev, 0, 5, 5, 5, 9, 5, 0);
1101
	litest_touch_up(dev, 0);
1102 1103

	litest_assert_empty_queue(li);
1104 1105 1106
}
END_TEST

1107 1108 1109 1110 1111
START_TEST(touchpad_palm_detect_palm_stays_palm)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li = dev->libinput;