示例#1
0
void QLibInputKeyboard::processKey(libinput_event_keyboard *e)
{
#ifndef QT_NO_XKBCOMMON_EVDEV
    if (!m_ctx || !m_keymap || !m_state)
        return;

    const uint32_t k = libinput_event_keyboard_get_key(e) + 8;
    const bool pressed = libinput_event_keyboard_get_key_state(e) == LIBINPUT_KEY_STATE_PRESSED;

    QVarLengthArray<char, 32> chars(32);
    const int size = xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
    if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
        chars.resize(size + 1);
        xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
    }
    const QString text = QString::fromUtf8(chars.constData(), size);

    const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k);

    // mods here is the modifier state before the event, i.e. not
    // including the current key in case it is a modifier.
    Qt::KeyboardModifiers mods = Qt::NoModifier;
    const int qtkey = keysymToQtKey(sym, &mods, text);

    xkb_state_component modtype = xkb_state_component(XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
    if (xkb_state_mod_index_is_active(m_state, m_modindex[0], modtype) && (qtkey != Qt::Key_Control || !pressed))
        mods |= Qt::ControlModifier;
    if (xkb_state_mod_index_is_active(m_state, m_modindex[1], modtype) && (qtkey != Qt::Key_Alt || !pressed))
        mods |= Qt::AltModifier;
    if (xkb_state_mod_index_is_active(m_state, m_modindex[2], modtype) && (qtkey != Qt::Key_Shift || !pressed))
        mods |= Qt::ShiftModifier;
    if (xkb_state_mod_index_is_active(m_state, m_modindex[3], modtype) && (qtkey != Qt::Key_Meta || !pressed))
        mods |= Qt::MetaModifier;

    xkb_state_update_key(m_state, k, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);

    QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(mods, qtkey);

    QWindowSystemInterface::handleExtendedKeyEvent(Q_NULLPTR,
                                                   pressed ? QEvent::KeyPress : QEvent::KeyRelease,
                                                   qtkey, mods, k, sym, mods, text);

    if (pressed && xkb_keymap_key_repeats(m_keymap, k)) {
        m_repeatData.qtkey = qtkey;
        m_repeatData.mods = mods;
        m_repeatData.nativeScanCode = k;
        m_repeatData.virtualKey = sym;
        m_repeatData.nativeMods = mods;
        m_repeatData.unicodeText = text;
        m_repeatData.repeatCount = 1;
        m_repeatTimer.setInterval(REPEAT_DELAY);
        m_repeatTimer.start();
    } else if (m_repeatTimer.isActive()) {
        m_repeatTimer.stop();
    }

#else
    Q_UNUSED(e);
#endif
}
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);
}
示例#3
0
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);
	}
示例#4
0
static void
handle_keyboard_key(struct libinput_device *libinput_device,
		    struct libinput_event_keyboard *keyboard_event)
{
	struct evdev_device *device =
		libinput_device_get_user_data(libinput_device);

	notify_key(device->seat,
		   libinput_event_keyboard_get_time(keyboard_event),
		   libinput_event_keyboard_get_key(keyboard_event),
		   libinput_event_keyboard_get_key_state(keyboard_event),
		   STATE_UPDATE_AUTOMATIC);
}
示例#5
0
static void
handle_keyboard_key(struct libinput_device *libinput_device,
		    struct libinput_event_keyboard *keyboard_event)
{
	struct evdev_device *device =
		libinput_device_get_user_data(libinput_device);
	int key_state =
		libinput_event_keyboard_get_key_state(keyboard_event);
	int seat_key_count =
		libinput_event_keyboard_get_seat_key_count(keyboard_event);

	/* Ignore key events that are not seat wide state changes. */
	if ((key_state == LIBINPUT_KEY_STATE_PRESSED &&
	     seat_key_count != 1) ||
	    (key_state == LIBINPUT_KEY_STATE_RELEASED &&
	     seat_key_count != 0))
		return;

	notify_key(device->seat,
		   libinput_event_keyboard_get_time(keyboard_event),
		   libinput_event_keyboard_get_key(keyboard_event),
		   libinput_event_keyboard_get_key_state(keyboard_event),
		   STATE_UPDATE_AUTOMATIC);
}
示例#6
0
文件: udev.c 项目: Azarn/wlc
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;
}
示例#7
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 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);
    }
}