END_TEST START_TEST(device_disable_release_keys) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_device *device; struct libinput_event *event; struct libinput_event_keyboard *kbdevent; enum libinput_config_status status; device = dev->libinput_device; litest_button_click(dev, KEY_A, true); litest_drain_events(li); litest_assert_empty_queue(li); status = libinput_device_config_send_events_set_mode(device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); litest_wait_for_event(li); event = libinput_get_event(li); ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_KEYBOARD_KEY); kbdevent = libinput_event_get_keyboard_event(event); ck_assert_int_eq(libinput_event_keyboard_get_key(kbdevent), KEY_A); ck_assert_int_eq(libinput_event_keyboard_get_key_state(kbdevent), LIBINPUT_KEY_STATE_RELEASED); libinput_event_destroy(event); litest_assert_empty_queue(li); }
END_TEST START_TEST(keyboard_ignore_no_pressed_release) { struct litest_device *dev; struct libinput *unused_libinput; struct libinput *libinput; struct libinput_event *event; struct libinput_event_keyboard *kevent; int events[] = { EV_KEY, KEY_A, -1, -1, }; enum libinput_key_state *state; enum libinput_key_state expected_states[] = { LIBINPUT_KEY_STATE_PRESSED, LIBINPUT_KEY_STATE_RELEASED, }; /* We can't send pressed -> released -> pressed events using uinput * as such non-symmetric events are dropped. Work-around this by first * adding the test device to the tested context after having sent an * initial pressed event. */ unused_libinput = litest_create_context(); dev = litest_add_device_with_overrides(unused_libinput, LITEST_KEYBOARD, "Generic keyboard", NULL, NULL, events); litest_keyboard_key(dev, KEY_A, true); litest_drain_events(unused_libinput); libinput = litest_create_context(); libinput_path_add_device(libinput, libevdev_uinput_get_devnode(dev->uinput)); litest_drain_events(libinput); litest_keyboard_key(dev, KEY_A, false); litest_keyboard_key(dev, KEY_A, true); litest_keyboard_key(dev, KEY_A, false); libinput_dispatch(libinput); ARRAY_FOR_EACH(expected_states, state) { event = libinput_get_event(libinput); ck_assert_notnull(event); ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_KEYBOARD_KEY); kevent = libinput_event_get_keyboard_event(event); ck_assert_int_eq(libinput_event_keyboard_get_key(kevent), KEY_A); ck_assert_int_eq(libinput_event_keyboard_get_key_state(kevent), *state); libinput_event_destroy(event); libinput_dispatch(libinput); }
int evdev_device_process_event(struct libinput_event *event) { struct libinput_device *libinput_device = libinput_event_get_device(event); int handled = 1; switch (libinput_event_get_type(event)) { case LIBINPUT_EVENT_KEYBOARD_KEY: handle_keyboard_key(libinput_device, libinput_event_get_keyboard_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION: handle_pointer_motion(libinput_device, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: handle_pointer_motion_absolute( libinput_device, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_BUTTON: handle_pointer_button(libinput_device, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_AXIS: handle_pointer_axis(libinput_device, libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_TOUCH_DOWN: handle_touch_down(libinput_device, libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_MOTION: handle_touch_motion(libinput_device, libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_UP: handle_touch_up(libinput_device, libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_FRAME: handle_touch_frame(libinput_device, libinput_event_get_touch_event(event)); break; default: handled = 0; weston_log("unknown libinput event %d\n", libinput_event_get_type(event)); } return handled; }
static int input_event(int fd, uint32_t mask, void *data) { (void)fd, (void)mask; struct input *input = data; if (libinput_dispatch(input->handle) != 0) wlc_log(WLC_LOG_WARN, "Failed to dispatch libinput"); struct libinput_event *event; while ((event = libinput_get_event(input->handle))) { struct libinput *handle = libinput_event_get_context(event); struct libinput_device *device = libinput_event_get_device(event); (void)handle; switch (libinput_event_get_type(event)) { case LIBINPUT_EVENT_DEVICE_ADDED: WLC_INTERFACE_EMIT(input.created, device); break; case LIBINPUT_EVENT_DEVICE_REMOVED: WLC_INTERFACE_EMIT(input.destroyed, device); break; case LIBINPUT_EVENT_POINTER_MOTION: { struct libinput_event_pointer *pev = libinput_event_get_pointer_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_MOTION; ev.time = libinput_event_pointer_get_time(pev); ev.motion.dx = libinput_event_pointer_get_dx(pev); ev.motion.dy = libinput_event_pointer_get_dy(pev); wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: { struct libinput_event_pointer *pev = libinput_event_get_pointer_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_MOTION_ABSOLUTE; ev.time = libinput_event_pointer_get_time(pev); ev.motion_abs.x = pointer_abs_x; ev.motion_abs.y = pointer_abs_y; ev.motion_abs.internal = pev; wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_POINTER_BUTTON: { struct libinput_event_pointer *pev = libinput_event_get_pointer_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_BUTTON; ev.time = libinput_event_pointer_get_time(pev); ev.button.code = libinput_event_pointer_get_button(pev); ev.button.state = (enum wl_pointer_button_state)libinput_event_pointer_get_button_state(pev); wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_POINTER_AXIS: { struct libinput_event_pointer *pev = libinput_event_get_pointer_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_SCROLL; ev.time = libinput_event_pointer_get_time(pev); #if LIBINPUT_VERSION_MAJOR == 0 && LIBINPUT_VERSION_MINOR < 8 /* < libinput 0.8.x (at least to 0.6.x) */ const enum wl_pointer_axis axis = libinput_event_pointer_get_axis(pev); ev.scroll.amount[(axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)] = libinput_event_pointer_get_axis_value(pev); ev.scroll.axis_bits |= (axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL ? WLC_SCROLL_AXIS_HORIZONTAL : WLC_SCROLL_AXIS_VERTICAL); #else /* > libinput 0.8.0 */ if (libinput_event_pointer_has_axis(pev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { ev.scroll.amount[0] = libinput_event_pointer_get_axis_value(pev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); ev.scroll.axis_bits |= WLC_SCROLL_AXIS_VERTICAL; } if (libinput_event_pointer_has_axis(pev, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { ev.scroll.amount[1] = libinput_event_pointer_get_axis_value(pev, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); ev.scroll.axis_bits |= WLC_SCROLL_AXIS_HORIZONTAL; } #endif // We should get other axis information from libinput as well, like source (finger, wheel) (v0.8) wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_KEYBOARD_KEY: { struct libinput_event_keyboard *kev = libinput_event_get_keyboard_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_KEY; ev.time = libinput_event_keyboard_get_time(kev); ev.key.code = libinput_event_keyboard_get_key(kev); ev.key.state = (enum wl_keyboard_key_state)libinput_event_keyboard_get_key_state(kev); ev.device = device; wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_TOUCH_UP: { struct libinput_event_touch *tev = libinput_event_get_touch_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_TOUCH; ev.time = libinput_event_touch_get_time(tev); ev.touch.type = wlc_touch_type_for_libinput_type(libinput_event_get_type(event)); ev.touch.slot = libinput_event_touch_get_seat_slot(tev); wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_TOUCH_DOWN: case LIBINPUT_EVENT_TOUCH_MOTION: { struct libinput_event_touch *tev = libinput_event_get_touch_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_TOUCH; ev.time = libinput_event_touch_get_time(tev); ev.touch.type = wlc_touch_type_for_libinput_type(libinput_event_get_type(event)); ev.touch.x = touch_abs_x; ev.touch.y = touch_abs_y; ev.touch.internal = tev; ev.touch.slot = libinput_event_touch_get_seat_slot(tev); wl_signal_emit(&wlc_system_signals()->input, &ev); } break; case LIBINPUT_EVENT_TOUCH_FRAME: case LIBINPUT_EVENT_TOUCH_CANCEL: { struct libinput_event_touch *tev = libinput_event_get_touch_event(event); struct wlc_input_event ev = {0}; ev.type = WLC_INPUT_EVENT_TOUCH; ev.time = libinput_event_touch_get_time(tev); ev.touch.type = wlc_touch_type_for_libinput_type(libinput_event_get_type(event)); wl_signal_emit(&wlc_system_signals()->input, &ev); } break; default: break; } libinput_event_destroy(event); } return 0; }
inline void LibInputHandler::HandleEvent(struct libinput_event *li_event) { int type = libinput_event_get_type(li_event); switch (type) { case LIBINPUT_EVENT_KEYBOARD_KEY: { /* Discard all data on stdin to avoid that keyboard input data is read * on the executing shell. */ tcflush(STDIN_FILENO, TCIFLUSH); libinput_event_keyboard *kb_li_event = libinput_event_get_keyboard_event(li_event); uint32_t key_code = libinput_event_keyboard_get_key(kb_li_event); libinput_key_state key_state = libinput_event_keyboard_get_key_state(kb_li_event); queue.Push(Event(key_state == LIBINPUT_KEY_STATE_PRESSED ? Event::KEY_DOWN : Event::KEY_UP, key_code)); } break; case LIBINPUT_EVENT_POINTER_MOTION: { libinput_event_pointer *ptr_li_event = libinput_event_get_pointer_event(li_event); if (-1.0 == x) x = 0.0; if (-1.0 == y) y = 0.0; x += libinput_event_pointer_get_dx(ptr_li_event); x = Clamp<double>(x, 0, width); y += libinput_event_pointer_get_dy(ptr_li_event); y = Clamp<double>(y, 0, height); queue.Push(Event(Event::MOUSE_MOTION, (unsigned) x, (unsigned) y)); } break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: { libinput_event_pointer *ptr_li_event = libinput_event_get_pointer_event(li_event); x = libinput_event_pointer_get_absolute_x_transformed(ptr_li_event, width); y = libinput_event_pointer_get_absolute_y_transformed(ptr_li_event, height); queue.Push(Event(Event::MOUSE_MOTION, (unsigned) x, (unsigned) y)); } break; case LIBINPUT_EVENT_POINTER_BUTTON: { libinput_event_pointer *ptr_li_event = libinput_event_get_pointer_event(li_event); libinput_button_state btn_state = libinput_event_pointer_get_button_state(ptr_li_event); queue.Push(Event(btn_state == LIBINPUT_BUTTON_STATE_PRESSED ? Event::MOUSE_DOWN : Event::MOUSE_UP, (unsigned) x, (unsigned) y)); } break; case LIBINPUT_EVENT_POINTER_AXIS: { libinput_event_pointer *ptr_li_event = libinput_event_get_pointer_event(li_event); double axis_value = libinput_event_pointer_get_axis_value(ptr_li_event); Event event(Event::MOUSE_WHEEL, (unsigned) x, (unsigned) y); event.param = unsigned((int) axis_value); queue.Push(event); } break; case LIBINPUT_EVENT_TOUCH_DOWN: { libinput_event_touch *touch_li_event = libinput_event_get_touch_event(li_event); x = libinput_event_touch_get_x_transformed(touch_li_event, width); y = libinput_event_touch_get_y_transformed(touch_li_event, height); queue.Push(Event(Event::MOUSE_DOWN, (unsigned) x, (unsigned) y)); } break; case LIBINPUT_EVENT_TOUCH_UP: { queue.Push(Event(Event::MOUSE_UP, (unsigned) x, (unsigned) y)); } break; case LIBINPUT_EVENT_TOUCH_MOTION: { libinput_event_touch *touch_li_event = libinput_event_get_touch_event(li_event); x = libinput_event_touch_get_x_transformed(touch_li_event, width); y = libinput_event_touch_get_y_transformed(touch_li_event, height); queue.Push(Event(Event::MOUSE_MOTION, (unsigned) x, (unsigned) y)); } break; } }
void LibInputHandlerPrivate::_q_liEventHandler() { Q_Q(LibInputHandler); if (libinput_dispatch(li) != 0) { qCWarning(lcInput) << "Failed to dispatch libinput events"; return; } libinput_event *event; while ((event = libinput_get_event(li)) != Q_NULLPTR) { libinput_event_type type = libinput_event_get_type(event); libinput_device *device = libinput_event_get_device(event); switch (type) { // Devices case LIBINPUT_EVENT_DEVICE_ADDED: if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) { ++keyboardCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->keyboardCountChanged(keyboardCount); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) { ++pointerCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->pointerCountChanged(pointerCount); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) { QTouchDevice *td = touch->registerDevice(device); Q_EMIT q->touchDeviceRegistered(td); ++touchCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->touchCountChanged(touchCount); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { ++gestureCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->gestureCountChanged(gestureCount); } break; case LIBINPUT_EVENT_DEVICE_REMOVED: if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) { --keyboardCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->keyboardCountChanged(keyboardCount); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) { --pointerCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->pointerCountChanged(pointerCount); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) { QTouchDevice *td = Q_NULLPTR; touch->unregisterDevice(device, &td); Q_EMIT q->touchDeviceUnregistered(td); --touchCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->touchCountChanged(touchCount); } if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) { --gestureCount; Q_EMIT q->capabilitiesChanged(); Q_EMIT q->gestureCountChanged(gestureCount); } break; // Keyboard case LIBINPUT_EVENT_KEYBOARD_KEY: keyboard->handleKey(libinput_event_get_keyboard_event(event)); break; // Pointer case LIBINPUT_EVENT_POINTER_BUTTON: pointer->handleButton(libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_AXIS: pointer->handleAxis(libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION: pointer->handleMotion(libinput_event_get_pointer_event(event)); break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: pointer->handleAbsoluteMotion(libinput_event_get_pointer_event(event)); break; // Touch case LIBINPUT_EVENT_TOUCH_UP: touch->handleTouchUp(libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_DOWN: touch->handleTouchDown(libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_FRAME: touch->handleTouchFrame(libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_MOTION: touch->handleTouchMotion(libinput_event_get_touch_event(event)); break; case LIBINPUT_EVENT_TOUCH_CANCEL: touch->handleTouchCancel(libinput_event_get_touch_event(event)); break; // Gesture case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: gesture->handlePinchBegin(libinput_event_get_gesture_event(event)); break; case LIBINPUT_EVENT_GESTURE_PINCH_END: gesture->handlePinchEnd(libinput_event_get_gesture_event(event)); break; case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: gesture->handlePinchUpdate(libinput_event_get_gesture_event(event)); break; case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: gesture->handleSwipeBegin(libinput_event_get_gesture_event(event)); break; case LIBINPUT_EVENT_GESTURE_SWIPE_END: gesture->handleSwipeEnd(libinput_event_get_gesture_event(event)); break; case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: gesture->handleSwipeUpdate(libinput_event_get_gesture_event(event)); break; default: break; } libinput_event_destroy(event); } }
void LibinputServer::processEvents() { libinput_dispatch(m_libinput); while (auto* event = libinput_get_event(m_libinput)) { switch (libinput_event_get_type(event)) { case LIBINPUT_EVENT_TOUCH_DOWN: if (m_handleTouchEvents) handleTouchEvent(event, Input::TouchEvent::Type::Down); break; case LIBINPUT_EVENT_TOUCH_UP: if (m_handleTouchEvents) handleTouchEvent(event, Input::TouchEvent::Type::Up); break; case LIBINPUT_EVENT_TOUCH_MOTION: if (m_handleTouchEvents) handleTouchEvent(event, Input::TouchEvent::Type::Motion); break; case LIBINPUT_EVENT_KEYBOARD_KEY: { auto* keyEvent = libinput_event_get_keyboard_event(event); Input::KeyboardEvent::Raw rawEvent{ libinput_event_keyboard_get_time(keyEvent), libinput_event_keyboard_get_key(keyEvent), libinput_event_keyboard_get_key_state(keyEvent) }; Input::KeyboardEventHandler::Result result = m_keyboardEventHandler->handleKeyboardEvent(rawEvent); m_client->handleKeyboardEvent({ rawEvent.time, std::get<0>(result), std::get<1>(result), !!rawEvent.state, std::get<2>(result) }); if (!!rawEvent.state) m_keyboardEventRepeating->schedule(rawEvent); else m_keyboardEventRepeating->cancel(); break; } case LIBINPUT_EVENT_POINTER_MOTION: { if (!m_handlePointerEvents) break; auto* pointerEvent = libinput_event_get_pointer_event(event); double dx = libinput_event_pointer_get_dx(pointerEvent); double dy = libinput_event_pointer_get_dy(pointerEvent); m_pointerCoords.first = std::min<int32_t>(std::max<uint32_t>(0, m_pointerCoords.first + dx), m_pointerBounds.first - 1); m_pointerCoords.second = std::min<int32_t>(std::max<uint32_t>(0, m_pointerCoords.second + dy), m_pointerBounds.second - 1); m_client->handlePointerEvent({ Input::PointerEvent::Motion, libinput_event_pointer_get_time(pointerEvent), m_pointerCoords.first, m_pointerCoords.second, 0, 0 }); break; } case LIBINPUT_EVENT_POINTER_BUTTON: { if (!m_handlePointerEvents) break; auto* pointerEvent = libinput_event_get_pointer_event(event); m_client->handlePointerEvent({ Input::PointerEvent::Button, libinput_event_pointer_get_time(pointerEvent), m_pointerCoords.first, m_pointerCoords.second, libinput_event_pointer_get_button(pointerEvent), libinput_event_pointer_get_button_state(pointerEvent) }); break; } case LIBINPUT_EVENT_POINTER_AXIS: { if (!m_handlePointerEvents) break; auto* pointerEvent = libinput_event_get_pointer_event(event); // Support only wheel events for now. if (libinput_event_pointer_get_axis_source(pointerEvent) != LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) break; if (libinput_event_pointer_has_axis(pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { auto axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; int32_t axisValue = libinput_event_pointer_get_axis_value(pointerEvent, axis); m_client->handleAxisEvent({ Input::AxisEvent::Motion, libinput_event_pointer_get_time(pointerEvent), m_pointerCoords.first, m_pointerCoords.second, axis, -axisValue }); } if (libinput_event_pointer_has_axis(pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { auto axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; int32_t axisValue = libinput_event_pointer_get_axis_value(pointerEvent, axis); m_client->handleAxisEvent({ Input::AxisEvent::Motion, libinput_event_pointer_get_time(pointerEvent), m_pointerCoords.first, m_pointerCoords.second, axis, axisValue }); } break; } default: break; } libinput_event_destroy(event); } }