/* * _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent * @device: a ClutterInputDevice * @stage: the stage the event should be delivered to * @xkb: XKB rules to translate the event * @_time: timestamp of the event * @key: a key code coming from a Linux input device * @state: TRUE if a press event, FALSE if a release event * @modifer_state: in/out * * Translate @key to a #ClutterKeyEvent using rules from xbbcommon. * * Return value: the new #ClutterEvent */ ClutterEvent * _clutter_key_event_new_from_evdev (ClutterInputDevice *device, ClutterInputDevice *core_device, ClutterStage *stage, struct xkb_state *xkb_state, uint32_t button_state, uint32_t _time, xkb_keycode_t key, uint32_t state) { ClutterEvent *event; xkb_keysym_t sym; const xkb_keysym_t *syms; char buffer[8]; int n; if (state) event = clutter_event_new (CLUTTER_KEY_PRESS); else event = clutter_event_new (CLUTTER_KEY_RELEASE); /* We use a fixed offset of 8 because evdev starts KEY_* numbering from * 0, whereas X11's minimum keycode, for really stupid reasons, is 8. * So the evdev XKB rules are based on the keycodes all being shifted * upwards by 8. */ key += 8; n = xkb_key_get_syms (xkb_state, key, &syms); if (n == 1) sym = syms[0]; else sym = XKB_KEY_NoSymbol; event->key.device = core_device; event->key.stage = stage; event->key.time = _time; _clutter_xkb_translate_state (event, xkb_state, button_state); event->key.hardware_keycode = key; event->key.keyval = sym; clutter_event_set_source_device (event, device); n = xkb_keysym_to_utf8 (sym, buffer, sizeof (buffer)); if (n == 0) { /* not printable */ event->key.unicode_value = (gunichar) '\0'; } else { event->key.unicode_value = g_utf8_get_char_validated (buffer, n); if (event->key.unicode_value == -1 || event->key.unicode_value == -2) event->key.unicode_value = (gunichar) '\0'; } return event; }
static ClutterEvent * new_absolute_motion_event (ClutterSeatEvdev *seat, ClutterInputDevice *input_device, guint64 time_us, gfloat x, gfloat y, gdouble *axes) { ClutterStage *stage = _clutter_input_device_get_stage (input_device); ClutterEvent *event; event = clutter_event_new (CLUTTER_MOTION); if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) _clutter_device_manager_evdev_constrain_pointer (seat->manager_evdev, seat->core_pointer, time_us, seat->pointer_x, seat->pointer_y, &x, &y); _clutter_evdev_event_set_time_usec (event, time_us); event->motion.time = us2ms (time_us); event->motion.stage = stage; _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); event->motion.x = x; event->motion.y = y; event->motion.axes = axes; clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) { ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); clutter_event_set_device_tool (event, device_evdev->last_tool); clutter_event_set_device (event, input_device); } else { clutter_event_set_device (event, seat->core_pointer); } _clutter_input_device_set_stage (seat->core_pointer, stage); if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) { seat->pointer_x = x; seat->pointer_y = y; } return event; }
static void notify_scroll (ClutterInputDevice *input_device, guint64 time_us, gdouble dx, gdouble dy, ClutterScrollSource scroll_source, ClutterScrollFinishFlags flags, gboolean emulated) { ClutterInputDeviceEvdev *device_evdev; ClutterSeatEvdev *seat; ClutterStage *stage; ClutterEvent *event = NULL; gdouble scroll_factor; /* We can drop the event on the floor if no stage has been * associated with the device yet. */ stage = _clutter_input_device_get_stage (input_device); if (stage == NULL) return; device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); seat = _clutter_input_device_evdev_get_seat (device_evdev); event = clutter_event_new (CLUTTER_SCROLL); _clutter_evdev_event_set_time_usec (event, time_us); event->scroll.time = us2ms (time_us); event->scroll.stage = CLUTTER_STAGE (stage); _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); /* libinput pointer axis events are in pointer motion coordinate space. * To convert to Xi2 discrete step coordinate space, multiply the factor * 1/10. */ event->scroll.direction = CLUTTER_SCROLL_SMOOTH; scroll_factor = 1.0 / DISCRETE_SCROLL_STEP; clutter_event_set_scroll_delta (event, scroll_factor * dx, scroll_factor * dy); event->scroll.x = seat->pointer_x; event->scroll.y = seat->pointer_y; clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); event->scroll.scroll_source = scroll_source; event->scroll.finish_flags = flags; _clutter_event_set_pointer_emulated (event, emulated); queue_event (event); }
static void notify_discrete_scroll (ClutterInputDevice *input_device, uint64_t time_us, ClutterScrollDirection direction, ClutterScrollSource scroll_source, gboolean emulated) { ClutterInputDeviceEvdev *device_evdev; ClutterSeatEvdev *seat; ClutterStage *stage; ClutterEvent *event = NULL; if (direction == CLUTTER_SCROLL_SMOOTH) 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 (input_device); if (stage == NULL) return; device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device); seat = _clutter_input_device_evdev_get_seat (device_evdev); event = clutter_event_new (CLUTTER_SCROLL); _clutter_evdev_event_set_time_usec (event, time_us); event->scroll.time = us2ms (time_us); event->scroll.stage = CLUTTER_STAGE (stage); _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); event->scroll.direction = direction; event->scroll.x = seat->pointer_x; event->scroll.y = seat->pointer_y; clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); event->scroll.scroll_source = scroll_source; _clutter_event_set_pointer_emulated (event, emulated); queue_event (event); }
void clutter_seat_evdev_notify_touch_event (ClutterSeatEvdev *seat, ClutterInputDevice *input_device, ClutterEventType evtype, uint64_t time_us, int slot, double x, double y) { ClutterStage *stage; ClutterEvent *event = NULL; /* We can drop the event on the floor if no stage has been * associated with the device yet. */ stage = _clutter_input_device_get_stage (input_device); if (stage == NULL) return; event = clutter_event_new (evtype); _clutter_evdev_event_set_time_usec (event, time_us); event->touch.time = us2ms (time_us); event->touch.stage = CLUTTER_STAGE (stage); event->touch.x = x; event->touch.y = y; clutter_input_device_evdev_translate_coordinates (input_device, stage, &event->touch.x, &event->touch.y); /* "NULL" sequences are special cased in clutter */ event->touch.sequence = GINT_TO_POINTER (MAX (1, slot + 1)); _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); if (evtype == CLUTTER_TOUCH_BEGIN || evtype == CLUTTER_TOUCH_UPDATE) event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); queue_event (event); }
void clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat, ClutterInputDevice *input_device, uint64_t time_us, uint32_t button, uint32_t state) { ClutterInputDeviceEvdev *device_evdev = (ClutterInputDeviceEvdev *) input_device; ClutterStage *stage; ClutterEvent *event = NULL; gint button_nr; static gint maskmap[8] = { CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK, CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0 }; int button_count; /* Drop any repeated button press (for example from virtual devices. */ button_count = update_button_count (seat, button, state); if (state && button_count > 1) return; if (!state && button_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 (input_device); if (stage == NULL) return; /* The evdev button numbers don't map sequentially to clutter button * numbers (the right and middle mouse buttons are in the opposite * order) so we'll map them directly with a switch statement */ switch (button) { case BTN_LEFT: case BTN_TOUCH: button_nr = CLUTTER_BUTTON_PRIMARY; break; case BTN_RIGHT: case BTN_STYLUS: button_nr = CLUTTER_BUTTON_SECONDARY; break; case BTN_MIDDLE: case BTN_STYLUS2: button_nr = CLUTTER_BUTTON_MIDDLE; break; case 0x149: /* BTN_STYLUS3 */ button_nr = 8; break; default: /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) button_nr = button - BTN_TOOL_PEN + 4; else button_nr = button - (BTN_LEFT - 1) + 4; break; } if (button_nr < 1 || button_nr > 12) { g_warning ("Unhandled button event 0x%x", button); return; } if (state) event = clutter_event_new (CLUTTER_BUTTON_PRESS); else event = clutter_event_new (CLUTTER_BUTTON_RELEASE); if (button_nr < G_N_ELEMENTS (maskmap)) { /* Update the modifiers */ if (state) seat->button_state |= maskmap[button_nr - 1]; else seat->button_state &= ~maskmap[button_nr - 1]; } _clutter_evdev_event_set_time_usec (event, time_us); event->button.time = us2ms (time_us); event->button.stage = CLUTTER_STAGE (stage); _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); event->button.button = button_nr; if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) { ClutterPoint point; clutter_input_device_get_coords (input_device, NULL, &point); event->button.x = point.x; event->button.y = point.y; } else { event->button.x = seat->pointer_x; event->button.y = seat->pointer_y; } clutter_event_set_device (event, seat->core_pointer); clutter_event_set_source_device (event, input_device); if (device_evdev->last_tool) { /* Apply the button event code as per the tool mapping */ guint mapped_button; mapped_button = clutter_input_device_tool_evdev_get_button_code (device_evdev->last_tool, button_nr); if (mapped_button != 0) button = mapped_button; } _clutter_evdev_event_set_event_code (event, button); if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) { clutter_event_set_device_tool (event, device_evdev->last_tool); clutter_event_set_device (event, input_device); } else { clutter_event_set_device (event, seat->core_pointer); } _clutter_input_device_set_stage (seat->core_pointer, stage); queue_event (event); }