Пример #1
0
/* Find drop target at position */
static XfdashboardDropAction* _xfdashboard_drag_action_find_drop_traget_at_coord(XfdashboardDragAction *self,
																					gfloat inStageX,
																					gfloat inStageY)
{
	XfdashboardDragActionPrivate	*priv;
	GSList							*list;

	g_return_val_if_fail(XFDASHBOARD_IS_DRAG_ACTION(self), NULL);

	priv=self->priv;

	/* Iterate through list and return first drop target in list
	 * where coordinates fit in
	 */
	for(list=priv->targets; list; list=g_slist_next(list))
	{
		ClutterActorMeta			*actorMeta=CLUTTER_ACTOR_META(list->data);
		ClutterActor				*actor=clutter_actor_meta_get_actor(actorMeta);
		gfloat						x, y, w, h;

		/* 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);

		/* If given stage coordinates fit in actor we found it */
		if(inStageX>=x && inStageX<(x+w) &&
			inStageY>=y && inStageY<(y+h))
		{
			return(XFDASHBOARD_DROP_ACTION(actorMeta));
		}
	}

	/* If we get here no drop target was found */
	return(NULL);
}
Пример #2
0
/* Called when attaching and detaching a ClutterActorMeta instance to a ClutterActor */
static void _xfdashboard_drop_action_set_actor(ClutterActorMeta *inActorMeta, ClutterActor *inActor)
{
	XfdashboardDropAction			*self;
	XfdashboardDropActionPrivate	*priv;

	g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(inActorMeta));
	g_return_if_fail(inActor==NULL || CLUTTER_IS_ACTOR(inActor));

	self=XFDASHBOARD_DROP_ACTION(inActorMeta);
	priv=self->priv;

	/* Unregister current drop target */
	if(priv->actor)
	{
		/* Disconnect signals */
		if(priv->destroySignalID) g_signal_handler_disconnect(priv->actor, priv->destroySignalID);

		/* Unset style */
		if(XFDASHBOARD_IS_ACTOR(priv->actor))
		{
			xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "drop-target");
		}

		/* Unregister drop target */
		_xfdashboard_drop_action_unregister_target(self);

		priv->destroySignalID=0;
		priv->actor=NULL;
	}

	/* Register new drop target */
	if(inActor)
	{
		priv->actor=inActor;

		/* Register drop target */
		_xfdashboard_drop_action_register_target(self);

		/* Connect signals */
		priv->destroySignalID=g_signal_connect_swapped(priv->actor,
														"destroy",
														G_CALLBACK(_xfdashboard_drop_action_on_target_actor_destroy),
														self);
	}

	/* Call parent's class method */
	CLUTTER_ACTOR_META_CLASS(xfdashboard_drop_action_parent_class)->set_actor(inActorMeta, inActor);
}
Пример #3
0
/* Dragging of actor ended */
static void _xfdashboard_drag_action_drag_end(ClutterDragAction *inAction,
												ClutterActor *inActor,
												gfloat inStageX,
												gfloat inStageY,
												ClutterModifierType inModifiers)
{
	XfdashboardDragAction				*self;
	XfdashboardDragActionPrivate		*priv;
	ClutterDragActionClass				*dragActionClass;
	GSList								*list;
	XfdashboardDropAction				*dropTarget;
	gfloat								dropX, dropY;
	gboolean							canDrop;

	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);
	canDrop=FALSE;
	dropTarget=NULL;

	/* Hold a reference on ourselve as ClutterAction as the actor where we are bound to
	 * may be destroyed in this function. We need to keep alive this action until
	 * function ends.
	 */
	g_object_ref(self);

	/* Unset styles */
	if(priv->source && XFDASHBOARD_IS_ACTOR(priv->source))
	{
		xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->source), "drag-source");
	}

	if(XFDASHBOARD_IS_ACTOR(priv->actor))
	{
		xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "dragged");
	}

	if(priv->dragHandle &&
		XFDASHBOARD_IS_ACTOR(priv->dragHandle))
	{
		gchar							*styleClass;

		if(priv->source)
		{
			styleClass=g_strdup_printf("drag-source-%s", G_OBJECT_TYPE_NAME(priv->source));
			xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass);
			g_free(styleClass);
		}

		styleClass=g_strdup_printf("drag-actor-%s", G_OBJECT_TYPE_NAME(priv->actor));
		xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass);
		g_free(styleClass);

		xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->dragHandle), "drag-handle");

		priv->dragHandle=NULL;
	}

	if(priv->dragHandleChangedID)
	{
		g_signal_handler_disconnect(self, priv->dragHandleChangedID);
		priv->dragHandleChangedID=0;
	}

	/* Remove 'destroy' signal on dragged actor */
	if(priv->actorDestroySignalID)
	{
		g_signal_handler_disconnect(priv->actor, priv->actorDestroySignalID);
		priv->actorDestroySignalID=0;
	}

	/* Remove our listerners for allocation changes */
	for(list=priv->targets; list; list=g_slist_next(list))
	{
		XfdashboardDropAction			*target=XFDASHBOARD_DROP_ACTION(list->data);
		ClutterActorMeta				*actorMeta=CLUTTER_ACTOR_META(target);
		ClutterActor					*actor=clutter_actor_meta_get_actor(actorMeta);

		g_signal_handlers_disconnect_by_func(actor, G_CALLBACK(_xfdashboard_drag_on_drop_target_allocation_changed), self);
	}

	/* Find drop target at stage coordinate if dragged actor was not destroyed */
	if(!priv->dragCancelled) dropTarget=_xfdashboard_drag_action_find_drop_traget_at_coord(self, inStageX, inStageY);

	/* If drop target was found check if we are allowed to drop on it. */
	if(dropTarget)
	{
		/* Transform event coordinates relative to drop target */
		_xfdashboard_drag_action_transform_stage_point(dropTarget,
														inStageX, inStageY,
														&dropX, &dropY);

		/* Ask drop target if we are allowed to drop dragged actor on it */
		g_signal_emit_by_name(dropTarget, "can-drop", self, dropX, dropY, &canDrop);
	}

	/* If we cannot drop the draggged actor emit "drag-cancel" on dragged actor */
	if(!canDrop) g_signal_emit_by_name(inAction, "drag-cancel", priv->actor, inStageX, inStageY, NULL);

	/* Iterate through list of drop targets to emit the "end" signal to the ones
	* on which the dragged actor will not be drop (either they were not the target
	* or it did not allow to drop on it). The real drop target gets the "drop"
	* signal.
	*/
	for(list=priv->targets; list; list=g_slist_next(list))
	{
		XfdashboardDropAction			*target=XFDASHBOARD_DROP_ACTION(list->data);

		if(canDrop && target && target==dropTarget)
		{
			g_signal_emit_by_name(dropTarget, "drop", self, dropX, dropY, NULL);
		}
			else
			{
				g_signal_emit_by_name(target, "end", self, NULL);
			}
	}

	/* Call parent's class method at last */
	if(dragActionClass->drag_end) dragActionClass->drag_end(inAction, inActor, inStageX, inStageY, inModifiers);

	/* Forget dragged actor as dragging has ended now */
	priv->actor=NULL;

	/* Free list of drop targets and unref each drop target */
	if(priv->targets) g_slist_free_full(priv->targets, g_object_unref);
	priv->targets=NULL;

	/* Free list of actor we crossed by motion */
	if(priv->lastMotionActors)
	{
		g_slist_foreach(priv->lastMotionActors, _xfdashboard_drag_action_on_motion_actor_destroyed, self);
		if(priv->lastMotionActors) g_slist_free(priv->lastMotionActors);
		priv->lastMotionActors=NULL;
	}

	/* Reset variables */
	priv->lastDropTarget=NULL;

	/* Release the reference we took at function beginning */
	g_object_unref(self);
}
Пример #4
0
/* Dragging of actor begins */
static void _xfdashboard_drag_action_drag_begin(ClutterDragAction *inAction,
												ClutterActor *inActor,
												gfloat inStageX,
												gfloat inStageY,
												ClutterModifierType inModifiers)
{
	XfdashboardDragAction				*self;
	XfdashboardDragActionPrivate		*priv;
	ClutterDragActionClass				*dragActionClass;
	GSList								*list;

	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_begin) dragActionClass->drag_begin(inAction, inActor, inStageX, inStageY, inModifiers);

	/* Remember dragged actor while dragging and listen to possible 'destroy' signal emissions */
	priv->actor=inActor;
	priv->actorDestroySignalID=g_signal_connect_swapped(priv->actor, "destroy", G_CALLBACK(_xfdashboard_drag_action_on_dragged_actor_destroyed), self);

	/* Get list of drop targets. It is a new list with all current
	 * drop targets already reffed. So the drop targets will be valid
	 * while dragging
	 */
	priv->targets=xfdashboard_drop_action_get_targets();

	/* Emit "begin" signal on all drop targets to determine if they
	 * can handle dragged actor and to prepare them for dragging.
	 * All targets returning TRUE (and therefore telling us they
	 * can handle dragged actor and are prepared for drag'n'drop)
	 * will be sorted.
	 */
	list=priv->targets;
	while(list)
	{
		XfdashboardDropAction			*dropTarget=XFDASHBOARD_DROP_ACTION(list->data);
		gboolean						canHandle=FALSE;

		g_signal_emit_by_name(dropTarget, "begin", self, &canHandle);
		if(!canHandle)
		{
			GSList						*next;

			/* Drop target cannot handle dragged actor so unref it and
			 * remove it from list of drop targets
			 */
			next=g_slist_next(list);
			priv->targets=g_slist_remove_link(priv->targets, list);
			g_object_unref(list->data);
			g_slist_free_1(list);
			list=next;
		}
			else list=g_slist_next(list);
	}
	_xfdashboard_drag_action_sort_targets(self);

	/* We should listen to allocation changes for each actor which
	 * is an active drop target.
	 */
	for(list=priv->targets; list; list=g_slist_next(list))
	{
		XfdashboardDropAction			*dropTarget=XFDASHBOARD_DROP_ACTION(list->data);
		ClutterActorMeta				*actorMeta=CLUTTER_ACTOR_META(dropTarget);
		ClutterActor					*actor=clutter_actor_meta_get_actor(actorMeta);

		g_signal_connect_swapped(actor, "allocation-changed", G_CALLBACK(_xfdashboard_drag_on_drop_target_allocation_changed), self);
	}

	/* Setup for dragging */
	priv->dragCancelled=FALSE;
	priv->lastDropTarget=NULL;
	priv->lastMotionActors=NULL;

	/* Set styles */
	if(priv->source && XFDASHBOARD_IS_ACTOR(priv->source))
	{
		xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->source), "drag-source");
	}

	if(XFDASHBOARD_IS_ACTOR(priv->actor))
	{
		xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "dragged");
	}

	priv->dragHandle=clutter_drag_action_get_drag_handle(CLUTTER_DRAG_ACTION(self));
	if(priv->dragHandle &&
		XFDASHBOARD_IS_ACTOR(priv->dragHandle))
	{
		gchar							*styleClass;

		if(priv->source)
		{
			styleClass=g_strdup_printf("drag-source-%s", G_OBJECT_TYPE_NAME(priv->source));
			xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass);
			g_free(styleClass);
		}

		styleClass=g_strdup_printf("drag-actor-%s", G_OBJECT_TYPE_NAME(priv->actor));
		xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->dragHandle), styleClass);
		g_free(styleClass);

		xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->dragHandle), "drag-handle");

		/* Get notified if drag handle changes */
		priv->dragHandleChangedID=g_signal_connect(self, "notify::drag-handle", G_CALLBACK(_xfdashboard_drag_action_on_drag_handle_changed), NULL);
	}
}