/*< internal > * clutter_input_device_set_associated_device: * @device: a #ClutterInputDevice * @associated: (allow-none): a #ClutterInputDevice, or %NULL * * Sets the associated device for @device. * * This function keeps a reference on the associated device. */ void _clutter_input_device_set_associated_device (ClutterInputDevice *device, ClutterInputDevice *associated) { if (device->associated == associated) return; if (device->associated != NULL) g_object_unref (device->associated); device->associated = associated; if (device->associated != NULL) g_object_ref (device->associated); CLUTTER_NOTE (MISC, "Associating device '%s' to device '%s'", clutter_input_device_get_device_name (device), device->associated != NULL ? clutter_input_device_get_device_name (device->associated) : "(none)"); if (device->device_mode != CLUTTER_INPUT_MODE_MASTER) { if (device->associated != NULL) device->device_mode = CLUTTER_INPUT_MODE_SLAVE; else device->device_mode = CLUTTER_INPUT_MODE_FLOATING; g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_DEVICE_MODE]); } }
static void manager_device_added_cb (ClutterDeviceManager *manager, ClutterInputDevice *device, TestDevicesApp *app) { ClutterInputDeviceType device_type; ClutterActor *hand = NULL; g_print ("got a %s device '%s' with id %d\n", device_type_name (device), clutter_input_device_get_device_name (device), clutter_input_device_get_device_id (device)); device_type = clutter_input_device_get_device_type (device); if (device_type == CLUTTER_POINTER_DEVICE || device_type == CLUTTER_PEN_DEVICE || device_type == CLUTTER_POINTER_DEVICE) { g_print ("*** enabling device '%s' ***\n", clutter_input_device_get_device_name (device)); clutter_input_device_set_enabled (device, TRUE); hand = clutter_texture_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL); g_hash_table_insert (app->devices, device, hand); clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand); } }
static gboolean stage_button_event_cb (ClutterActor *actor, ClutterEvent *event, TestDevicesApp *app) { ClutterInputDevice *device; ClutterInputDevice *source_device; ClutterActor *hand = NULL; gdouble *axes; guint n_axes, i; device = clutter_event_get_device (event); source_device = clutter_event_get_source_device (event); hand = g_hash_table_lookup (app->devices, device); g_print ("Device: '%s' (id:%d, type: %s, source: '%s', axes: %d)\n", clutter_input_device_get_device_name (device), clutter_input_device_get_device_id (device), device_type_name (device), source_device != device ? clutter_input_device_get_device_name (source_device) : "<same>", clutter_input_device_get_n_axes (device)); if (hand != NULL) { gfloat event_x, event_y; clutter_event_get_coords (event, &event_x, &event_y); clutter_actor_set_position (hand, event_x, event_y); } axes = clutter_event_get_axes (event, &n_axes); for (i = 0; i < n_axes; i++) { ClutterInputAxis axis; axis = clutter_input_device_get_axis (device, i); if (axis == CLUTTER_INPUT_AXIS_IGNORE) continue; g_print ("\tAxis[%2d][%s].value: %.2f\n", i, axis_type_name (axis), axes[i]); } return FALSE; }
static void * get_property (ClutterInputDevice *device, const gchar *property, Atom type, int format, gulong nitems) { MetaBackend *backend = meta_get_backend (); Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); gulong nitems_ret, bytes_after_ret; int rc, device_id, format_ret; Atom property_atom, type_ret; guchar *data_ret = NULL; property_atom = XInternAtom (xdisplay, property, False); device_id = clutter_input_device_get_device_id (device); rc = XIGetProperty (xdisplay, device_id, property_atom, 0, 10, False, type, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &data_ret); if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems) { if (nitems_ret > nitems) g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu", property, clutter_input_device_get_device_name (device), nitems_ret, nitems); return data_ret; } meta_XFree (data_ret); return NULL; }
static void manager_device_removed_cb (ClutterDeviceManager *manager, ClutterInputDevice *device, TestDevicesApp *app) { ClutterInputDeviceType device_type; ClutterActor *hand = NULL; g_print ("removed a %s device '%s' with id %d\n", device_type_name (device), clutter_input_device_get_device_name (device), clutter_input_device_get_device_id (device)); device_type = clutter_input_device_get_device_type (device); if (device_type == CLUTTER_POINTER_DEVICE || device_type == CLUTTER_PEN_DEVICE || device_type == CLUTTER_POINTER_DEVICE) { hand = g_hash_table_lookup (app->devices, device); if (hand != NULL) clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand); g_hash_table_remove (app->devices, device); } }
/* * _clutter_input_device_update: * @device: a #ClutterInputDevice * * Updates the input @device by determining the #ClutterActor underneath the * pointer's cursor * * This function calls _clutter_input_device_set_actor() if needed. * * This function only works for #ClutterInputDevice of type * %CLUTTER_POINTER_DEVICE. * * Since: 1.2 */ ClutterActor * _clutter_input_device_update (ClutterInputDevice *device, gboolean emit_crossing) { ClutterStage *stage; ClutterActor *new_cursor_actor; ClutterActor *old_cursor_actor; gint x, y; if (device->device_type == CLUTTER_KEYBOARD_DEVICE) return NULL; stage = device->stage; if (G_UNLIKELY (stage == NULL)) { CLUTTER_NOTE (EVENT, "No stage defined for device '%s'", clutter_input_device_get_device_name (device)); return NULL; } clutter_input_device_get_device_coords (device, &x, &y); old_cursor_actor = device->cursor_actor; new_cursor_actor = _clutter_do_pick (stage, x, y, CLUTTER_PICK_REACTIVE); /* if the pick could not find an actor then we do not update the * input device, to avoid ghost enter/leave events; the pick should * never fail, except for bugs in the glReadPixels() implementation * in which case this is the safest course of action anyway */ if (new_cursor_actor == NULL) return NULL; CLUTTER_NOTE (EVENT, "Actor under cursor (device %d, at %d, %d): %s", clutter_input_device_get_device_id (device), x, y, clutter_actor_get_name (new_cursor_actor) != NULL ? clutter_actor_get_name (new_cursor_actor) : G_OBJECT_TYPE_NAME (new_cursor_actor)); /* short-circuit here */ if (new_cursor_actor == old_cursor_actor) return old_cursor_actor; _clutter_input_device_set_actor (device, new_cursor_actor, emit_crossing); return device->cursor_actor; }
G_MODULE_EXPORT int test_devices_main (int argc, char **argv) { ClutterActor *stage; TestDevicesApp *app; ClutterDeviceManager *manager; const GSList *stage_devices, *l; /* force enabling X11 support */ clutter_x11_enable_xinput (); clutter_init (&argc, &argv); app = g_new0 (TestDevicesApp, 1); app->devices = g_hash_table_new (g_direct_hash, g_direct_equal) ; stage = clutter_stage_new (); clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_LightSkyBlue); clutter_stage_set_title (CLUTTER_STAGE (stage), "Devices"); clutter_stage_hide_cursor (CLUTTER_STAGE (stage)); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); g_signal_connect (stage, "motion-event", G_CALLBACK (stage_motion_event_cb), app); g_signal_connect (stage, "button-press-event", G_CALLBACK (stage_button_event_cb), app); app->stage = stage; clutter_actor_show_all (stage); manager = clutter_device_manager_get_default (); g_signal_connect (manager, "device-added", G_CALLBACK (manager_device_added_cb), app); g_signal_connect (manager, "device-removed", G_CALLBACK (manager_device_removed_cb), app); stage_devices = clutter_device_manager_peek_devices (manager); if (stage_devices == NULL) g_error ("No input devices found."); for (l = stage_devices; l != NULL; l = l->next) { ClutterInputDevice *device = l->data; ClutterInputDeviceType device_type; ClutterActor *hand = NULL; g_print ("got a %s device '%s' with id %d\n", device_type_name (device), clutter_input_device_get_device_name (device), clutter_input_device_get_device_id (device)); device_type = clutter_input_device_get_device_type (device); if (device_type == CLUTTER_POINTER_DEVICE || device_type == CLUTTER_PEN_DEVICE || device_type == CLUTTER_POINTER_DEVICE) { g_print ("*** enabling device '%s' ***\n", clutter_input_device_get_device_name (device)); clutter_input_device_set_enabled (device, TRUE); hand = clutter_texture_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL); g_hash_table_insert (app->devices, device, hand); clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand); } } clutter_main (); return EXIT_SUCCESS; }