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; } }
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; } }