static gboolean st_button_button_release (ClutterActor *actor, ClutterButtonEvent *event) { StButton *button = ST_BUTTON (actor); StButtonPrivate *priv = st_button_get_instance_private (button); StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button); ClutterInputDevice *device = clutter_event_get_device ((ClutterEvent*) event); if (priv->button_mask & mask) { gboolean is_click; is_click = priv->grabbed && clutter_actor_contains (actor, event->source); st_button_release (button, device, mask, is_click ? event->button : 0, NULL); priv->grabbed &= ~mask; if (priv->grabbed == 0) clutter_ungrab_pointer (); return TRUE; } return FALSE; }
static gboolean st_button_button_press (ClutterActor *actor, ClutterButtonEvent *event) { StButton *button = ST_BUTTON (actor); StButtonPrivate *priv = st_button_get_instance_private (button); StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button); ClutterInputDevice *device = clutter_event_get_device ((ClutterEvent*) event); if (priv->press_sequence) return CLUTTER_EVENT_PROPAGATE; if (priv->button_mask & mask) { if (priv->grabbed == 0) clutter_grab_pointer (actor); priv->grabbed |= mask; st_button_press (button, device, mask, NULL); return TRUE; } return FALSE; }
static GesturePoint * gesture_register_point (ClutterGestureAction *action, ClutterEvent *event) { ClutterGestureActionPrivate *priv = action->priv; GesturePoint *point = NULL; if (priv->points->len >= MAX_GESTURE_POINTS) return NULL; g_array_set_size (priv->points, priv->points->len + 1); point = &g_array_index (priv->points, GesturePoint, priv->points->len - 1); point->last_event = clutter_event_copy (event); point->device = clutter_event_get_device (event); clutter_event_get_coords (event, &point->press_x, &point->press_y); point->last_motion_x = point->press_x; point->last_motion_y = point->press_y; point->last_motion_time = clutter_event_get_time (event); point->last_delta_x = point->last_delta_y = 0; point->last_delta_time = 0; if (clutter_event_type (event) != CLUTTER_BUTTON_PRESS) point->sequence = clutter_event_get_event_sequence (event); else point->sequence = NULL; return point; }
static gboolean st_button_touch_event (ClutterActor *actor, ClutterTouchEvent *event) { StButton *button = ST_BUTTON (actor); StButtonPrivate *priv = st_button_get_instance_private (button); StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (1); ClutterEventSequence *sequence; ClutterInputDevice *device; if (priv->pressed != 0) return CLUTTER_EVENT_PROPAGATE; device = clutter_event_get_device ((ClutterEvent*) event); sequence = clutter_event_get_event_sequence ((ClutterEvent*) event); if (event->type == CLUTTER_TOUCH_BEGIN && !priv->press_sequence) { clutter_input_device_sequence_grab (device, sequence, actor); st_button_press (button, device, 0, sequence); return CLUTTER_EVENT_STOP; } else if (event->type == CLUTTER_TOUCH_END && priv->device == device && priv->press_sequence == sequence) { st_button_release (button, device, mask, 0, sequence); clutter_input_device_sequence_ungrab (device, sequence); return CLUTTER_EVENT_STOP; } return CLUTTER_EVENT_PROPAGATE; }
void _clutter_event_push (const ClutterEvent *event, gboolean do_copy) { ClutterMainContext *context = _clutter_context_get_default (); ClutterInputDevice *device; g_assert (context != NULL); if (context->events_queue == NULL) context->events_queue = g_queue_new (); /* disabled devices don't propagate events */ device = clutter_event_get_device (event); if (device != NULL) { if (!clutter_input_device_get_enabled (device)) return; } if (do_copy) { ClutterEvent *copy; copy = clutter_event_copy (event); event = copy; } g_queue_push_head (context->events_queue, (gpointer) event); }
static GesturePoint * gesture_find_point (ClutterGestureAction *action, ClutterEvent *event, gint *position) { ClutterGestureActionPrivate *priv = action->priv; GesturePoint *point = NULL; ClutterEventType type = clutter_event_type (event); ClutterInputDevice *device = clutter_event_get_device (event); ClutterEventSequence *sequence = NULL; gint i; if ((type != CLUTTER_BUTTON_PRESS) && (type != CLUTTER_BUTTON_RELEASE) && (type != CLUTTER_MOTION)) sequence = clutter_event_get_event_sequence (event); for (i = 0; i < priv->points->len; i++) { if ((g_array_index (priv->points, GesturePoint, i).device == device) && (g_array_index (priv->points, GesturePoint, i).sequence == sequence)) { if (position != NULL) *position = i; point = &g_array_index (priv->points, GesturePoint, i); break; } } return point; }
static void handle_idletime_for_event (const ClutterEvent *event) { #ifdef HAVE_NATIVE_BACKEND /* This is handled by XSync under X11. */ MetaBackend *backend = meta_get_backend (); if (META_IS_BACKEND_NATIVE (backend)) { ClutterInputDevice *device, *source_device; MetaIdleMonitor *core_monitor, *device_monitor; int device_id; device = clutter_event_get_device (event); if (device == NULL) return; device_id = clutter_input_device_get_device_id (device); core_monitor = meta_idle_monitor_get_core (); device_monitor = meta_idle_monitor_get_for_device (device_id); meta_idle_monitor_native_reset_idletime (core_monitor); meta_idle_monitor_native_reset_idletime (device_monitor); source_device = clutter_event_get_source_device (event); if (source_device != device) { device_id = clutter_input_device_get_device_id (device); device_monitor = meta_idle_monitor_get_for_device (device_id); meta_idle_monitor_native_reset_idletime (device_monitor); } } #endif /* HAVE_NATIVE_BACKEND */ }
/** * clutter_event_get_axes: * @event: a #ClutterEvent * @n_axes: (out): return location for the number of axes returned * * Retrieves the array of axes values attached to the event. * * Return value: (transfer none): an array of axis values * * Since: 1.6 */ gdouble * clutter_event_get_axes (const ClutterEvent *event, guint *n_axes) { gdouble *retval = NULL; guint len = 0; switch (event->type) { case CLUTTER_NOTHING: case CLUTTER_STAGE_STATE: case CLUTTER_DESTROY_NOTIFY: case CLUTTER_CLIENT_MESSAGE: case CLUTTER_DELETE: case CLUTTER_ENTER: case CLUTTER_LEAVE: case CLUTTER_KEY_PRESS: case CLUTTER_KEY_RELEASE: case CLUTTER_EVENT_LAST: break; case CLUTTER_SCROLL: retval = event->scroll.axes; break; case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_RELEASE: retval = event->button.axes; break; case CLUTTER_TOUCH_BEGIN: case CLUTTER_TOUCH_UPDATE: case CLUTTER_TOUCH_END: case CLUTTER_TOUCH_CANCEL: retval = event->touch.axes; break; case CLUTTER_MOTION: retval = event->motion.axes; break; } if (retval != NULL) { ClutterInputDevice *device; device = clutter_event_get_device (event); if (device != NULL) len = clutter_input_device_get_n_axes (device); else retval = NULL; } if (n_axes) *n_axes = len; return retval; }
/** * clutter_event_get_device_type: * @event: a #ClutterEvent * * Retrieves the type of the device for @event * * Return value: the #ClutterInputDeviceType for the device, if * any is set * * Since: 1.0 */ ClutterInputDeviceType clutter_event_get_device_type (const ClutterEvent *event) { ClutterInputDevice *device = NULL; g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE); device = clutter_event_get_device (event); if (device != NULL) return clutter_input_device_get_device_type (device); return CLUTTER_POINTER_DEVICE; }
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; }
/** * clutter_event_get_source_device: * @event: a #ClutterEvent * * Retrieves the hardware device that originated the event. * * If you need the virtual device, use clutter_event_get_device(). * * If no hardware device originated this event, this function will * return the same device as clutter_event_get_device(). * * Return value: (transfer none): a pointer to a #ClutterInputDevice * or %NULL * * Since: 1.6 */ ClutterInputDevice * clutter_event_get_source_device (const ClutterEvent *event) { ClutterEventPrivate *real_event; if (!is_event_allocated (event)) return NULL; real_event = (ClutterEventPrivate *) event; if (real_event->source_device != NULL) return real_event->source_device; return clutter_event_get_device (event); }
static void handle_idletime_for_event (const ClutterEvent *event) { #ifdef HAVE_NATIVE_BACKEND /* This is handled by XSync under X11. */ MetaBackend *backend = meta_get_backend (); if (META_IS_BACKEND_NATIVE (backend)) { ClutterInputDevice *device, *source_device; MetaIdleMonitor *core_monitor, *device_monitor; int device_id; device = clutter_event_get_device (event); if (device == NULL) return; if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC || event->type == CLUTTER_ENTER || event->type == CLUTTER_LEAVE || event->type == CLUTTER_STAGE_STATE || event->type == CLUTTER_DESTROY_NOTIFY || event->type == CLUTTER_CLIENT_MESSAGE || event->type == CLUTTER_DELETE) return; device_id = clutter_input_device_get_device_id (device); core_monitor = meta_idle_monitor_get_core (); device_monitor = meta_idle_monitor_get_for_device (device_id); meta_idle_monitor_native_reset_idletime (core_monitor); meta_idle_monitor_native_reset_idletime (device_monitor); source_device = clutter_event_get_source_device (event); if (source_device != device) { device_id = clutter_input_device_get_device_id (device); device_monitor = meta_idle_monitor_get_for_device (device_id); meta_idle_monitor_native_reset_idletime (device_monitor); } } #endif /* HAVE_NATIVE_BACKEND */ }
static gboolean stage_motion_event_cb (ClutterActor *actor, ClutterEvent *event, TestDevicesApp *app) { ClutterInputDevice *device; ClutterActor *hand = NULL; device = clutter_event_get_device (event); hand = g_hash_table_lookup (app->devices, 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); return TRUE; } return FALSE; }
static void handle_idletime_for_event (const ClutterEvent *event) { ClutterInputDevice *device, *source_device; MetaIdleMonitor *core_monitor, *device_monitor; int device_id; device = clutter_event_get_device (event); if (device == NULL) return; if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC || event->type == CLUTTER_ENTER || event->type == CLUTTER_LEAVE || event->type == CLUTTER_STAGE_STATE || event->type == CLUTTER_DESTROY_NOTIFY || event->type == CLUTTER_CLIENT_MESSAGE || event->type == CLUTTER_DELETE) return; device_id = clutter_input_device_get_device_id (device); core_monitor = meta_idle_monitor_get_core (); device_monitor = meta_idle_monitor_get_for_device (device_id); meta_idle_monitor_reset_idletime (core_monitor); meta_idle_monitor_reset_idletime (device_monitor); source_device = clutter_event_get_source_device (event); if (source_device != device) { device_id = clutter_input_device_get_device_id (device); device_monitor = meta_idle_monitor_get_for_device (device_id); meta_idle_monitor_reset_idletime (device_monitor); } }
IO_METHOD(IoClutterEvent, getDevice) { return IoClutterInputDevice_newWithDevice( IOSTATE, clutter_event_get_device(IOCEVENT(self)) ); }
/** * clutter_event_copy: * @event: A #ClutterEvent. * * Copies @event. * * Return value: (transfer full): A newly allocated #ClutterEvent */ ClutterEvent * clutter_event_copy (const ClutterEvent *event) { ClutterEvent *new_event; ClutterEventPrivate *new_real_event; ClutterInputDevice *device; gint n_axes = 0; g_return_val_if_fail (event != NULL, NULL); new_event = clutter_event_new (CLUTTER_NOTHING); new_real_event = (ClutterEventPrivate *) new_event; *new_event = *event; if (is_event_allocated (event)) { ClutterEventPrivate *real_event = (ClutterEventPrivate *) event; new_real_event->device = real_event->device; new_real_event->source_device = real_event->source_device; new_real_event->delta_x = real_event->delta_x; new_real_event->delta_y = real_event->delta_y; } device = clutter_event_get_device (event); if (device != NULL) n_axes = clutter_input_device_get_n_axes (device); switch (event->type) { case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_RELEASE: if (event->button.axes != NULL) new_event->button.axes = g_memdup (event->button.axes, sizeof (gdouble) * n_axes); break; case CLUTTER_SCROLL: if (event->scroll.axes != NULL) new_event->scroll.axes = g_memdup (event->scroll.axes, sizeof (gdouble) * n_axes); break; case CLUTTER_MOTION: if (event->motion.axes != NULL) new_event->motion.axes = g_memdup (event->motion.axes, sizeof (gdouble) * n_axes); break; case CLUTTER_TOUCH_BEGIN: case CLUTTER_TOUCH_UPDATE: case CLUTTER_TOUCH_END: case CLUTTER_TOUCH_CANCEL: if (event->touch.axes != NULL) new_event->touch.axes = g_memdup (event->touch.axes, sizeof (gdouble) * n_axes); break; default: break; } if (is_event_allocated (event)) _clutter_backend_copy_event_data (clutter_get_default_backend (), event, new_event); return new_event; }
/** * clutter_gdk_handle_event: * @event: a #GdkEvent * * This function processes a single GDK event; it can be used to hook * into external event processing * * Return value: #GdkFilterReturn. %GDK_FILTER_REMOVE indicates that * Clutter has internally handled the event and the caller should do * no further processing. %GDK_FILTER_CONTINUE indicates that Clutter * is either not interested in the event, or has used the event to * update internal state without taking any exclusive action. * %GDK_FILTER_TRANSLATE will not occur. * */ GdkFilterReturn clutter_gdk_handle_event (GdkEvent *gdk_event) { ClutterDeviceManager *device_manager; ClutterBackendGdk *backend_gdk; ClutterBackend *backend; ClutterStage *stage = NULL; ClutterEvent *event = NULL; gint spin = 0; GdkFilterReturn result = GDK_FILTER_CONTINUE; ClutterInputDevice *device, *source_device; GdkDevice *gdk_device; backend = clutter_get_default_backend (); if (!CLUTTER_IS_BACKEND_GDK (backend)) return GDK_FILTER_CONTINUE; if (gdk_event->any.window == NULL) return GDK_FILTER_CONTINUE; device_manager = clutter_device_manager_get_default (); if (G_UNLIKELY (device_manager == NULL)) return GDK_FILTER_CONTINUE; backend_gdk = CLUTTER_BACKEND_GDK (backend); stage = clutter_gdk_get_stage_from_window (gdk_event->any.window); gdk_device = gdk_event_get_device (gdk_event); if (gdk_device != NULL) device = _clutter_device_manager_gdk_lookup_device (device_manager, gdk_device); else device = NULL; gdk_device = gdk_event_get_source_device (gdk_event); if (gdk_device != NULL) source_device = _clutter_device_manager_gdk_lookup_device (device_manager, gdk_device); else source_device = NULL; if (stage == NULL) return GDK_FILTER_CONTINUE; _clutter_threads_acquire_lock (); switch (gdk_event->type) { case GDK_DELETE: event = clutter_event_new (CLUTTER_DELETE); break; case GDK_DESTROY: event = clutter_event_new (CLUTTER_DESTROY_NOTIFY); break; case GDK_EXPOSE: { ClutterPaintVolume clip; ClutterVertex origin; CLUTTER_NOTE (EVENT, "Expose for stage '%s' [%p] { %d, %d - %d x %d }", _clutter_actor_get_debug_name (CLUTTER_ACTOR (stage)), stage, gdk_event->expose.area.x, gdk_event->expose.area.y, gdk_event->expose.area.width, gdk_event->expose.area.height); origin.x = gdk_event->expose.area.x; origin.y = gdk_event->expose.area.y; origin.z = 0; _clutter_paint_volume_init_static (&clip, CLUTTER_ACTOR (stage)); clutter_paint_volume_set_origin (&clip, &origin); clutter_paint_volume_set_width (&clip, gdk_event->expose.area.width); clutter_paint_volume_set_height (&clip, gdk_event->expose.area.height); _clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), 0, &clip); clutter_paint_volume_free (&clip); } break; case GDK_DAMAGE: /* This is handled by cogl */ break; case GDK_MOTION_NOTIFY: event = clutter_event_new (CLUTTER_MOTION); event->motion.time = gdk_event->motion.time; event->motion.x = gdk_event->motion.x; event->motion.y = gdk_event->motion.y; event->motion.axes = NULL; /* It's all X in the end, right? */ event->motion.modifier_state = gdk_event->motion.state; clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); CLUTTER_NOTE (EVENT, "Motion notifiy [%.2f, %.2f]", event->motion.x, event->motion.y); break; case GDK_BUTTON_PRESS: case GDK_BUTTON_RELEASE: event = clutter_event_new (gdk_event->type == GDK_BUTTON_PRESS ? CLUTTER_BUTTON_PRESS : CLUTTER_BUTTON_RELEASE); event->button.time = gdk_event->button.time; event->button.x = gdk_event->button.x; event->button.y = gdk_event->button.y; event->button.axes = NULL; event->button.modifier_state = gdk_event->button.state; event->button.button = gdk_event->button.button; event->button.click_count = 1; clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); CLUTTER_NOTE (EVENT, "Button %d %s [%.2f, %.2f]", event->button.button, event->type == CLUTTER_BUTTON_PRESS ? "press" : "release", event->button.x, event->button.y); break; case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: /* these are handled by clutter-main.c updating click_count */ break; case GDK_KEY_PRESS: case GDK_KEY_RELEASE: event = clutter_event_new (gdk_event->type == GDK_KEY_PRESS ? CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE); event->key.time = gdk_event->key.time; event->key.modifier_state = gdk_event->key.state; event->key.keyval = gdk_event->key.keyval; event->key.hardware_keycode = gdk_event->key.hardware_keycode; event->key.unicode_value = g_utf8_get_char (gdk_event->key.string); clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); CLUTTER_NOTE (EVENT, "Key %d %s", event->key.keyval, event->type == CLUTTER_KEY_PRESS ? "press" : "release"); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: event = clutter_event_new (gdk_event->type == GDK_ENTER_NOTIFY ? CLUTTER_ENTER : CLUTTER_LEAVE); event->crossing.source = CLUTTER_ACTOR (stage); event->crossing.time = gdk_event_get_time (gdk_event); event->crossing.x = gdk_event->crossing.x; event->crossing.y = gdk_event->crossing.y; /* XXX: no better fallback here? */ clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); if (gdk_event->type == GDK_ENTER_NOTIFY) _clutter_input_device_set_stage (clutter_event_get_device (event), stage); else _clutter_input_device_set_stage (clutter_event_get_device (event), NULL); CLUTTER_NOTE (EVENT, "Crossing %s [%.2f, %.2f]", event->type == CLUTTER_ENTER ? "enter" : "leave", event->crossing.x, event->crossing.y); break; case GDK_FOCUS_CHANGE: if (gdk_event->focus_change.in) _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED); else _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0); break; case GDK_CONFIGURE: { gfloat w, h; clutter_actor_get_size (CLUTTER_ACTOR (stage), &w, &h); if (w != gdk_event->configure.width || h != gdk_event->configure.height) { clutter_actor_set_size (CLUTTER_ACTOR (stage), gdk_event->configure.width, gdk_event->configure.height); } } break; case GDK_SCROLL: event = clutter_event_new (CLUTTER_SCROLL); event->scroll.time = gdk_event->scroll.time; event->scroll.x = gdk_event->scroll.x; event->scroll.y = gdk_event->scroll.y; event->scroll.modifier_state = gdk_event->scroll.state; event->scroll.axes = NULL; /* XXX: must keep ClutterScrollDirection compatible with GdkScrollDirection */ event->scroll.direction = (ClutterScrollDirection) gdk_event->scroll.direction; clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); clutter_event_set_scroll_delta (event, gdk_event->scroll.delta_x, gdk_event->scroll.delta_y); break; case GDK_WINDOW_STATE: if (gdk_event->window_state.changed_mask & GDK_WINDOW_STATE_FULLSCREEN) { gboolean is_fullscreen; is_fullscreen = (gdk_event->window_state.new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0; if (is_fullscreen) _clutter_stage_update_state (stage, 0, CLUTTER_STAGE_STATE_FULLSCREEN); else _clutter_stage_update_state (stage, CLUTTER_STAGE_STATE_FULLSCREEN, 0); } break; case GDK_SETTING: _clutter_backend_gdk_update_setting (backend_gdk, gdk_event->setting.name); break; default: break; } if (event != NULL) { event->any.stage = stage; if (gdk_event->any.send_event) event->any.flags = CLUTTER_EVENT_FLAG_SYNTHETIC; _clutter_event_push (event, FALSE); spin = 1; CLUTTER_NOTE (EVENT, "Translated one event from Gdk"); /* handle also synthetic enter/leave events */ if (event->type == CLUTTER_MOTION) spin += 2; while (spin > 0 && (event = clutter_event_get ())) { /* forward the event into clutter for emission etc. */ clutter_do_event (event); clutter_event_free (event); --spin; } result = GDK_FILTER_REMOVE; } _clutter_threads_release_lock (); return result; }