static void clutter_wayland_handle_pointer_leave (void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl; ClutterEvent *event; stage_cogl = wl_surface_get_user_data (surface); g_assert (device->pointer_focus == stage_cogl); event = clutter_event_new (CLUTTER_LEAVE); event->crossing.stage = stage_cogl->wrapper; event->crossing.time = 0; /* ?! */ event->crossing.x = device->x; event->crossing.y = device->y; event->crossing.source = CLUTTER_ACTOR (stage_cogl->wrapper); event->crossing.device = CLUTTER_INPUT_DEVICE (device); _clutter_event_push (event, FALSE); device->pointer_focus = NULL; _clutter_input_device_set_stage (CLUTTER_INPUT_DEVICE (device), NULL); }
static void clutter_wayland_handle_pointer_enter (void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl; ClutterEvent *event; ClutterBackend *backend; ClutterBackendWayland *backend_wayland; stage_cogl = wl_surface_get_user_data (surface); device->pointer_focus = stage_cogl; _clutter_input_device_set_stage (CLUTTER_INPUT_DEVICE (device), stage_cogl->wrapper); event = clutter_event_new (CLUTTER_ENTER); event->crossing.stage = stage_cogl->wrapper; event->crossing.time = 0; /* ?! */ event->crossing.x = wl_fixed_to_double(x); event->crossing.y = wl_fixed_to_double(y); event->crossing.source = CLUTTER_ACTOR (stage_cogl->wrapper); event->crossing.device = CLUTTER_INPUT_DEVICE (device); device->x = event->crossing.x; device->y = event->crossing.y; _clutter_event_push (event, FALSE); /* Set the cursor to the cursor loaded at backend initialisation */ backend = clutter_get_default_backend (); backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); wl_pointer_set_cursor (pointer, serial, backend_wayland->cursor_surface, backend_wayland->cursor_x, backend_wayland->cursor_y); wl_surface_attach (backend_wayland->cursor_surface, backend_wayland->cursor_buffer, 0, 0); wl_surface_damage (backend_wayland->cursor_surface, 0, 0, 32, /* XXX: FFS */ 32); wl_surface_commit (backend_wayland->cursor_surface); }
static void clutter_input_device_dispose (GObject *gobject) { ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (gobject); g_free (device->device_name); if (device->device_mode == CLUTTER_INPUT_MODE_SLAVE) _clutter_input_device_remove_slave (device->associated, device); if (device->associated != NULL) { _clutter_input_device_set_associated_device (device->associated, NULL); g_object_unref (device->associated); device->associated = NULL; } if (device->axes != NULL) { g_array_free (device->axes, TRUE); device->axes = NULL; } if (device->keys != NULL) { g_array_free (device->keys, TRUE); device->keys = NULL; } G_OBJECT_CLASS (clutter_input_device_parent_class)->dispose (gobject); }
void _clutter_device_manager_wayland_add_input_group (ClutterDeviceManager *manager, uint32_t id) { ClutterBackend *backend = _clutter_device_manager_get_backend (manager); ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); ClutterInputDeviceWayland *device; device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_WAYLAND, "id", id, "device-type", CLUTTER_POINTER_DEVICE, "name", "wayland device", "enabled", TRUE, NULL); device->input_device = wl_display_bind (backend_wayland->wayland_display, id, &wl_input_device_interface); wl_input_device_add_listener (device->input_device, &_clutter_input_device_wayland_listener, device); wl_input_device_set_user_data (device->input_device, device); device->xkb = _clutter_xkb_desc_new (NULL, option_xkb_layout, option_xkb_variant, option_xkb_options); if (!device->xkb) CLUTTER_NOTE (BACKEND, "Failed to compile keymap"); _clutter_device_manager_add_device (manager, CLUTTER_INPUT_DEVICE (device)); }
static void stop_slow_keys (ClutterEvent *event, ClutterInputDeviceEvdev *device, ClutterEmitInputDeviceEvent emit_event_func) { GList *item; /* Check if we have a slow key event queued for this key event */ item = g_list_find_custom (device->slow_keys_list, event, find_pending_event_by_keycode); if (item) { SlowKeysEventPending *slow_keys_event = item->data; device->slow_keys_list = g_list_delete_link (device->slow_keys_list, item); clutter_input_device_evdev_free_pending_slow_key (slow_keys_event); if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT) clutter_input_device_evdev_bell_notify (); return; } /* If no key press event was pending, just emit the key release as-is */ emit_event_func (event, CLUTTER_INPUT_DEVICE (device)); }
static void clutter_input_device_get_property (GObject *gobject, guint prop_id, GValue *value, GParamSpec *pspec) { ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject); switch (prop_id) { case PROP_ID: g_value_set_int (value, self->id); break; case PROP_DEVICE_TYPE: g_value_set_enum (value, self->device_type); break; case PROP_NAME: g_value_set_string (value, self->device_name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); break; } }
static void notify_stickykeys_mask (ClutterInputDeviceEvdev *device) { g_signal_emit_by_name (CLUTTER_INPUT_DEVICE (device)->device_manager, "kbd-a11y-mods-state-changed", device->stickykeys_latched_mask, device->stickykeys_locked_mask); }
/* * _clutter_input_device_evdev_new: * @manager: the device manager * @seat: the seat the device will belong to * @libinput_device: the libinput device * * Create a new ClutterInputDevice given a libinput device and associate * it with the provided seat. */ ClutterInputDevice * _clutter_input_device_evdev_new (ClutterDeviceManager *manager, ClutterSeatEvdev *seat, struct libinput_device *libinput_device) { ClutterInputDeviceEvdev *device; ClutterInputDeviceType type; ClutterDeviceManagerEvdev *manager_evdev; gchar *vendor, *product; gint device_id, n_rings = 0, n_strips = 0, n_groups = 1; gchar *node_path; gdouble width, height; type = _clutter_input_device_evdev_determine_type (libinput_device); vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device)); product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device)); manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); node_path = g_strdup_printf ("/dev/input/%s", libinput_device_get_sysname (libinput_device)); if (libinput_device_has_capability (libinput_device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device); n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device); n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device); } device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, "id", device_id, "name", libinput_device_get_name (libinput_device), "device-manager", manager, "device-type", type, "device-mode", CLUTTER_INPUT_MODE_SLAVE, "enabled", TRUE, "vendor-id", vendor, "product-id", product, "n-rings", n_rings, "n-strips", n_strips, "n-mode-groups", n_groups, "device-node", node_path, NULL); device->seat = seat; device->libinput_device = libinput_device; libinput_device_set_user_data (libinput_device, device); libinput_device_ref (libinput_device); g_free (vendor); g_free (product); g_free (node_path); if (libinput_device_get_size (libinput_device, &width, &height) == 0) device->device_aspect_ratio = width / height; return CLUTTER_INPUT_DEVICE (device); }
static void clutter_input_device_xi2_constructed (GObject *gobject) { ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (gobject); g_object_get (gobject, "id", &device_xi2->device_id, NULL); if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed) G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject); #ifdef HAVE_LIBWACOM if (clutter_input_device_get_device_type (CLUTTER_INPUT_DEVICE (gobject)) == CLUTTER_PAD_DEVICE) { device_xi2->group_modes = g_array_new (FALSE, TRUE, sizeof (guint)); g_array_set_size (device_xi2->group_modes, clutter_input_device_get_n_mode_groups (CLUTTER_INPUT_DEVICE (gobject))); } #endif }
static void set_slowkeys_on (ClutterInputDeviceEvdev *device) { device->a11y_flags |= CLUTTER_A11Y_SLOW_KEYS_ENABLED; g_signal_emit_by_name (CLUTTER_INPUT_DEVICE (device)->device_manager, "kbd-a11y-flags-changed", device->a11y_flags, CLUTTER_A11Y_SLOW_KEYS_ENABLED); }
static void notify_stickykeys_change (ClutterInputDeviceEvdev *device) { /* Everytime sticky keys setting is changed, clear the masks */ device->stickykeys_depressed_mask = 0; update_internal_xkb_state (device, 0, 0); g_signal_emit_by_name (CLUTTER_INPUT_DEVICE (device)->device_manager, "kbd-a11y-flags-changed", device->a11y_flags, CLUTTER_A11Y_STICKY_KEYS_ENABLED); }
static void start_bounce_keys (ClutterEvent *event, ClutterInputDeviceEvdev *device) { stop_bounce_keys (device); device->debounce_key = ((ClutterKeyEvent *) event)->hardware_keycode; device->debounce_timer = clutter_threads_add_timeout (get_debounce_delay (CLUTTER_INPUT_DEVICE (device)), clear_bounce_keys, device); }
static void clutter_input_device_get_property (GObject *gobject, guint prop_id, GValue *value, GParamSpec *pspec) { ClutterInputDevice *self = CLUTTER_INPUT_DEVICE (gobject); switch (prop_id) { case PROP_ID: g_value_set_int (value, self->id); break; case PROP_DEVICE_TYPE: g_value_set_enum (value, self->device_type); break; case PROP_DEVICE_MANAGER: g_value_set_object (value, self->device_manager); break; case PROP_DEVICE_MODE: g_value_set_enum (value, self->device_mode); break; case PROP_BACKEND: g_value_set_object (value, self->backend); break; case PROP_NAME: g_value_set_string (value, self->device_name); break; case PROP_HAS_CURSOR: g_value_set_boolean (value, self->has_cursor); break; case PROP_N_AXES: g_value_set_uint (value, clutter_input_device_get_n_axes (self)); break; case PROP_ENABLED: g_value_set_boolean (value, self->is_enabled); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); break; } }
static void clutter_input_device_evdev_finalize (GObject *object) { ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (object); ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (object); ClutterDeviceManagerEvdev *manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (device->device_manager); if (device_evdev->libinput_device) libinput_device_unref (device_evdev->libinput_device); _clutter_device_manager_evdev_release_device_id (manager_evdev, device); G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object); }
static void enable_mousekeys (ClutterInputDeviceEvdev *device) { ClutterDeviceManager *manager; device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; device->move_mousekeys_timer = 0; device->mousekeys_first_motion_time = 0; device->mousekeys_last_motion_time = 0; device->last_mousekeys_key = 0; if (device->mousekeys_virtual_device) return; manager = CLUTTER_INPUT_DEVICE (device)->device_manager; device->mousekeys_virtual_device = clutter_device_manager_create_virtual_device (manager, CLUTTER_POINTER_DEVICE); }
/* * _clutter_input_device_evdev_new_virtual: * @manager: the device manager * @seat: the seat the device will belong to * @type: the input device type * * Create a new virtual ClutterInputDevice of the given type. */ ClutterInputDevice * _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager, ClutterSeatEvdev *seat, ClutterInputDeviceType type, ClutterInputMode mode) { ClutterInputDeviceEvdev *device; ClutterDeviceManagerEvdev *manager_evdev; const char *name; gint device_id; switch (type) { case CLUTTER_KEYBOARD_DEVICE: name = "Virtual keyboard device for seat"; break; case CLUTTER_POINTER_DEVICE: name = "Virtual pointer device for seat"; break; case CLUTTER_TOUCHSCREEN_DEVICE: name = "Virtual touchscreen device for seat"; break; default: name = "Virtual device for seat"; break; }; manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, "id", device_id, "name", name, "device-manager", manager, "device-type", type, "device-mode", mode, "enabled", TRUE, NULL); device->seat = seat; return CLUTTER_INPUT_DEVICE (device); }
void clutter_input_device_evdev_release_touch_slots (ClutterInputDeviceEvdev *device_evdev, uint64_t time_us) { GHashTableIter iter; ClutterTouchState *touch_state; g_hash_table_iter_init (&iter, device_evdev->touches); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &touch_state)) { clutter_seat_evdev_notify_touch_event (touch_state->seat, CLUTTER_INPUT_DEVICE (device_evdev), CLUTTER_TOUCH_CANCEL, time_us, touch_state->seat_slot, touch_state->coords.x, touch_state->coords.y); g_hash_table_iter_remove (&iter); } }
static gboolean trigger_slow_keys (gpointer data) { SlowKeysEventPending *slow_keys_event = data; ClutterInputDeviceEvdev *device = slow_keys_event->device; ClutterKeyEvent *key_event = (ClutterKeyEvent *) slow_keys_event->event; /* Alter timestamp and emit the event */ key_event->time = us2ms (g_get_monotonic_time ()); slow_keys_event->emit_event_func (slow_keys_event->event, CLUTTER_INPUT_DEVICE (device)); /* Then remote the pending event */ device->slow_keys_list = g_list_remove (device->slow_keys_list, slow_keys_event); clutter_input_device_evdev_free_pending_slow_key (slow_keys_event); if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT) clutter_input_device_evdev_bell_notify (); return G_SOURCE_REMOVE; }
static void clutter_wayland_handle_button (void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t _time, uint32_t button, uint32_t state) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl = device->pointer_focus; ClutterEvent *event; ClutterEventType type; if (state) type = CLUTTER_BUTTON_PRESS; else type = CLUTTER_BUTTON_RELEASE; event = clutter_event_new (type); event->button.stage = stage_cogl->wrapper; event->button.device = CLUTTER_INPUT_DEVICE (device); event->button.time = /*_time*/ serial; event->button.x = device->x; event->button.y = device->y; event->button.modifier_state = xkb_state_serialize_mods (device->xkb, XKB_STATE_EFFECTIVE); /* evdev button codes */ switch (button) { case 272: event->button.button = 1; break; case 273: event->button.button = 3; break; case 274: event->button.button = 2; break; } _clutter_event_push (event, FALSE); }
static void clutter_input_device_evdev_finalize (GObject *object) { ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (object); ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (object); ClutterDeviceManagerEvdev *manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (device->device_manager); if (device_evdev->libinput_device) libinput_device_unref (device_evdev->libinput_device); clutter_input_device_evdev_release_touch_slots (device_evdev, g_get_monotonic_time ()); _clutter_device_manager_evdev_release_device_id (manager_evdev, device); clear_slow_keys (device_evdev); stop_bounce_keys (device_evdev); stop_toggle_slowkeys (device_evdev); stop_mousekeys_move (device_evdev); G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object); }
static void clutter_wayland_handle_motion (void *data, struct wl_pointer *pointer, uint32_t _time, wl_fixed_t x, wl_fixed_t y) { ClutterInputDeviceWayland *device = data; ClutterStageCogl *stage_cogl = device->pointer_focus; ClutterEvent *event; event = clutter_event_new (CLUTTER_MOTION); event->motion.stage = stage_cogl->wrapper; event->motion.device = CLUTTER_INPUT_DEVICE (device); event->motion.time = _time; event->motion.modifier_state = 0; event->motion.x = wl_fixed_to_double(x); event->motion.y = wl_fixed_to_double(y); device->x = event->motion.x; device->y = event->motion.y; _clutter_event_push (event, FALSE); }
/* * _clutter_input_device_evdev_new: * @manager: the device manager * @seat: the seat the device will belong to * @libinput_device: the libinput device * * Create a new ClutterInputDevice given a libinput device and associate * it with the provided seat. */ ClutterInputDevice * _clutter_input_device_evdev_new (ClutterDeviceManager *manager, ClutterSeatEvdev *seat, struct libinput_device *libinput_device) { ClutterInputDeviceEvdev *device; ClutterInputDeviceType type; ClutterDeviceManagerEvdev *manager_evdev; gchar *vendor, *product; gint device_id; type = _clutter_input_device_evdev_determine_type (libinput_device); vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device)); product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device)); manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager); device_id = _clutter_device_manager_evdev_acquire_device_id (manager_evdev); device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV, "id", device_id, "name", libinput_device_get_sysname (libinput_device), "device-manager", manager, "device-type", type, "device-mode", CLUTTER_INPUT_MODE_SLAVE, "enabled", TRUE, "vendor-id", vendor, "product-id", product, NULL); device->seat = seat; device->libinput_device = libinput_device; libinput_device_set_user_data (libinput_device, device); libinput_device_ref (libinput_device); g_free (vendor); g_free (product); return CLUTTER_INPUT_DEVICE (device); }
static void start_slow_keys (ClutterEvent *event, ClutterInputDeviceEvdev *device, ClutterEmitInputDeviceEvent emit_event_func) { SlowKeysEventPending *slow_keys_event; ClutterKeyEvent *key_event = (ClutterKeyEvent *) event; if (key_event->flags & CLUTTER_EVENT_FLAG_REPEATED) return; slow_keys_event = g_new0 (SlowKeysEventPending, 1); slow_keys_event->device = device; slow_keys_event->event = clutter_event_copy (event); slow_keys_event->emit_event_func = emit_event_func; slow_keys_event->timer = clutter_threads_add_timeout (get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)), trigger_slow_keys, slow_keys_event); device->slow_keys_list = g_list_append (device->slow_keys_list, slow_keys_event); if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS) clutter_input_device_evdev_bell_notify (); }