static gboolean
clutter_wayland_repeat_key (void *data)
{
  ClutterInputDeviceWayland *device = data;
  ClutterStageCogl          *stage_cogl = device->keyboard_focus;
  ClutterEvent              *event;

  event = _clutter_key_event_new_from_evdev ((ClutterInputDevice *) device,
                                             stage_cogl->wrapper,
                                             device->xkb,
                                             device->repeat_time,
                                             device->repeat_key,
                                             1);
  device->repeat_time += KEY_REPEAT_INTERVAL;
  _clutter_event_push (event, FALSE);

  if (!device->is_initial_repeat)
    return TRUE;

  g_source_remove (device->repeat_source);
  device->repeat_source = g_timeout_add (KEY_REPEAT_INTERVAL,
                                         clutter_wayland_repeat_key,
                                         device);
  device->is_initial_repeat = FALSE;

  return FALSE;
}
static void
clutter_wayland_handle_key (void *data,
                            struct wl_keyboard *keyboard,
                            uint32_t serial, uint32_t _time,
                            uint32_t key, uint32_t state)
{
  ClutterInputDeviceWayland *device = data;
  ClutterStageCogl          *stage_cogl = device->keyboard_focus;
  ClutterEvent              *event;

  if (!device->xkb)
    return;

  event = _clutter_key_event_new_from_evdev ((ClutterInputDevice *) device,
                                             stage_cogl->wrapper,
                                             device->xkb,
                                             _time, key, state);

  _clutter_event_push (event, FALSE);

  if (!xkb_key_repeats (xkb_state_get_map (device->xkb), key))
    return;

  if (state)
    {
      if (device->repeat_key != XKB_KEYCODE_INVALID)
        g_source_remove (device->repeat_source);
      device->repeat_key = key;
      device->repeat_time = _time + KEY_REPEAT_DELAY;
      device->repeat_source = g_timeout_add (KEY_REPEAT_DELAY,
                                             clutter_wayland_repeat_key,
                                             device);
      device->is_initial_repeat = TRUE;
    }
  else if (device->repeat_key == key)
    {
      g_source_remove (device->repeat_source);
      device->repeat_key = XKB_KEYCODE_INVALID;
    }
}
Beispiel #3
0
void
clutter_seat_evdev_notify_key (ClutterSeatEvdev   *seat,
                               ClutterInputDevice *device,
                               uint64_t            time_us,
                               uint32_t            key,
                               uint32_t            state,
                               gboolean            update_keys)
{
  ClutterStage *stage;
  ClutterEvent *event = NULL;
  enum xkb_state_component changed_state;

  if (state != AUTOREPEAT_VALUE)
    {
      /* Drop any repeated button press (for example from virtual devices. */
      int count = update_button_count (seat, key, state);
      if (state && count > 1)
        return;
      if (!state && count != 0)
        return;
    }

  /* We can drop the event on the floor if no stage has been
   * associated with the device yet. */
  stage = _clutter_input_device_get_stage (device);
  if (stage == NULL)
    {
      clutter_seat_evdev_clear_repeat_timer (seat);
      return;
    }

  event = _clutter_key_event_new_from_evdev (device,
					     seat->core_keyboard,
					     stage,
					     seat->xkb,
					     seat->button_state,
					     us2ms (time_us), key, state);
  _clutter_evdev_event_set_event_code (event, key);

  /* We must be careful and not pass multiple releases to xkb, otherwise it gets
     confused and locks the modifiers */
  if (state != AUTOREPEAT_VALUE)
    {
      changed_state = xkb_state_update_key (seat->xkb,
                                            event->key.hardware_keycode,
                                            state ? XKB_KEY_DOWN : XKB_KEY_UP);
    }
  else
    {
      changed_state = 0;
      clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED);
    }

  queue_event (event);

  if (update_keys && (changed_state & XKB_STATE_LEDS))
    {
      ClutterBackend *backend;

      backend = clutter_get_default_backend ();
      g_signal_emit_by_name (clutter_backend_get_keymap (backend), "state-changed");
      clutter_seat_evdev_sync_leds (seat);
    }

  if (state == 0 ||             /* key release */
      !seat->repeat ||
      !xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb),
                               event->key.hardware_keycode))
    {
      clutter_seat_evdev_clear_repeat_timer (seat);
      return;
    }

  if (state == 1)               /* key press */
    seat->repeat_count = 0;

  seat->repeat_count += 1;
  seat->repeat_key = key;

  switch (seat->repeat_count)
    {
    case 1:
    case 2:
      {
        guint32 interval;

        clutter_seat_evdev_clear_repeat_timer (seat);
        seat->repeat_device = g_object_ref (device);

        if (seat->repeat_count == 1)
          interval = seat->repeat_delay;
        else
          interval = seat->repeat_interval;

        seat->repeat_timer =
          clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
                                            interval,
                                            keyboard_repeat,
                                            seat,
                                            NULL);
        return;
      }
    default:
      return;
    }
}