Пример #1
0
static gboolean
handle_capture_event_cb (ClutterActor *trough,
                         ClutterEvent *event,
                         StScrollBar  *bar)
{
  if (clutter_event_type (event) == CLUTTER_MOTION)
    {
      move_slider (bar,
                   ((ClutterMotionEvent*) event)->x,
                   ((ClutterMotionEvent*) event)->y);
    }
  else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE
           && ((ClutterButtonEvent*) event)->button == 1)
    {
      ClutterActor *stage, *target;

      stop_scrolling (bar);

      /* check if the mouse pointer has left the handle during the drag and
       * remove the hover state if it has */
      stage = clutter_actor_get_stage (bar->priv->trough);
      target = clutter_stage_get_actor_at_pos ((ClutterStage*) stage,
                                               CLUTTER_PICK_REACTIVE,
                                               ((ClutterButtonEvent*) event)->x,
                                               ((ClutterButtonEvent*) event)->y);
      if (target != bar->priv->handle)
        {
          st_widget_remove_style_pseudo_class ((StWidget*) bar->priv->handle, "hover");
        }
    }

  return TRUE;
}
Пример #2
0
/* Action signal to move selection was emitted */
static gboolean _xfdashboard_focusable_selection_move_to_direction(XfdashboardFocusable *self,
																	XfdashboardFocusable *inSource,
																	const gchar *inAction,
																	ClutterEvent *inEvent,
																	XfdashboardSelectionTarget inDirection)
{
	ClutterActor				*currentSelection;
	ClutterActor				*newSelection;

	g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(self), CLUTTER_EVENT_PROPAGATE);
	g_return_val_if_fail(inEvent, CLUTTER_EVENT_PROPAGATE);
	g_return_val_if_fail(inDirection<=XFDASHBOARD_SELECTION_TARGET_NEXT, CLUTTER_EVENT_PROPAGATE);

	/* Check for key press or release event */
	if(clutter_event_type(inEvent)!=CLUTTER_KEY_PRESS &&
		clutter_event_type(inEvent)!=CLUTTER_KEY_RELEASE)
	{
		return(CLUTTER_EVENT_PROPAGATE);
	}

	/* If focusable actor does not support selections return here with event unhandled */
	if(!xfdashboard_focusable_supports_selection(self)) return(CLUTTER_EVENT_PROPAGATE);

	/* Find new selection */
	currentSelection=xfdashboard_focusable_get_selection(self);
	newSelection=xfdashboard_focusable_find_selection(self, currentSelection, inDirection);

	/* Set new selection */
	xfdashboard_focusable_set_selection(self, newSelection);

	/* All done so return and stop further processing of this action */
	return(CLUTTER_EVENT_STOP);
}
Пример #3
0
static gboolean
actor_captured_event_cb (ClutterActor *actor,
                         ClutterEvent *event,
                         ClutterGestureAction *action)
{
  ClutterGestureActionPrivate *priv = action->priv;
  GesturePoint *point G_GNUC_UNUSED;

  if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) &&
      (clutter_event_type (event) != CLUTTER_TOUCH_BEGIN))
    return CLUTTER_EVENT_PROPAGATE;

  if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
    return CLUTTER_EVENT_PROPAGATE;

  point = gesture_register_point (action, event);

  if (priv->stage == NULL)
    priv->stage = clutter_actor_get_stage (actor);

  if (priv->stage_capture_id == 0)
    priv->stage_capture_id =
      g_signal_connect_after (priv->stage, "captured-event",
                              G_CALLBACK (stage_captured_event_cb),
                              action);

  /* Start the gesture immediately if the gesture has no
   * _TRIGGER_EDGE_AFTER drag threshold. */
  if ((priv->points->len >= priv->requested_nb_points) &&
      (priv->edge != CLUTTER_GESTURE_TRIGGER_EDGE_AFTER))
    begin_gesture (action, actor);

  return CLUTTER_EVENT_PROPAGATE;
}
Пример #4
0
static gboolean
on_handle_capture_event (ClutterActor *trough,
                         ClutterEvent *event,
                         MxSlider     *bar)
{
  MxSliderPrivate *priv = bar->priv;

  if (clutter_event_type (event) == CLUTTER_MOTION)
    {
      drag_handle (bar,
                   ((ClutterMotionEvent*)event)->x,
                   ((ClutterMotionEvent*)event)->y);
    }
  else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE
           && ((ClutterButtonEvent*)event)->button == 1)
    {
      ClutterActor *stage, *target;

      stage = clutter_actor_get_stage(priv->trough);

      if (priv->capture_handler)
        {
          g_signal_handler_disconnect (stage, priv->capture_handler);
          priv->capture_handler = 0;

          /* update the handle position */
          mx_slider_allocate_fill_handle (bar, NULL, 0);
          clutter_actor_queue_redraw (CLUTTER_ACTOR (bar));
        }

      clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage), TRUE);

      /* check if the mouse pointer has left the handle during the drag and
       * remove the hover state if it has */
      target =
        clutter_stage_get_actor_at_pos ((ClutterStage*) stage,
                                        CLUTTER_PICK_REACTIVE,
                                        ((ClutterButtonEvent*) event)->x,
                                        ((ClutterButtonEvent*) event)->y);
      if (target != priv->handle)
        {
          mx_stylable_set_style_pseudo_class (MX_STYLABLE (priv->handle),
                                            NULL);
        }

      /* emit the stop signal */
      g_signal_emit (bar, signals[SLIDE_STOP], 0);
    }

  return FALSE;
}
Пример #5
0
/* An event after a tooltip was shown so check if tooltip should be hidden again */
static gboolean _xfdashboard_tooltip_action_on_captured_event_after_tooltip(XfdashboardTooltipAction *self,
																			ClutterEvent *inEvent,
																			gpointer inUserData)
{
	gboolean		doHide;

	g_return_val_if_fail(XFDASHBOARD_IS_TOOLTIP_ACTION(self), CLUTTER_EVENT_PROPAGATE);
	g_return_val_if_fail(XFDASHBOARD_IS_STAGE(inUserData), CLUTTER_EVENT_PROPAGATE);

	/* Check if tooltip should be hidden depending on event type */
	switch(clutter_event_type(inEvent))
	{
		case CLUTTER_NOTHING:
		case CLUTTER_MOTION:
			doHide=FALSE;
			break;

		default:
			doHide=TRUE;
			break;
	}

	/* Hide tooltip if requested */
	if(doHide)
	{
		_xfdashboard_tooltip_action_on_leave_event(self, inEvent, inUserData);
	}

	return(CLUTTER_EVENT_PROPAGATE);
}
Пример #6
0
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;
}
Пример #7
0
static void
drag_grab_button (MetaWaylandPointerGrab *grab,
		  const ClutterEvent     *event)
{
  MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
  MetaWaylandSeat *seat = drag_grab->seat;
  ClutterEventType event_type = clutter_event_type (event);

  if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
      event_type == CLUTTER_BUTTON_RELEASE)
    {
      gboolean success = FALSE;

      if (drag_grab->drag_focus_data_device &&
          drag_grab->drag_data_source->has_target)
        {
          wl_data_device_send_drop (drag_grab->drag_focus_data_device);
          success = TRUE;
        }

      /* Finish drag and let actor self-destruct */
      meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
                                  success);
      drag_grab->feedback_actor = NULL;
    }

  if (seat->pointer.button_count == 0 &&
      event_type == CLUTTER_BUTTON_RELEASE)
    data_device_end_drag_grab (drag_grab);
}
Пример #8
0
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
handle_capture_event_cb (ClutterActor *trough,
                         ClutterEvent *event,
                         MxScrollBar  *bar)
{
  if (clutter_event_type (event) == CLUTTER_MOTION)
    {
      move_slider (bar,
                   ((ClutterMotionEvent*) event)->x,
                   ((ClutterMotionEvent*) event)->y);
    }
  else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE
           && ((ClutterButtonEvent*) event)->button == 1)
    {
      ClutterActor *stage, *target;

      stage = clutter_actor_get_stage(bar->priv->trough);

      if (bar->priv->capture_handler)
        {
          g_signal_handler_disconnect (stage, bar->priv->capture_handler);
          bar->priv->capture_handler = 0;
        }

      clutter_set_motion_events_enabled (TRUE);
      g_signal_emit (bar, signals[SCROLL_STOP], 0);

      /* check if the mouse pointer has left the handle during the drag and
       * remove the hover state if it has */
      target = clutter_stage_get_actor_at_pos ((ClutterStage*) stage,
                                               CLUTTER_PICK_REACTIVE,
                                               ((ClutterButtonEvent*) event)->x,
                                               ((ClutterButtonEvent*) event)->y);
      if (target != bar->priv->handle)
        {
          mx_stylable_set_style_pseudo_class (MX_STYLABLE (bar->priv->handle),
                                              NULL);
        }
      else
        {
          /* allow the release event to continue to the handle for processing */
          return FALSE;
        }
    }

  return TRUE;
}
Пример #10
0
gboolean Animation::handleTouchEvents(ClutterActor *actor, ClutterEvent *event, gpointer user_data) {

    ClutterEventType eventType = clutter_event_type(event);

//    if (eventType == CLUTTER_TOUCH_END) {
//        // printf("Touch end!\n");
//
//    } else

    if (eventType == CLUTTER_TOUCH_UPDATE || eventType == CLUTTER_MOTION) {

        // Rebuild the struct from the pointer we handed in:
//        TouchData *data;
//        data = (TouchData *) user_data;
        gfloat stage_x, stage_y;
        gfloat actor_x = 0, actor_y = 0;

        clutter_event_get_coords(event, &stage_x, &stage_y);
        clutter_actor_transform_stage_point(actor, stage_x, stage_y, &actor_x, &actor_y);

//        printf("Touch Move!!\nx: %f\ny: %f\n\n", actor_x, actor_y );

        // Now we have some x,y coordinates we can throw back at those animations!
        //  but we should probably scale them now since we have all the stuff we need
        //  to do so in this block...
        //
        // This will scale both to 0.0 <-> 255.0:
        //actor_x = actor_x / clutter_actor_get_width(actor) * 255;
        //actor_y = actor_y / clutter_actor_get_height(actor) * 255;

        // This will scale both to the actual on screen pixel size:
        actor_x = actor_x * osd_scale;
        actor_y = actor_y * osd_scale;

        // We only want integers:
        temp_x = static_cast<int>(actor_x);
        temp_y = static_cast<int>(actor_y);

        // And this will map the values around so that we can use the full range even though
        // the edges of the touchscreen are not really touchable:
        input_x = map(temp_x, 0, WIDTH*osd_scale, 0, WIDTH*osd_scale+(WIDTH*osd_scale-150));
        input_y = map(temp_y, 0, HEIGHT*osd_scale, 0-50, HEIGHT*osd_scale+(HEIGHT*osd_scale-750));

//        input_x = temp_x;
//        input_y = temp_y;

//        printf("Touch Move!!\nx: %i\ny: %i\n\n", input_x, input_y );
    }
//    else {
//        // printf("Some other touch event %i\n", eventType);
//    }

    return CLUTTER_EVENT_STOP;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
static gboolean
st_im_text_captured_event (ClutterActor *actor,
                           ClutterEvent *event)
{
  StIMText *self = ST_IM_TEXT (actor);
  StIMTextPrivate *priv = self->priv;
  ClutterText *clutter_text = CLUTTER_TEXT (actor);
  ClutterEventType type = clutter_event_type (event);
  gboolean result = FALSE;
  int old_position;

  if (type != CLUTTER_KEY_PRESS && type != CLUTTER_KEY_RELEASE)
    return FALSE;

  if (clutter_text_get_editable (clutter_text))
    {
      GdkEventKey *event_gdk = key_event_to_gdk ((ClutterKeyEvent *)event);

      if (gtk_im_context_filter_keypress (priv->im_context, event_gdk))
        {
          priv->need_im_reset = TRUE;
          result = TRUE;
        }

      gdk_event_free ((GdkEvent *)event_gdk);
    }

  old_position = clutter_text_get_cursor_position (clutter_text);

  if (!result &&
      CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->captured_event)
    result = CLUTTER_ACTOR_CLASS (st_im_text_parent_class)->captured_event (actor, event);

  if (type == CLUTTER_KEY_PRESS &&
      clutter_text_get_cursor_position (clutter_text) != old_position)
    reset_im_context (self);

  return result;
}
Пример #14
0
/* input handler */
static gboolean
input_cb (ClutterStage *stage,
	  ClutterEvent *event,
	  gpointer      data)
{
  ClutterEventType event_type = clutter_event_type (event);
  SuperOH *oh = data;

  if (event_type == CLUTTER_BUTTON_PRESS)
    {
      ClutterActor *a;
      gfloat x, y;

      clutter_event_get_coords (event, &x, &y);

      a = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_ALL, x, y);
      if (a != NULL && (CLUTTER_IS_TEXTURE (a) || CLUTTER_IS_CLONE (a)))
	clutter_actor_hide (a);
    }
  else if (event->type == CLUTTER_KEY_PRESS)
    {
      g_print ("*** key press event (key:%c) ***\n",
	       clutter_event_get_key_symbol (event));
      
      if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q)
	gtk_main_quit ();
      else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r)
        {
          int i;

          for (i = 0; i < NHANDS; i++)
            clutter_actor_show (oh->hand[i]);
        }
    }

  return TRUE;
}
Пример #15
0
IO_METHOD(IoClutterEvent, eventType) {
  return IONUMBER(clutter_event_type(IOCEVENT(self)));
}
Пример #16
0
/**
 * 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 ();
}
Пример #17
0
/* Handle key event (it is either key-press or key-release) by focusable actor
 * which has the focus or by specified actor.
 */
gboolean xfdashboard_focus_manager_handle_key_event(XfdashboardFocusManager *self, const ClutterEvent *inEvent, XfdashboardFocusable *inFocusable)
{
	XfdashboardFocusManagerPrivate	*priv;

	g_return_val_if_fail(XFDASHBOARD_IS_FOCUS_MANAGER(self), CLUTTER_EVENT_PROPAGATE);
	g_return_val_if_fail(inEvent, CLUTTER_EVENT_PROPAGATE);
	g_return_val_if_fail(clutter_event_type(inEvent)==CLUTTER_KEY_PRESS || clutter_event_type(inEvent)==CLUTTER_KEY_RELEASE, CLUTTER_EVENT_PROPAGATE);
	g_return_val_if_fail(!inFocusable || XFDASHBOARD_IS_FOCUSABLE(inFocusable), CLUTTER_EVENT_PROPAGATE);

	priv=self->priv;

	/* If no focusable actor was specified then use current focused actor */
	if(!inFocusable)
	{
		inFocusable=priv->currentFocus;

		/* If still no focusable actor is available we cannot handle event
		 * so let the others try it by propagating event.
		 */
		if(!inFocusable) return(CLUTTER_EVENT_PROPAGATE);
	}

	/* Synthesize event for specified focusable actor */
	if(inFocusable)
	{
		XfdashboardBindingsPool			*bindings;
		const XfdashboardBinding		*binding;
		gboolean						eventStatus;

		/* Take reference on ourselve and the focusable actor to keep them alive when handling event */
		g_object_ref(self);
		g_object_ref(inFocusable);

		/* Lookup action for event and emit action if a binding was found
		 * for this event.
		 */
		eventStatus=CLUTTER_EVENT_PROPAGATE;
		bindings=xfdashboard_bindings_pool_get_default();
		binding=xfdashboard_bindings_pool_find_for_event(bindings, CLUTTER_ACTOR(inFocusable), inEvent);
		if(binding)
		{
			const gchar					*target;
			const gchar					*action;
			GSList						*targetFocusables;
			GSList						*iter;
			GSignalQuery				signalData={ 0, };

			/* Get action of binding */
			action=xfdashboard_binding_get_action(binding);

			/* Build up list of targets which is either the requested focusable actor,
			 * the current focused actor or focusable actors of a specific type
			 */
			targetFocusables=NULL;
			target=xfdashboard_binding_get_target(binding);
			if(target)
			{
				/* Target class name is specified so build up a list of targets */
				targetFocusables=_xfdashboard_focus_manager_get_targets_for_binding(self, binding);
			}
				else
				{
					/* No target class name was specified so add requested focusable
					 * actor to list of target.
					 */
					targetFocusables=g_slist_append(targetFocusables, g_object_ref(inFocusable));
				}

			g_debug("Target list for action '%s' has %d actors",
						action,
						g_slist_length(targetFocusables));

			/* Emit action of binding to each actor in target list just build up */
			for(iter=targetFocusables; iter; iter=g_slist_next(iter))
			{
				GObject				*targetObject;
				guint				signalID;

				/* Get target to emit action signal at */
				targetObject=G_OBJECT(iter->data);

				/* Check if target provides action requested as signal */
				signalID=g_signal_lookup(action, G_OBJECT_TYPE(targetObject));
				if(!signalID)
				{
					g_warning(_("Object type %s does not provide action '%s'"),
								G_OBJECT_TYPE_NAME(targetObject),
								action);
					continue;
				}

				/* Query signal for detailed data */
				g_signal_query(signalID, &signalData);

				/* Check if signal is an action signal */
				if(!(signalData.signal_flags & G_SIGNAL_ACTION))
				{
					g_warning(_("Action '%s' at object type %s is not an action signal."),
								action,
								G_OBJECT_TYPE_NAME(targetObject));
					continue;
				}

#if DEBUG
				/* In debug mode also check if signal has right signature
				 * to be able to handle this action properly.
				 */
				if(signalID)
				{
					GType				returnValueType=G_TYPE_BOOLEAN;
					GType				parameterTypes[]={ XFDASHBOARD_TYPE_FOCUSABLE, G_TYPE_STRING, CLUTTER_TYPE_EVENT };
					guint				parameterCount;
					guint				i;

					/* Check if signal wants the right type of return value */
					if(signalData.return_type!=returnValueType)
					{
						g_critical(_("Action '%s' at object type %s wants return value of type %s but expected is %s."),
									action,
									G_OBJECT_TYPE_NAME(targetObject),
									g_type_name(signalData.return_type),
									g_type_name(returnValueType));
					}

					/* Check if signals wants the right number and types of parameters */
					parameterCount=sizeof(parameterTypes)/sizeof(GType);
					if(signalData.n_params!=parameterCount)
					{
						g_critical(_("Action '%s' at object type %s wants %u parameters but expected are %u."),
									action,
									G_OBJECT_TYPE_NAME(targetObject),
									signalData.n_params,
									parameterCount);
					}

					for(i=0; i<(parameterCount<signalData.n_params ? parameterCount : signalData.n_params); i++)
					{
						if(signalData.param_types[i]!=parameterTypes[i])
						{
							g_critical(_("Action '%s' at object type %s wants type %s at parameter %u but type %s is expected."),
										action,
										G_OBJECT_TYPE_NAME(targetObject),
										g_type_name(signalData.param_types[i]),
										i+1,
										g_type_name(parameterTypes[i]));
						}
					}
				}
#endif

				/* Emit action signal at target */
				g_debug("Emitting action signal '%s' at focusable actor %s",
							action,
							G_OBJECT_TYPE_NAME(targetObject));
				g_signal_emit_by_name(targetObject, action, inFocusable, action, inEvent, &eventStatus);
				g_debug("Action signal '%s' was %s by focusable actor %s",
							action,
							eventStatus==CLUTTER_EVENT_STOP ? "handled" : "not handled",
							G_OBJECT_TYPE_NAME(targetObject));
			}

			/* Release allocated resources */
			g_slist_free_full(targetFocusables, g_object_unref);
		}
		g_object_unref(bindings);

		/* Release reference on ourselve and the focusable actor to took to keep them alive  */
		g_object_unref(inFocusable);
		g_object_unref(self);

		if(eventStatus==CLUTTER_EVENT_STOP) return(CLUTTER_EVENT_STOP);
	}

	/* Event was not handled so synthesize event to specified focusable actor */
	return(clutter_actor_event(CLUTTER_ACTOR(inFocusable), inEvent, FALSE));
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
/* 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);
}
Пример #21
0
/* 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);
}
Пример #22
0
/* Dragged actor moved */
static void _xfdashboard_drag_action_drag_motion(ClutterDragAction *inAction,
													ClutterActor *inActor,
													gfloat inDeltaX,
													gfloat inDeltaY)
{
	XfdashboardDragAction				*self;
	XfdashboardDragActionPrivate		*priv;
	ClutterDragActionClass				*dragActionClass;
	gfloat								stageX, stageY;
	XfdashboardDropAction				*dropTarget;
	gfloat								dropX, dropY;
	const ClutterEvent					*event;

	g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inAction));

	self=XFDASHBOARD_DRAG_ACTION(inAction);
	priv=self->priv;
	dragActionClass=CLUTTER_DRAG_ACTION_CLASS(xfdashboard_drag_action_parent_class);

	/* Call parent's class method */
	if(dragActionClass->drag_motion) dragActionClass->drag_motion(inAction, inActor, inDeltaX, inDeltaY);

	/* Remember motion delta coordinates */
	priv->lastDeltaX=inDeltaX;
	priv->lastDeltaY=inDeltaY;

	/* Get event coordinates relative to stage */
	clutter_drag_action_get_motion_coords(inAction, &stageX, &stageY);

	/* Find drop target at stage coordinate */
	dropTarget=_xfdashboard_drag_action_find_drop_traget_at_coord(self, stageX, stageY);

	/* If found drop target is not the same as the last one emit "drag-leave"
	 * signal at last drop target and "drag-enter" in new drop target
	 */
	if(priv->lastDropTarget!=dropTarget)
	{
		/* Emit "drag-leave" signal on last drop target */
		if(priv->lastDropTarget)
		{
			g_signal_emit_by_name(priv->lastDropTarget, "drag-leave", self, NULL);
			priv->lastDropTarget=NULL;
		}

		/* Check if new drop target is active and emit "drag-enter" signal */
		if(dropTarget)
		{
			ClutterActorMeta			*actorMeta=CLUTTER_ACTOR_META(dropTarget);
			ClutterActor				*dropActor=clutter_actor_meta_get_actor(actorMeta);

			if(clutter_actor_meta_get_enabled(actorMeta) &&
				clutter_actor_is_visible(dropActor) &&
				clutter_actor_get_reactive(dropActor))
			{
				g_signal_emit_by_name(dropTarget, "drag-enter", self, NULL);
				priv->lastDropTarget=dropTarget;
			}
		}
	}

	/* Transform event coordinates relative to last drop target which
	 * should be the drop target under pointer device if it is active
	 * and emit "drag-motion" signal
	 */
	if(priv->lastDropTarget)
	{
		dropX=dropY=0.0f;
		_xfdashboard_drag_action_transform_stage_point(priv->lastDropTarget,
														stageX, stageY,
														&dropX, &dropY);
		g_signal_emit_by_name(priv->lastDropTarget, "drag-motion", self, dropX, dropY, NULL);
	}

	/* We are derived from ClutterDragAction and this one disables stage motion
	 * so no "enter-event", "motion-event" and "leave-event" will be emitted while
	 * dragging. We need to do it on our own.
	 */
	event=clutter_get_current_event();
	if(event && clutter_event_type(event)==CLUTTER_MOTION)
	{
		GSList							*list, *next;
		ClutterStage					*stage;
		ClutterActor					*motionActor;
		gboolean						newMotionActor;
		ClutterActor					*actor;
		gfloat							x, y, w, h;
		gboolean						result;
		ClutterEvent					*actorEvent;

		/* Get stage where event happened */
		stage=clutter_event_get_stage(event);
		if(stage)
		{
			/* Get actor under pointer */
			newMotionActor=TRUE;
			motionActor=clutter_stage_get_actor_at_pos(stage,
														CLUTTER_PICK_REACTIVE,
														stageX, stageY);

			/* Iterate through list of crossed actors so far and check if pointer
			 * is still inside. If pointer is outside of an actor emit "leave-event".
			 * For each actor the pointer is still inside emit this "motion-event".
			 * Also check if actor under pointer is already is list to prevent
			 * "enter-event" to be emitted more than once.
			 */
			list=priv->lastMotionActors;
			while(list)
			{
				/* Get next entry now as this entry might get deleted */
				next=g_slist_next(list);

				/* Get actor from entry */
				actor=CLUTTER_ACTOR(list->data);

				/* Actor must be one same stage where event happened */
				if(clutter_actor_get_stage(actor)!=CLUTTER_ACTOR(stage)) continue;

				/* Get position and size of actor in stage coordinates */
				clutter_actor_get_transformed_position(actor, &x, &y);
				clutter_actor_get_transformed_size(actor, &w, &h);

				/* Check if pointer is still inside actor */
				if(stageX>=x && stageX<(x+w) &&
					stageY>=y && stageY<(y+h))
				{

					/* Check if actor is the "new" motion actor. If so set flag. */
					if(actor==motionActor) newMotionActor=FALSE;

					/* Emit "motion-event" */
					actorEvent=clutter_event_copy(event);
					actorEvent->motion.source=actor;

					g_signal_emit_by_name(actor, "motion-event", actorEvent, &result);

					clutter_event_free(actorEvent);
				}
					/* Pointer is not inside actor anymore so remove actor from list
					 * of last known "motion actors" and send "leave-event"
					 */
					else
					{
						/* Disconnect signal */
						g_signal_handlers_disconnect_by_func(actor, G_CALLBACK(_xfdashboard_drag_action_on_motion_actor_destroyed), self);

						/* Remove from list */
						priv->lastMotionActors=g_slist_remove_link(priv->lastMotionActors, list);
						g_slist_free_1(list);

						/* Create and emit "leave-event" */
						actorEvent=clutter_event_new(CLUTTER_LEAVE);
						actorEvent->crossing.time=event->motion.time;
						actorEvent->crossing.flags=event->motion.flags;
						actorEvent->crossing.stage=event->motion.stage;
						actorEvent->crossing.source=actor;

						actorEvent->crossing.x=event->motion.x;
						actorEvent->crossing.y=event->motion.y;
						actorEvent->crossing.device=event->motion.device;
						actorEvent->crossing.related=event->motion.source;

						g_signal_emit_by_name(actor, "leave-event", actorEvent, &result);

						clutter_event_free(actorEvent);
					}

				/* Proceed with next actor */
				list=next;
			}

			/* We have an actor under pointer and was not seen while iterating
			 * through list of all last known "motion actors" then add this actor
			 * to list and emit "enter-event" and also all parent actors because
			 * if pointer is inside their child then it is also inside them.
			 */
			if(motionActor && newMotionActor)
			{
				while(motionActor)
				{
					/* Avoid duplicates */
					if(!g_slist_find(priv->lastMotionActors, motionActor))
					{
						/* Add to list */
						priv->lastMotionActors=g_slist_append(priv->lastMotionActors, motionActor);

						/* Create and emit "enter-event" */
						actorEvent=clutter_event_new(CLUTTER_ENTER);
						actorEvent->crossing.time=event->motion.time;
						actorEvent->crossing.flags=event->motion.flags;
						actorEvent->crossing.stage=event->motion.stage;
						actorEvent->crossing.source=event->motion.source;

						actorEvent->crossing.x=event->motion.x;
						actorEvent->crossing.y=event->motion.y;
						actorEvent->crossing.device=event->motion.device;
						actorEvent->crossing.related=motionActor;

						g_signal_emit_by_name(motionActor, "enter-event", actorEvent, &result);

						clutter_event_free(actorEvent);

						/* To prevent emiting these motion events on actors being
						 * destroyed while drag is in progress we connect to 'destroy'
						 * signal of each "motion actor" added to list. The signal
						 * handler will be removed either on actor's destruction by
						 * signal handler's callback, when pointer leaves actor or on
						 * end of drag.
						 */
						g_signal_connect(motionActor, "destroy", G_CALLBACK(_xfdashboard_drag_action_on_motion_actor_destroyed), self);
					}

					/* Get parent */
					motionActor=clutter_actor_get_parent(motionActor);
				}
			}
		}
	}
}
Пример #23
0
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;
}
Пример #24
0
/**
 * 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 ();
}