static gboolean actor_manipulator_motion (ClutterActor *stage, ClutterEvent *event, gpointer data) { if (manipulated_actor) { gfloat x; gfloat y; gfloat dx; gfloat dy; x = (event->button.x); y = (event->button.y); clutter_actor_transform_stage_point ( clutter_actor_get_parent (manipulated_actor), x, y, &x, &y); dx = x - start_x; dy = y - start_y; switch (mode) { #ifdef BOX2D_MANIPULATION case Box2D: { ClutterVertex target = { x, y }; clutter_box2d_mouse_joint_update_target (mouse_joint, &target); break; } #endif case Direct: if (clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK) { x = orig_x + dx; y = orig_y + dy; clutter_actor_set_position (manipulated_actor, x, y); } else if (clutter_event_get_state (event) & CLUTTER_BUTTON2_MASK) { clutter_actor_set_rotation (manipulated_actor, CLUTTER_Z_AXIS, orig_rotation + dx, 0, 0, 0); } break; case None: g_print ("we shouldn't be doing %s in None mode\n", G_STRLOC); return FALSE; } } return FALSE; }
/** * clutter_input_device_update_from_event: * @device: a #ClutterInputDevice * @event: a #ClutterEvent * @update_stage: whether to update the #ClutterStage of the @device * using the stage of the event * * Forcibly updates the state of the @device using a #ClutterEvent * * This function should never be used by applications: it is meant * for integration with embedding toolkits, like clutter-gtk * * Embedding toolkits that disable the event collection inside Clutter * need to use this function to update the state of input devices depending * on a #ClutterEvent that they are going to submit to the event handling code * in Clutter though clutter_do_event(). Since the input devices hold the state * that is going to be used to fill in fields like the #ClutterButtonEvent * click count, or to emit synthesized events like %CLUTTER_ENTER and * %CLUTTER_LEAVE, it is necessary for embedding toolkits to also be * responsible of updating the input device state. * * For instance, this might be the code to translate an embedding toolkit * native motion notification into a Clutter #ClutterMotionEvent and ask * Clutter to process it: * * |[ * ClutterEvent c_event; * * translate_native_event_to_clutter (native_event, &c_event); * * clutter_do_event (&c_event); * ]| * * Before letting clutter_do_event() process the event, it is necessary to call * clutter_input_device_update_from_event(): * * |[ * ClutterEvent c_event; * ClutterDeviceManager *manager; * ClutterInputDevice *device; * * translate_native_event_to_clutter (native_event, &c_event); * * /* get the device manager */ * manager = clutter_device_manager_get_default (); * * /* use the default Core Pointer that Clutter * * backends register by default * */ * device = clutter_device_manager_get_core_device (manager, %CLUTTER_POINTER_DEVICE); * * /* update the state of the input device */ * clutter_input_device_update_from_event (device, &c_event, FALSE); * * clutter_do_event (&c_event); * ]| * * The @update_stage boolean argument should be used when the input device * enters and leaves a #ClutterStage; it will use the #ClutterStage field * of the passed @event to update the stage associated to the input device. * * Since: 1.2 */ void clutter_input_device_update_from_event (ClutterInputDevice *device, ClutterEvent *event, gboolean update_stage) { ClutterModifierType event_state; ClutterStage *event_stage; gfloat event_x, event_y; guint32 event_time; g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); g_return_if_fail (event != NULL); event_state = clutter_event_get_state (event); event_time = clutter_event_get_time (event); event_stage = clutter_event_get_stage (event); clutter_event_get_coords (event, &event_x, &event_y); _clutter_input_device_set_coords (device, event_x, event_y); _clutter_input_device_set_state (device, event_state); _clutter_input_device_set_time (device, event_time); if (update_stage) _clutter_input_device_set_stage (device, event_stage); }
static void emit_drag_end (ClutterDragAction *action, ClutterActor *actor, ClutterEvent *event) { ClutterDragActionPrivate *priv = action->priv; clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); /* we might not have emitted ::drag-begin yet */ if (!priv->emit_delayed_press) g_signal_emit (action, drag_signals[DRAG_END], 0, actor, priv->last_motion_x, priv->last_motion_y, clutter_event_get_state (event)); /* disconnect the capture */ if (priv->capture_id != 0) { g_signal_handler_disconnect (priv->stage, priv->capture_id); priv->capture_id = 0; } _clutter_stage_set_motion_events_enabled (priv->stage, priv->motion_events_enabled); priv->in_drag = FALSE; }
gboolean key_press_event(ClutterActor *stage, ClutterEvent *event, gpointer user_data) { UNUSED(user_data); guint keyval = clutter_event_get_key_symbol(event); ClutterModifierType state = clutter_event_get_state(event); gboolean ctrl_pressed = (state & CLUTTER_CONTROL_MASK ? TRUE : FALSE); if (keyval == CLUTTER_KEY_Escape) { if (clutter_stage_get_fullscreen(CLUTTER_STAGE(stage))) clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), FALSE); else clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), TRUE); } else if (keyval == CLUTTER_KEY_q) { // Quit application on ctrl-q, this quits the main loop // (if there is one) if (ctrl_pressed) { if (option_verbose) g_print("ctrl-q pressed. quitting.\n"); clutter_main_quit(); } } return TRUE; }
static void key_event_cb(ClutterActor *actor, ClutterKeyEvent *event, gpointer user_data) { TempiClutterStageNode *self = (TempiClutterStageNode *) user_data; (void) self; // TODO: remove this ClutterModifierType state = clutter_event_get_state((ClutterEvent*) event); bool ctrl_pressed = (state & CLUTTER_CONTROL_MASK ? true : false); switch (event->keyval) { case CLUTTER_KEY_q: if (ctrl_pressed) clutter_main_quit(); break; } }
static gboolean key_release_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) { guint keysym = clutter_event_get_key_symbol (event); ClutterModifierType mods = clutter_event_get_state (event); if (keysym == CLUTTER_KEY_q || ((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q)) clutter_main_quit (); return CLUTTER_EVENT_STOP; }
static gboolean on_captured_event (ClutterActor *stage, ClutterEvent *event, ClutterDragAction *action) { ClutterDragActionPrivate *priv = action->priv; ClutterActor *actor; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); if (!priv->in_drag) return FALSE; switch (clutter_event_type (event)) { case CLUTTER_MOTION: { ClutterModifierType mods = clutter_event_get_state (event); /* we might miss a button-release event in case of grabs, * so we need to check whether the button is still down * during a motion event */ if (mods & CLUTTER_BUTTON1_MASK) emit_drag_motion (action, actor, event); else emit_drag_end (action, actor, event); } break; case CLUTTER_BUTTON_RELEASE: if (priv->in_drag) emit_drag_end (action, actor, event); break; case CLUTTER_ENTER: case CLUTTER_LEAVE: if (priv->in_drag) return TRUE; break; default: break; } return FALSE; }
static gboolean on_key_release(ClutterActor *actor, ClutterEvent *event, MosesOverview* self) { MosesOverviewPrivate* priv = self->priv; MetaScreen* screen = meta_plugin_get_screen(priv->plugin); MetaDisplay* display = meta_screen_get_display(screen); ClutterModifierType state = clutter_event_get_state(event); g_debug("%s", __func__); if (priv->ready) { guint action = meta_display_get_keybinding_action(display, clutter_event_get_key_code(event), state); if (action == elsa_wm_get_action(ELSA_WM_PLUGIN(priv->plugin), "expose-windows")) { overview_animated_destroy(self, MOSES_OV_REASON_NORMAL, FALSE); return TRUE; } } return FALSE; }
static gboolean button_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) { gfloat x, y; gchar *event_type; guint button_pressed; ClutterModifierType state; gchar *ctrl_pressed; guint32 click_count; /* where the pointer was when the button event occurred */ clutter_event_get_coords (event, &x, &y); /* check whether it was a press or release event */ event_type = "released"; if (clutter_event_type (event) == CLUTTER_BUTTON_PRESS) event_type = "pressed"; /* which button triggered the event */ button_pressed = clutter_event_get_button (event); /* keys down when the button was pressed */ state = clutter_event_get_state (event); ctrl_pressed = "ctrl not pressed"; if (state & CLUTTER_CONTROL_MASK) ctrl_pressed = "ctrl pressed"; /* click count */ click_count = clutter_event_get_click_count (event); g_debug ("button %d %s at %.0f,%.0f; %s; click count %d", button_pressed, event_type, x, y, ctrl_pressed, click_count); return TRUE; }
static gboolean on_button_press (ClutterActor *actor, ClutterEvent *event, ClutterDragAction *action) { ClutterDragActionPrivate *priv = action->priv; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) return FALSE; if (clutter_event_get_button (event) != 1) return FALSE; if (priv->stage == NULL) priv->stage = CLUTTER_STAGE (clutter_actor_get_stage (actor)); clutter_event_get_coords (event, &priv->press_x, &priv->press_y); priv->press_state = clutter_event_get_state (event); priv->last_motion_x = priv->press_x; priv->last_motion_y = priv->press_y; priv->transformed_press_x = priv->press_x; priv->transformed_press_y = priv->press_y; clutter_actor_transform_stage_point (actor, priv->press_x, priv->press_y, &priv->transformed_press_x, &priv->transformed_press_y); priv->motion_events_enabled = _clutter_stage_get_motion_events_enabled (priv->stage); if (priv->x_drag_threshold == 0 || priv->y_drag_threshold == 0) emit_drag_begin (action, actor, event); else priv->emit_delayed_press = TRUE; priv->in_drag = TRUE; priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", G_CALLBACK (on_captured_event), action); return FALSE; }
//FIXME: actually key_release is activated even when key press (WTF). does it because I'm hold alt/super? static gboolean on_key_release(ClutterActor *actor, ClutterEvent *event, MetaSwitcher* self) { MetaSwitcherPrivate* priv = self->priv; MetaScreen* screen = meta_plugin_get_screen(priv->plugin); MetaDisplay* display = meta_screen_get_display(screen); ClutterModifierType state = clutter_event_get_state(event); guint keysym = clutter_event_get_key_symbol(event); guint action = meta_display_get_keybinding_action(display, clutter_event_get_key_code(event), state); int id = priv->selected_id; if (action == META_KEYBINDING_ACTION_SWITCH_WINDOWS) { id = (id + 1) % priv->apps->len; } else if (action == META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD) { id = (priv->apps->len + id - 1) % priv->apps->len; } else if (action == META_KEYBINDING_ACTION_SWITCH_APPLICATIONS) { id = (id + 1) % priv->apps->len; } else if (action == META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD) { id = (priv->apps->len + id - 1) % priv->apps->len; } _set_highlight(self, priv->selected_id, FALSE); _set_highlight(self, id, TRUE); g_debug("%s, key: 0x%x, action: %d, previd: %d, now: %d", __func__, keysym, action, priv->selected_id, id); priv->selected_id = id; switch(keysym) { //FIXME: do not hardcode keysyms, use action instead case CLUTTER_KEY_Super_L: case CLUTTER_KEY_Super_R: case CLUTTER_KEY_Alt_L: case CLUTTER_KEY_Alt_R: { if (priv->selected_id >= 0) { meta_window_activate(g_ptr_array_index(priv->apps, priv->selected_id), clutter_get_current_event_time()); } g_object_unref(self); } default: break; } return FALSE; }
/* An event was captured */ static gboolean _xfdashboard_click_action_on_captured_event(XfdashboardClickAction *self, ClutterEvent *inEvent, gpointer inUserData) { XfdashboardClickActionPrivate *priv; ClutterActor *stage G_GNUC_UNUSED; ClutterActor *actor; ClutterModifierType modifierState; gboolean hasButton; g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self), CLUTTER_EVENT_PROPAGATE); g_return_val_if_fail(CLUTTER_IS_ACTOR(inUserData), CLUTTER_EVENT_PROPAGATE); priv=self->priv; stage=CLUTTER_ACTOR(inUserData); hasButton=TRUE; /* Handle captured event */ actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self)); switch(clutter_event_type(inEvent)) { case CLUTTER_TOUCH_END: hasButton=FALSE; case CLUTTER_BUTTON_RELEASE: if(!priv->isHeld) return(CLUTTER_EVENT_STOP); if((hasButton && clutter_event_get_button(inEvent)!=priv->pressButton) || (hasButton && clutter_event_get_click_count(inEvent)!=1) || clutter_event_get_device_id(inEvent)!=priv->pressDeviceID || clutter_event_get_event_sequence(inEvent)!=priv->pressSequence) { return(CLUTTER_EVENT_PROPAGATE); } _xfdashboard_click_action_set_held(self, FALSE); _xfdashboard_click_action_cancel_long_press(self); /* Disconnect the capture */ if(priv->captureID!=0) { g_signal_handler_disconnect(priv->stage, priv->captureID); priv->captureID = 0; } if(priv->longPressID!=0) { g_source_remove(priv->longPressID); priv->longPressID=0; } if(!clutter_actor_contains(actor, clutter_event_get_source(inEvent))) { return(CLUTTER_EVENT_PROPAGATE); } /* Exclude any button-mask so that we can compare * the press and release states properly */ modifierState=clutter_event_get_state(inEvent) & ~(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK | CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK); /* If press and release states don't match we simply ignore * modifier keys. i.e. modifier keys are expected to be pressed * throughout the whole click */ if(modifierState!=priv->modifierState) priv->modifierState=0; _xfdashboard_click_action_set_pressed(self, FALSE); g_signal_emit(self, XfdashboardClickActionSignals[SIGNAL_CLICKED], 0, actor); break; case CLUTTER_MOTION: case CLUTTER_TOUCH_UPDATE: { gfloat motionX, motionY; gfloat deltaX, deltaY; if(!priv->isHeld) return(CLUTTER_EVENT_PROPAGATE); clutter_event_get_coords (inEvent, &motionX, &motionY); deltaX=ABS(motionX-priv->pressX); deltaY=ABS(motionY-priv->pressY); if(deltaX>priv->dragThreshold || deltaY>priv->dragThreshold) { _xfdashboard_click_action_cancel_long_press(self); } } break; default: break; } /* This is line changed in returning CLUTTER_EVENT_PROPAGATE * instead of CLUTTER_EVENT_STOP */ return(CLUTTER_EVENT_PROPAGATE); }
static gboolean on_captured_event (ClutterActor *stage, ClutterEvent *event, ClutterClickAction *action) { ClutterClickActionPrivate *priv = action->priv; ClutterActor *actor; ClutterModifierType modifier_state; gboolean has_button = TRUE; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); switch (clutter_event_type (event)) { case CLUTTER_TOUCH_END: has_button = FALSE; case CLUTTER_BUTTON_RELEASE: if (!priv->is_held) return CLUTTER_EVENT_STOP; if ((has_button && clutter_event_get_button (event) != priv->press_button) || (has_button && clutter_event_get_click_count (event) != 1) || clutter_event_get_device_id (event) != priv->press_device_id || clutter_event_get_event_sequence (event) != priv->press_sequence) return CLUTTER_EVENT_PROPAGATE; click_action_set_held (action, FALSE); click_action_cancel_long_press (action); /* disconnect the capture */ if (priv->capture_id != 0) { g_signal_handler_disconnect (priv->stage, priv->capture_id); priv->capture_id = 0; } if (priv->long_press_id != 0) { g_source_remove (priv->long_press_id); priv->long_press_id = 0; } if (!clutter_actor_contains (actor, clutter_event_get_source (event))) return CLUTTER_EVENT_PROPAGATE; /* exclude any button-mask so that we can compare * the press and release states properly */ modifier_state = clutter_event_get_state (event) & ~(CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK | CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK); /* if press and release states don't match we * simply ignore modifier keys. i.e. modifier keys * are expected to be pressed throughout the whole * click */ if (modifier_state != priv->modifier_state) priv->modifier_state = 0; click_action_set_pressed (action, FALSE); g_signal_emit (action, click_signals[CLICKED], 0, actor); break; case CLUTTER_MOTION: case CLUTTER_TOUCH_UPDATE: { gfloat motion_x, motion_y; gfloat delta_x, delta_y; if (!priv->is_held) return CLUTTER_EVENT_PROPAGATE; clutter_event_get_coords (event, &motion_x, &motion_y); delta_x = ABS (motion_x - priv->press_x); delta_y = ABS (motion_y - priv->press_y); if (delta_x > priv->drag_threshold || delta_y > priv->drag_threshold) click_action_cancel_long_press (action); } break; default: break; } return CLUTTER_EVENT_STOP; }
static gboolean on_event (ClutterActor *actor, ClutterEvent *event, ClutterClickAction *action) { ClutterClickActionPrivate *priv = action->priv; gboolean has_button = TRUE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) return CLUTTER_EVENT_PROPAGATE; switch (clutter_event_type (event)) { case CLUTTER_TOUCH_BEGIN: has_button = FALSE; case CLUTTER_BUTTON_PRESS: if (has_button && clutter_event_get_click_count (event) != 1) return CLUTTER_EVENT_PROPAGATE; if (priv->is_held) return CLUTTER_EVENT_STOP; if (!clutter_actor_contains (actor, clutter_event_get_source (event))) return CLUTTER_EVENT_PROPAGATE; priv->press_button = has_button ? clutter_event_get_button (event) : 0; priv->press_device_id = clutter_event_get_device_id (event); priv->press_sequence = clutter_event_get_event_sequence (event); priv->modifier_state = clutter_event_get_state (event); clutter_event_get_coords (event, &priv->press_x, &priv->press_y); if (priv->long_press_threshold < 0) { ClutterSettings *settings = clutter_settings_get_default (); g_object_get (settings, "dnd-drag-threshold", &priv->drag_threshold, NULL); } else priv->drag_threshold = priv->long_press_threshold; if (priv->stage == NULL) priv->stage = clutter_actor_get_stage (actor); priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", G_CALLBACK (on_captured_event), action); click_action_set_pressed (action, TRUE); click_action_set_held (action, TRUE); click_action_query_long_press (action); break; case CLUTTER_ENTER: click_action_set_pressed (action, priv->is_held); break; case CLUTTER_LEAVE: click_action_set_pressed (action, priv->is_held); click_action_cancel_long_press (action); break; default: break; } return CLUTTER_EVENT_PROPAGATE; }
/** * cinnamon_tray_icon_click: * @icon: a #CinnamonTrayIcon * @event: the #ClutterEvent triggering the fake click * * Fakes a press and release on @icon. @event must be a * %CLUTTER_BUTTON_RELEASE event. Its relevant details will be passed * on to the icon, but its coordinates will be ignored; the click is * always made on the center of @icon. */ void cinnamon_tray_icon_click (CinnamonTrayIcon *icon, ClutterEvent *event) { XButtonEvent xbevent; XCrossingEvent xcevent; GdkWindow *remote_window; GdkScreen *screen; int x_root, y_root; Display *xdisplay; Window xwindow, xrootwindow; g_return_if_fail (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE); gdk_error_trap_push (); remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket)); if (remote_window == NULL) { g_warning ("cinnamon tray: plug window is gone"); gdk_error_trap_pop_ignored (); return; } xwindow = GDK_WINDOW_XID (remote_window); xdisplay = GDK_WINDOW_XDISPLAY (remote_window); screen = gdk_window_get_screen (remote_window); xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen)); gdk_window_get_origin (remote_window, &x_root, &y_root); /* First make the icon believe the pointer is inside it */ xcevent.type = EnterNotify; xcevent.window = xwindow; xcevent.root = xrootwindow; xcevent.subwindow = None; xcevent.time = clutter_event_get_time (event); xcevent.x = gdk_window_get_width (remote_window) / 2; xcevent.y = gdk_window_get_height (remote_window) / 2; xcevent.x_root = x_root + xcevent.x; xcevent.y_root = y_root + xcevent.y; xcevent.mode = NotifyNormal; xcevent.detail = NotifyNonlinear; xcevent.same_screen = True; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); /* Now do the click */ xbevent.type = ButtonPress; xbevent.window = xwindow; xbevent.root = xrootwindow; xbevent.subwindow = None; xbevent.time = xcevent.time; xbevent.x = xcevent.x; xbevent.y = xcevent.y; xbevent.x_root = xcevent.x_root; xbevent.y_root = xcevent.y_root; xbevent.state = clutter_event_get_state (event); xbevent.button = clutter_event_get_button (event); xbevent.same_screen = True; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); xbevent.type = ButtonRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); /* And move the pointer back out */ xcevent.type = LeaveNotify; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); gdk_error_trap_pop_ignored (); }
/** * cinnamon_get_event_state: * @event: a #ClutterEvent * * Gets the current state of the event (the set of modifier keys that * are pressed down). Thhis is a wrapper around * clutter_event_get_state() that strips out any un-declared modifier * flags, to make gjs happy; see * https://bugzilla.gnome.org/show_bug.cgi?id=597292. * * Return value: the state from the event */ ClutterModifierType cinnamon_get_event_state (ClutterEvent *event) { ClutterModifierType state = clutter_event_get_state (event); return state & CLUTTER_MODIFIER_MASK; }
/** * clutter_event_has_control_modifier: * @event: a #ClutterEvent * * Checks whether @event has the Control modifier mask set. * * Return value: %TRUE if the event has the Control modifier mask set * * Since: 1.12 */ gboolean clutter_event_has_control_modifier (const ClutterEvent *event) { return (clutter_event_get_state (event) & CLUTTER_CONTROL_MASK) != FALSE; }
/** * clutter_event_has_shift_modifier: * @event: a #ClutterEvent * * Checks whether @event has the Shift modifier mask set. * * Return value: %TRUE if the event has the Shift modifier mask set * * Since: 1.12 */ gboolean clutter_event_has_shift_modifier (const ClutterEvent *event) { return (clutter_event_get_state (event) & CLUTTER_SHIFT_MASK) != FALSE; }
static gboolean stage_captured_event_cb (ClutterActor *stage, ClutterEvent *event, ClutterGestureAction *action) { ClutterGestureActionPrivate *priv = action->priv; ClutterActor *actor; gint position; float threshold_x, threshold_y; gboolean return_value; GesturePoint *point; ClutterEventType event_type; event_type = clutter_event_type (event); if (event_type != CLUTTER_TOUCH_CANCEL && event_type != CLUTTER_TOUCH_UPDATE && event_type != CLUTTER_TOUCH_END && event_type != CLUTTER_MOTION && event_type != CLUTTER_BUTTON_RELEASE) return CLUTTER_EVENT_PROPAGATE; if ((point = gesture_find_point (action, event, &position)) == NULL) return CLUTTER_EVENT_PROPAGATE; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); switch (clutter_event_type (event)) { case CLUTTER_MOTION: { ClutterModifierType mods = clutter_event_get_state (event); /* we might miss a button-release event in case of grabs, * so we need to check whether the button is still down * during a motion event */ if (!(mods & CLUTTER_BUTTON1_MASK)) { cancel_gesture (action); return CLUTTER_EVENT_PROPAGATE; } } /* Follow same code path as a touch event update */ case CLUTTER_TOUCH_UPDATE: if (!priv->in_gesture) { if (priv->points->len < priv->requested_nb_points) { gesture_update_motion_point (point, event); return CLUTTER_EVENT_PROPAGATE; } /* Wait until the drag threshold has been exceeded * before starting _TRIGGER_EDGE_AFTER gestures. */ if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_AFTER && gesture_point_pass_threshold (action, point, event)) { gesture_update_motion_point (point, event); return CLUTTER_EVENT_PROPAGATE; } if (!begin_gesture (action, actor)) { if ((point = gesture_find_point (action, event, &position)) != NULL) gesture_update_motion_point (point, event); return CLUTTER_EVENT_PROPAGATE; } if ((point = gesture_find_point (action, event, &position)) == NULL) return CLUTTER_EVENT_PROPAGATE; } gesture_update_motion_point (point, event); g_signal_emit (action, gesture_signals[GESTURE_PROGRESS], 0, actor, &return_value); if (!return_value) { cancel_gesture (action); return CLUTTER_EVENT_PROPAGATE; } /* Check if a _TRIGGER_EDGE_BEFORE gesture needs to be cancelled because * the drag threshold has been exceeded. */ clutter_gesture_action_get_threshold_trigger_distance (action, &threshold_x, &threshold_y); if (priv->edge == CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE && ((fabsf (point->press_y - point->last_motion_y) > threshold_y) || (fabsf (point->press_x - point->last_motion_x) > threshold_x))) { cancel_gesture (action); return CLUTTER_EVENT_PROPAGATE; } break; case CLUTTER_BUTTON_RELEASE: case CLUTTER_TOUCH_END: { gesture_update_release_point (point, event); if (priv->in_gesture && ((priv->points->len - 1) < priv->requested_nb_points)) { priv->in_gesture = FALSE; g_signal_emit (action, gesture_signals[GESTURE_END], 0, actor); } gesture_unregister_point (action, position); } break; case CLUTTER_TOUCH_CANCEL: { gesture_update_release_point (point, event); if (priv->in_gesture) { priv->in_gesture = FALSE; cancel_gesture (action); } gesture_unregister_point (action, position); } break; default: break; } if (priv->points->len == 0 && priv->stage_capture_id) { g_signal_handler_disconnect (priv->stage, priv->stage_capture_id); priv->stage_capture_id = 0; } return CLUTTER_EVENT_PROPAGATE; }
/** * shell_tray_icon_click: * @icon: a #ShellTrayIcon * @event: the #ClutterEvent triggering the fake click * * Fakes a press and release on @icon. @event must be a * %CLUTTER_BUTTON_RELEASE, %CLUTTER_KEY_PRESS or %CLUTTER_KEY_RELEASE event. * Its relevant details will be passed on to the icon, but its * coordinates will be ignored; the click is * always made on the center of @icon. */ void shell_tray_icon_click (ShellTrayIcon *icon, ClutterEvent *event) { XKeyEvent xkevent; XButtonEvent xbevent; XCrossingEvent xcevent; GdkWindow *remote_window; GdkScreen *screen; int x_root, y_root; Display *xdisplay; Window xwindow, xrootwindow; ClutterEventType event_type = clutter_event_type (event); g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE || event_type == CLUTTER_KEY_PRESS || event_type == CLUTTER_KEY_RELEASE); gdk_error_trap_push (); remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket)); xwindow = GDK_WINDOW_XID (remote_window); xdisplay = GDK_WINDOW_XDISPLAY (remote_window); screen = gdk_window_get_screen (remote_window); xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen)); gdk_window_get_origin (remote_window, &x_root, &y_root); /* First make the icon believe the pointer is inside it */ xcevent.type = EnterNotify; xcevent.window = xwindow; xcevent.root = xrootwindow; xcevent.subwindow = None; xcevent.time = clutter_event_get_time (event); xcevent.x = gdk_window_get_width (remote_window) / 2; xcevent.y = gdk_window_get_height (remote_window) / 2; xcevent.x_root = x_root + xcevent.x; xcevent.y_root = y_root + xcevent.y; xcevent.mode = NotifyNormal; xcevent.detail = NotifyNonlinear; xcevent.same_screen = True; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); /* Now do the click */ if (event_type == CLUTTER_BUTTON_RELEASE) { xbevent.window = xwindow; xbevent.root = xrootwindow; xbevent.subwindow = None; xbevent.time = xcevent.time; xbevent.x = xcevent.x; xbevent.y = xcevent.y; xbevent.x_root = xcevent.x_root; xbevent.y_root = xcevent.y_root; xbevent.state = clutter_event_get_state (event); xbevent.same_screen = True; xbevent.type = ButtonPress; xbevent.button = clutter_event_get_button (event); XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); xbevent.type = ButtonRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); } else { xkevent.window = xwindow; xkevent.root = xrootwindow; xkevent.subwindow = None; xkevent.time = xcevent.time; xkevent.x = xcevent.x; xkevent.y = xcevent.y; xkevent.x_root = xcevent.x_root; xkevent.y_root = xcevent.y_root; xkevent.state = clutter_event_get_state (event); xkevent.same_screen = True; xkevent.keycode = clutter_event_get_key_code (event); xkevent.type = KeyPress; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent); if (event_type == CLUTTER_KEY_RELEASE) { /* If the application takes a grab on KeyPress, we don't * want to send it a KeyRelease. There's no good way of * knowing whether a tray icon will take a grab, so just * assume it does, and don't send the KeyRelease. That might * make the tracking for key events messed up if it doesn't take * a grab, but the tray icon won't get key focus in normal cases, * so let's hope this isn't too damaging... */ xkevent.type = KeyRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent); } } /* And move the pointer back out */ xcevent.type = LeaveNotify; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); gdk_error_trap_pop_ignored (); }
IO_METHOD(IoClutterEvent, getState) { return IONUMBER(clutter_event_get_state(IOCEVENT(self))); }
/* An event was received */ static gboolean _xfdashboard_click_action_on_event(XfdashboardClickAction *self, ClutterEvent *inEvent, gpointer inUserData) { XfdashboardClickActionPrivate *priv; gboolean hasButton; ClutterActor *actor; g_return_val_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self), CLUTTER_EVENT_PROPAGATE); g_return_val_if_fail(CLUTTER_IS_ACTOR(inUserData), CLUTTER_EVENT_PROPAGATE); priv=self->priv; hasButton=TRUE; actor=CLUTTER_ACTOR(inUserData); /* Check if actor is enabled to handle events */ if(!clutter_actor_meta_get_enabled(CLUTTER_ACTOR_META(self))) return(CLUTTER_EVENT_PROPAGATE); /* Handle event */ switch(clutter_event_type(inEvent)) { case CLUTTER_TOUCH_BEGIN: hasButton=FALSE; case CLUTTER_BUTTON_PRESS: /* We only handle single clicks if it is pointer device */ if(hasButton && clutter_event_get_click_count(inEvent)!=1) { return(CLUTTER_EVENT_PROPAGATE); } /* Do we already held the press? */ if(priv->isHeld) return(CLUTTER_EVENT_STOP); /* Is the source of event a child of this actor. If not do * not handle this event but any other. */ if(!clutter_actor_contains(actor, clutter_event_get_source(inEvent))) { return(CLUTTER_EVENT_PROPAGATE); } /* Remember event data */ priv->pressButton=hasButton ? clutter_event_get_button(inEvent) : 0; priv->pressDeviceID=clutter_event_get_device_id(inEvent); priv->pressSequence=clutter_event_get_event_sequence(inEvent); priv->modifierState=clutter_event_get_state(inEvent); clutter_event_get_coords(inEvent, &priv->pressX, &priv->pressY); if(priv->longPressThreshold<0) { ClutterSettings *settings=clutter_settings_get_default(); g_object_get(settings, "dnd-drag-threshold", &priv->dragThreshold, NULL); } else priv->dragThreshold=priv->longPressThreshold; if(priv->stage==NULL) priv->stage=clutter_actor_get_stage(actor); /* Connect signals */ priv->captureID=g_signal_connect_object(priv->stage, "captured-event", G_CALLBACK(_xfdashboard_click_action_on_captured_event), self, G_CONNECT_AFTER | G_CONNECT_SWAPPED); /* Set state of this action */ _xfdashboard_click_action_set_pressed(self, TRUE); _xfdashboard_click_action_set_held(self, TRUE); _xfdashboard_click_action_query_long_press(self); break; case CLUTTER_ENTER: _xfdashboard_click_action_set_pressed(self, priv->isHeld); break; case CLUTTER_LEAVE: _xfdashboard_click_action_set_pressed(self, priv->isHeld); _xfdashboard_click_action_cancel_long_press(self); break; default: break; } return(CLUTTER_EVENT_PROPAGATE); }