END_TEST

START_TEST(udev_device_sysname)
{
	struct libinput *li;
	struct libinput_event *ev;
	struct libinput_device *device;
	const char *sysname;
	struct udev *udev;

	udev = udev_new();
	ck_assert(udev != NULL);

	li = libinput_udev_create_context(&simple_interface, NULL, udev);
	ck_assert(li != NULL);
	ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);

	libinput_dispatch(li);

	while ((ev = libinput_get_event(li))) {
		if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED)
			continue;

		device = libinput_event_get_device(ev);
		sysname = libinput_device_get_sysname(device);
		ck_assert(sysname != NULL && strlen(sysname) > 1);
		ck_assert(strchr(sysname, '/') == NULL);
		ck_assert_int_eq(strncmp(sysname, "event", 5), 0);
		libinput_event_destroy(ev);
	}

	libinput_unref(li);
	udev_unref(udev);
}
END_TEST

START_TEST(abs_mt_device_no_range)
{
	struct libinput *li;
	int code = _i; /* looped test */
	/* set x/y so libinput doesn't just reject for missing axes */
	struct input_absinfo absinfo[] = {
		{ ABS_X, 0, 10, 0, 0, 0 },
		{ ABS_Y, 0, 10, 0, 0, 0 },
		{ ABS_MT_SLOT, 0, 10, 0, 0, 0 },
		{ ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 },
		{ ABS_MT_POSITION_X, 0, 10, 0, 0, 0 },
		{ ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 },
		{ code, 0, 0, 0, 0, 0 },
		{ -1, -1, -1, -1, -1, -1 }
	};

	li = litest_create_context();
	litest_disable_log_handler(li);

	if (code != ABS_MT_TOOL_TYPE &&
	    code != ABS_MT_TRACKING_ID) /* kernel overrides it */
		assert_device_ignored(li, absinfo);

	litest_restore_log_handler(li);
	libinput_unref(li);
}
END_TEST

START_TEST(udev_create_empty_seat)
{
	struct libinput *li;
	struct libinput_event *event;
	struct udev *udev;
	int fd;

	udev = udev_new();
	ck_assert(udev != NULL);

	/* expect a libinput reference, but no events */
	li = libinput_udev_create_context(&simple_interface, NULL, udev);
	ck_assert(li != NULL);
	ck_assert_int_eq(libinput_udev_assign_seat(li, "seatdoesntexist"), 0);

	fd = libinput_get_fd(li);
	ck_assert_int_ge(fd, 0);

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

	libinput_event_destroy(event);
	libinput_unref(li);
	udev_unref(udev);
}
Example #4
0
END_TEST

START_TEST(path_create_invalid)
{
	struct libinput *li;
	struct libinput_device *device;
	const char *path = "/tmp";

	open_func_count = 0;
	close_func_count = 0;

	li = libinput_path_create_context(&simple_interface, NULL);
	ck_assert(li != NULL);
	device = libinput_path_add_device(li, path);
	ck_assert(device == NULL);

	ck_assert_int_eq(open_func_count, 0);
	ck_assert_int_eq(close_func_count, 0);

	libinput_unref(li);
	ck_assert_int_eq(close_func_count, 0);

	open_func_count = 0;
	close_func_count = 0;
}
Example #5
0
END_TEST

START_TEST(path_create_destroy)
{
	struct libinput *li;
	struct libinput_device *device;
	struct libevdev_uinput *uinput;
	int rc;
	void *userdata = &rc;

	uinput = litest_create_uinput_device("test device", NULL,
					     EV_KEY, BTN_LEFT,
					     EV_KEY, BTN_RIGHT,
					     EV_REL, REL_X,
					     EV_REL, REL_Y,
					     -1);

	li = libinput_path_create_context(&simple_interface, userdata);
	ck_assert(li != NULL);
	ck_assert(libinput_get_user_data(li) == userdata);

	device = libinput_path_add_device(li,
					  libevdev_uinput_get_devnode(uinput));
	ck_assert(device != NULL);

	ck_assert_int_eq(open_func_count, 1);

	libevdev_uinput_destroy(uinput);
	libinput_unref(li);
	ck_assert_int_eq(close_func_count, 1);

	open_func_count = 0;
	close_func_count = 0;
}
END_TEST

START_TEST(udev_create_seat0)
{
	struct libinput *li;
	struct libinput_event *event;
	struct udev *udev;
	int fd;

	udev = udev_new();
	ck_assert(udev != NULL);

	li = libinput_udev_create_context(&simple_interface, NULL, udev);
	ck_assert(li != NULL);
	ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);

	fd = libinput_get_fd(li);
	ck_assert_int_ge(fd, 0);

	/* expect at least one event */
	libinput_dispatch(li);
	event = libinput_get_event(li);
	ck_assert(event != NULL);

	libinput_event_destroy(event);
	libinput_unref(li);
	udev_unref(udev);
}
END_TEST

START_TEST(abs_mt_device_no_absx)
{
	struct libevdev_uinput *uinput;
	struct libinput *li;
	struct libinput_device *device;

	uinput = litest_create_uinput_device("test device", NULL,
					     EV_KEY, BTN_LEFT,
					     EV_KEY, BTN_RIGHT,
					     EV_ABS, ABS_X,
					     EV_ABS, ABS_Y,
					     EV_ABS, ABS_MT_SLOT,
					     EV_ABS, ABS_MT_POSITION_Y,
					     -1);
	li = litest_create_context();
	litest_disable_log_handler(li);
	device = libinput_path_add_device(li,
					  libevdev_uinput_get_devnode(uinput));
	litest_restore_log_handler(li);
	ck_assert(device == NULL);
	libinput_unref(li);

	libevdev_uinput_destroy(uinput);
}
END_TEST

START_TEST(device_reenable_device_removed)
{
	struct libinput *li;
	struct litest_device *litest_device;
	struct libinput_device *device;
	enum libinput_config_status status;

	li = litest_create_context();
	litest_device = litest_add_device(li, LITEST_MOUSE);
	device = litest_device->libinput_device;

	libinput_device_ref(device);
	status = libinput_device_config_send_events_set_mode(device,
			LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);

	litest_drain_events(li);

	litest_delete_device(litest_device);
	litest_drain_events(li);

	status = libinput_device_config_send_events_set_mode(device,
			LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);

	/* can't really check for much here, this really just exercises the
	   code path. */
	litest_assert_empty_queue(li);

	libinput_device_unref(device);
	libinput_unref(li);
}
END_TEST

START_TEST(device_group_ref)
{
	struct libinput *li = litest_create_context();
	struct litest_device *dev = litest_add_device(li,
						      LITEST_MOUSE);
	struct libinput_device *device = dev->libinput_device;
	struct libinput_device_group *group;

	group = libinput_device_get_device_group(device);
	ck_assert_notnull(group);
	libinput_device_group_ref(group);

	libinput_device_ref(device);
	litest_drain_events(li);
	litest_delete_device(dev);
	litest_drain_events(li);

	/* make sure the device is dead but the group is still around */
	ck_assert(libinput_device_unref(device) == NULL);

	libinput_device_group_ref(group);
	ck_assert_notnull(libinput_device_group_unref(group));
	ck_assert(libinput_device_group_unref(group) == NULL);

	libinput_unref(li);
}
Example #10
0
static struct libinput *
open_device(const struct libinput_interface *interface,
	    void *userdata,
	    const char *path,
	    int verbose)
{
	struct libinput_device *device;
	struct libinput *li;

	li = libinput_path_create_context(interface, userdata);
	if (!li) {
		fprintf(stderr, "Failed to initialize context from %s\n", path);
		return NULL;
	}

	if (verbose) {
		libinput_log_set_handler(li, log_handler);
		libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
	}

	device = libinput_path_add_device(li, path);
	if (!device) {
		fprintf(stderr, "Failed to initialized device %s\n", path);
		libinput_unref(li);
		li = NULL;
	}

	return li;
}
Example #11
0
END_TEST

START_TEST(log_priority)
{
	struct libinput *li;

	li = libinput_path_create_context(&simple_interface, NULL);
	libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_ERROR);
	libinput_log_set_handler(li, simple_log_handler);
	log_handler_context = li;

	libinput_path_add_device(li, "/tmp");

	ck_assert_int_eq(log_handler_called, 1);

	libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_INFO);
	/* event0 is usually Lid Switch which prints an info that
	   we don't handle it */
	libinput_path_add_device(li, "/dev/input/event0");
	ck_assert_int_gt(log_handler_called, 1);

	log_handler_called = 0;

	libinput_unref(li);
	log_handler_context = NULL;
}
Example #12
0
END_TEST

START_TEST(path_create_invalid_file)
{
	struct libinput *li;
	struct libinput_device *device;
	char path[] = "/tmp/litest_path_XXXXXX";
	int fd;

	umask(002);
	fd = mkstemp(path);
	ck_assert_int_ge(fd, 0);
	close(fd);

	open_func_count = 0;
	close_func_count = 0;

	li = libinput_path_create_context(&simple_interface, NULL);
	unlink(path);

	ck_assert(li != NULL);
	device = libinput_path_add_device(li, path);
	ck_assert(device == NULL);

	ck_assert_int_eq(open_func_count, 0);
	ck_assert_int_eq(close_func_count, 0);

	libinput_unref(li);
	ck_assert_int_eq(close_func_count, 0);

	open_func_count = 0;
	close_func_count = 0;
}
END_TEST

START_TEST(abs_mt_device_missing_res)
{
	struct libinput *li;
	struct input_absinfo absinfo[] = {
		{ ABS_X, 0, 10, 0, 0, 10 },
		{ ABS_Y, 0, 10, 0, 0, 10 },
		{ ABS_MT_SLOT, 0, 2, 0, 0, 0 },
		{ ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 },
		{ ABS_MT_POSITION_X, 0, 10, 0, 0, 10 },
		{ ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 },
		{ -1, -1, -1, -1, -1, -1 }
	};

	li = litest_create_context();
	litest_disable_log_handler(li);
	assert_device_ignored(li, absinfo);

	absinfo[4].resolution = 0;
	absinfo[5].resolution = 20;

	assert_device_ignored(li, absinfo);

	litest_restore_log_handler(li);
	libinput_unref(li);

}
LibinputServer::~LibinputServer()
{
#ifdef KEY_INPUT_HANDLING_VIRTUAL
    if (m_virtualkeyboard != nullptr) {
       Destruct(m_virtualkeyboard);
    }
#endif
    libinput_unref(m_libinput);
    udev_unref(m_udev);
}
END_TEST

START_TEST(device_reenable_syspath_changed)
{
	struct libinput *li;
	struct litest_device *litest_device;
	struct libinput_device *device1, *device2;
	enum libinput_config_status status;
	struct libinput_event *event;

	li = litest_create_context();
	litest_device = litest_add_device(li, LITEST_MOUSE);
	device1 = litest_device->libinput_device;

	libinput_device_ref(device1);
	status = libinput_device_config_send_events_set_mode(device1,
			LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);

	litest_drain_events(li);

	litest_delete_device(litest_device);
	litest_drain_events(li);

	litest_device = litest_add_device(li, LITEST_MOUSE);
	device2 = litest_device->libinput_device;
	/* Note: if the sysname isn't the same, some other device got added
	 * or removed while this test was running.  This is unlikely and
	 * would result in a false positive, so let's fail the test here */
	ck_assert_str_eq(libinput_device_get_sysname(device1),
			 libinput_device_get_sysname(device2));

	status = libinput_device_config_send_events_set_mode(device1,
			LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);

	/* can't really check for much here, other than that if we pump
	   events through libinput, none of them should be from the first
	   device */
	litest_event(litest_device, EV_REL, REL_X, 1);
	litest_event(litest_device, EV_REL, REL_Y, 1);
	litest_event(litest_device, EV_SYN, SYN_REPORT, 0);

	libinput_dispatch(li);
	while ((event = libinput_get_event(li))) {
		ck_assert(libinput_event_get_device(event) != device1);
		libinput_event_destroy(event);
	}

	litest_delete_device(litest_device);
	libinput_device_unref(device1);
	libinput_unref(li);
}
Example #16
0
END_TEST

START_TEST(path_set_user_data)
{
	struct libinput *li;
	int data1, data2;

	li = libinput_path_create_context(&simple_interface, &data1);
	ck_assert(li != NULL);
	ck_assert(libinput_get_user_data(li) == &data1);
	libinput_set_user_data(li, &data2);
	ck_assert(libinput_get_user_data(li) == &data2);

	libinput_unref(li);
}
END_TEST

/**
 * This test only works if there's at least one device in the system that is
 * assigned the default seat. Should cover the 99% case.
 */
START_TEST(udev_added_seat_default)
{
	struct libinput *li;
	struct libinput_event *event;
	struct udev *udev;
	struct libinput_device *device;
	struct libinput_seat *seat;
	const char *seat_name;
	enum libinput_event_type type;
	int default_seat_found = 0;

	udev = udev_new();
	ck_assert(udev != NULL);

	li = libinput_udev_create_context(&simple_interface, NULL, udev);
	ck_assert(li != NULL);
	ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
	libinput_dispatch(li);

	while (!default_seat_found && (event = libinput_get_event(li))) {
		type = libinput_event_get_type(event);
		if (type != LIBINPUT_EVENT_DEVICE_ADDED) {
			libinput_event_destroy(event);
			continue;
		}

		device = libinput_event_get_device(event);
		seat = libinput_device_get_seat(device);
		ck_assert(seat != NULL);

		seat_name = libinput_seat_get_logical_name(seat);
		default_seat_found = !strcmp(seat_name, "default");
		libinput_event_destroy(event);
	}

	ck_assert(default_seat_found);

	libinput_unref(li);
	udev_unref(udev);
}
Example #18
0
END_TEST

START_TEST(log_handler_NULL)
{
	struct libinput *li;

	li = libinput_path_create_context(&simple_interface, NULL);
	libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
	libinput_log_set_handler(li, NULL);

	libinput_path_add_device(li, "/tmp");

	ck_assert_int_eq(log_handler_called, 0);
	log_handler_called = 0;

	libinput_unref(li);
}
Example #19
0
END_TEST

START_TEST(path_force_destroy)
{
	struct litest_device *dev = litest_current_device();
	struct libinput *li;
	struct libinput_device *device;

	li = libinput_path_create_context(&simple_interface, NULL);
	ck_assert_notnull(li);
	libinput_ref(li);
	device = libinput_path_add_device(li,
				  libevdev_uinput_get_devnode(dev->uinput));
	ck_assert_notnull(device);

	while (libinput_unref(li) != NULL)
		;
}
Example #20
0
void
LibInputHandler::Close()
{
  if (fd.IsDefined()) {
    io_loop.Remove(fd);
    fd.SetUndefined();
  }

  if (nullptr != li)
    libinput_unref(li);
  li = nullptr;

  if (nullptr != li_if)
    delete li_if;
  li_if = nullptr;

  delete udev_context;
  udev_context = nullptr;
}
Example #21
0
END_TEST

START_TEST(path_add_invalid_path)
{
	struct libinput *li;
	struct libinput_event *event;
	struct libinput_device *device;

	li = litest_create_context();

	device = libinput_path_add_device(li, "/tmp/");
	ck_assert(device == NULL);

	libinput_dispatch(li);

	while ((event = libinput_get_event(li)))
		ck_abort();

	libinput_unref(li);
}
int
main(int argc, char **argv)
{
	struct libinput *li;
	struct tools_options options;
	struct libinput_event *ev;

	if (argc > 1) {
		printf("Usage: %s [--help]\n"
		       "\n"
		       "This tool creates a libinput context on the default seat \"seat0\"\n"
		       "and lists all devices recognized by libinput and the configuration options.\n"
		       "Where multiple options are possible, the default is prefixed with \"*\".\n"
		       "\n"
		       "This tool requires access to the /dev/input/eventX nodes.\n",
		       program_invocation_short_name);

		return 1;
	}

	tools_init_options(&options);

	li = tools_open_backend(&options, NULL, &interface);
	if (!li)
		return 1;

	libinput_dispatch(li);
	while ((ev = libinput_get_event(li))) {

		if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
			print_device_notify(ev);

		libinput_event_destroy(ev);
		libinput_dispatch(li);
	}

	libinput_unref(li);

	return 0;
}
Example #23
0
static struct libinput *
open_udev(const struct libinput_interface *interface,
	  void *userdata,
	  const char *seat,
	  int verbose)
{
	struct libinput *li;
	struct udev *udev = udev_new();

	if (!udev) {
		fprintf(stderr, "Failed to initialize udev\n");
		return NULL;
	}

	li = libinput_udev_create_context(interface, userdata, udev);
	if (!li) {
		fprintf(stderr, "Failed to initialize context from udev\n");
		goto out;
	}

	if (verbose) {
		libinput_log_set_handler(li, log_handler);
		libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
	}

	if (libinput_udev_assign_seat(li, seat)) {
		fprintf(stderr, "Failed to set seat\n");
		libinput_unref(li);
		li = NULL;
		goto out;
	}

out:
	udev_unref(udev);
	return li;
}
END_TEST

START_TEST(abs_device_missing_res)
{
	struct libinput *li;
	struct input_absinfo absinfo[] = {
		{ ABS_X, 0, 10, 0, 0, 10 },
		{ ABS_Y, 0, 10, 0, 0, 0 },
		{ -1, -1, -1, -1, -1, -1 }
	};

	li = litest_create_context();
	litest_disable_log_handler(li);

	assert_device_ignored(li, absinfo);

	absinfo[0].resolution = 0;
	absinfo[1].resolution = 20;

	assert_device_ignored(li, absinfo);

	litest_restore_log_handler(li);
	libinput_unref(li);
}
END_TEST

START_TEST(udev_seat_recycle)
{
	struct udev *udev;
	struct libinput *li;
	struct libinput_event *ev;
	struct libinput_device *device;
	struct libinput_seat *saved_seat = NULL;
	struct libinput_seat *seat;
	int data = 0;
	int found = 0;
	void *user_data;

	udev = udev_new();
	ck_assert(udev != NULL);

	li = libinput_udev_create_context(&simple_interface, NULL, udev);
	ck_assert(li != NULL);
	ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);

	libinput_dispatch(li);
	while ((ev = libinput_get_event(li))) {
		switch (libinput_event_get_type(ev)) {
		case LIBINPUT_EVENT_DEVICE_ADDED:
			if (saved_seat)
				break;

			device = libinput_event_get_device(ev);
			ck_assert(device != NULL);
			saved_seat = libinput_device_get_seat(device);
			libinput_seat_set_user_data(saved_seat, &data);
			libinput_seat_ref(saved_seat);
			break;
		default:
			break;
		}

		libinput_event_destroy(ev);
	}

	ck_assert(saved_seat != NULL);

	libinput_suspend(li);

	litest_drain_events(li);

	libinput_resume(li);

	libinput_dispatch(li);
	while ((ev = libinput_get_event(li))) {
		switch (libinput_event_get_type(ev)) {
		case LIBINPUT_EVENT_DEVICE_ADDED:
			device = libinput_event_get_device(ev);
			ck_assert(device != NULL);

			seat = libinput_device_get_seat(device);
			user_data = libinput_seat_get_user_data(seat);
			if (user_data == &data) {
				found = 1;
				ck_assert(seat == saved_seat);
			}
			break;
		default:
			break;
		}

		libinput_event_destroy(ev);
	}

	ck_assert(found == 1);

	libinput_unref(li);
	udev_unref(udev);
}
Example #26
0
END_TEST

START_TEST(path_seat_recycle)
{
	struct libinput *li;
	struct libevdev_uinput *uinput;
	int rc;
	void *userdata = &rc;
	struct libinput_event *ev;
	struct libinput_device *device;
	struct libinput_seat *saved_seat = NULL;
	struct libinput_seat *seat;
	int data = 0;
	int found = 0;
	void *user_data;

	uinput = litest_create_uinput_device("test device", NULL,
					     EV_KEY, BTN_LEFT,
					     EV_KEY, BTN_RIGHT,
					     EV_REL, REL_X,
					     EV_REL, REL_Y,
					     -1);

	li = libinput_path_create_context(&simple_interface, userdata);
	ck_assert(li != NULL);

	device = libinput_path_add_device(li,
					  libevdev_uinput_get_devnode(uinput));
	ck_assert(device != NULL);

	libinput_dispatch(li);
	while ((ev = libinput_get_event(li))) {
		switch (libinput_event_get_type(ev)) {
		case LIBINPUT_EVENT_DEVICE_ADDED:
			if (saved_seat)
				break;

			device = libinput_event_get_device(ev);
			ck_assert(device != NULL);
			saved_seat = libinput_device_get_seat(device);
			libinput_seat_set_user_data(saved_seat, &data);
			libinput_seat_ref(saved_seat);
			break;
		default:
			break;
		}

		libinput_event_destroy(ev);
	}

	ck_assert(saved_seat != NULL);

	libinput_suspend(li);

	litest_drain_events(li);

	libinput_resume(li);

	libinput_dispatch(li);
	while ((ev = libinput_get_event(li))) {
		switch (libinput_event_get_type(ev)) {
		case LIBINPUT_EVENT_DEVICE_ADDED:
			device = libinput_event_get_device(ev);
			ck_assert(device != NULL);

			seat = libinput_device_get_seat(device);
			user_data = libinput_seat_get_user_data(seat);
			if (user_data == &data) {
				found = 1;
				ck_assert(seat == saved_seat);
			}
			break;
		default:
			break;
		}

		libinput_event_destroy(ev);
	}

	ck_assert(found == 1);

	libinput_unref(li);

	libevdev_uinput_destroy(uinput);
}
Example #27
0
END_TEST

START_TEST(path_add_device_suspend_resume_remove_device)
{
	struct libinput *li;
	struct libinput_device *device;
	struct libinput_event *event;
	struct libevdev_uinput *uinput1, *uinput2;
	int rc;
	int nevents;
	void *userdata = &rc;

	uinput1 = litest_create_uinput_device("test device", NULL,
					      EV_KEY, BTN_LEFT,
					      EV_KEY, BTN_RIGHT,
					      EV_REL, REL_X,
					      EV_REL, REL_Y,
					      -1);
	uinput2 = litest_create_uinput_device("test device 2", NULL,
					      EV_KEY, BTN_LEFT,
					      EV_KEY, BTN_RIGHT,
					      EV_REL, REL_X,
					      EV_REL, REL_Y,
					      -1);

	li = libinput_path_create_context(&simple_interface, userdata);
	ck_assert(li != NULL);

	device = libinput_path_add_device(li,
					  libevdev_uinput_get_devnode(uinput1));
	ck_assert(device != NULL);
	device = libinput_path_add_device(li,
					  libevdev_uinput_get_devnode(uinput2));

	libinput_device_ref(device);
	libinput_dispatch(li);

	nevents = 0;
	while ((event = libinput_get_event(li))) {
		enum libinput_event_type type;
		type = libinput_event_get_type(event);
		ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
		libinput_event_destroy(event);
		nevents++;
	}

	ck_assert_int_eq(nevents, 2);

	libinput_suspend(li);
	libinput_dispatch(li);

	nevents = 0;
	while ((event = libinput_get_event(li))) {
		enum libinput_event_type type;
		type = libinput_event_get_type(event);
		ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_REMOVED);
		libinput_event_destroy(event);
		nevents++;
	}

	ck_assert_int_eq(nevents, 2);

	/* now drop and remove one of the devices */
	libevdev_uinput_destroy(uinput2);
	libinput_path_remove_device(device);
	libinput_device_unref(device);

	rc = libinput_resume(li);
	ck_assert_int_eq(rc, 0);

	libinput_dispatch(li);

	nevents = 0;
	while ((event = libinput_get_event(li))) {
		enum libinput_event_type type;
		type = libinput_event_get_type(event);
		ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
		libinput_event_destroy(event);
		nevents++;
	}

	ck_assert_int_eq(nevents, 1);

	libevdev_uinput_destroy(uinput1);
	libinput_unref(li);

	open_func_count = 0;
	close_func_count = 0;
}