/* Sort drop action targets */ static gint _xfdashboard_drag_action_sort_targets_callback(gconstpointer inLeft, gconstpointer inRight) { ClutterActor *actor1, *actor2; gfloat depth1, depth2; gfloat x1, y1, w1, h1; gfloat x2, y2, w2, h2; ClutterActorBox *box1, *box2; gint numberPoint1, numberPoint2; g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(inLeft) && XFDASHBOARD_IS_DROP_ACTION(inRight), 0); actor1=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(inLeft)); actor2=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(inRight)); /* Return -1 if actor in inLeft should be inserted before actor in inRight * and return 1 if otherwise. If both actors can be handled equal then * return 0. But how to decide? * The actor with higher z-depth should be inserted before. If both actors * have equal z-depth then the actor with the most edge points within the * other actor (overlap) should be inserted before. Edge points are: * [left,top], [right,top], [left,bottom] and [right, bottom]. */ depth1=clutter_actor_get_z_position(actor1); depth2=clutter_actor_get_z_position(actor2); if(depth1>depth2) return(-1); else if(depth1<depth2) return(1); clutter_actor_get_transformed_position(actor1, &x1, &y1); clutter_actor_get_transformed_size(actor1, &w1, &h1); box1=clutter_actor_box_new(x1, y1, x1+w1, y1+h1); clutter_actor_get_transformed_position(actor2, &x2, &y2); clutter_actor_get_transformed_size(actor2, &w2, &h2); box2=clutter_actor_box_new(x2, y2, x2+w2, y2+h2); numberPoint1 =(clutter_actor_box_contains(box1, x2, y2) ? 1 : 0); numberPoint1+=(clutter_actor_box_contains(box1, x2+w2, y2) ? 1 : 0); numberPoint1+=(clutter_actor_box_contains(box1, x2, y2+h2) ? 1 : 0); numberPoint1+=(clutter_actor_box_contains(box1, x2+w2, y2+h2) ? 1 : 0); numberPoint2 =(clutter_actor_box_contains(box2, x1, y1) ? 1 : 0); numberPoint2+=(clutter_actor_box_contains(box2, x1+w1, y1) ? 1 : 0); numberPoint2+=(clutter_actor_box_contains(box2, x1, y1+h1) ? 1 : 0); numberPoint2+=(clutter_actor_box_contains(box2, x1+w1, y1+h1) ? 1 : 0); clutter_actor_box_free(box1); clutter_actor_box_free(box2); /* Return result */ if(numberPoint1>numberPoint2) return(1); else if(numberPoint2>numberPoint1) return(-1); return(0); }
/* Drag of an actor to this view as drop target begins */ static gboolean _xfdashboard_workspace_selector_on_drop_begin(XfdashboardLiveWorkspace *self, XfdashboardDragAction *inDragAction, gpointer inUserData) { ClutterActor *dragSource; ClutterActor *draggedActor; gboolean canHandle; g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inDragAction), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(inUserData), FALSE); canHandle=FALSE; /* Get source where dragging started and actor being dragged */ dragSource=xfdashboard_drag_action_get_source(inDragAction); draggedActor=xfdashboard_drag_action_get_actor(inDragAction); /* Check if we can handle dragged actor from given source */ if(XFDASHBOARD_IS_WINDOWS_VIEW(dragSource) && XFDASHBOARD_IS_LIVE_WINDOW(draggedActor)) { canHandle=TRUE; } if(XFDASHBOARD_IS_APPLICATION_BUTTON(draggedActor)) { canHandle=TRUE; } /* Return TRUE if we can handle dragged actor in this drop target * otherwise FALSE */ return(canHandle); }
/* Register a new drop target */ static void _xfdashboard_drop_action_register_target(XfdashboardDropAction *self) { g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(self)); /* Check if target is already registered */ if(g_slist_find(_xfdashboard_drop_action_targets, self)) { g_warning(_("Target %s is already registered"), G_OBJECT_TYPE_NAME(self)); return; } /* Add object to list of dropable targets */ _xfdashboard_drop_action_targets=g_slist_prepend(_xfdashboard_drop_action_targets, self); }
/* 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); }
/* Default signal handler for "drag-leave" */ static void _xfdashboard_drop_action_class_real_drag_leave(XfdashboardDropAction *self, XfdashboardDragAction *inDragAction) { XfdashboardDropActionPrivate *priv; g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(self)); priv=self->priv; /* Unset style */ if(priv->actor && XFDASHBOARD_IS_ACTOR(priv->actor)) { xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "drop-target"); } }
/* Unregister a drop target */ static void _xfdashboard_drop_action_unregister_target(XfdashboardDropAction *self) { XfdashboardDropActionPrivate *priv; g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(self)); priv=self->priv; /* Unset style */ if(priv->actor && XFDASHBOARD_IS_ACTOR(priv->actor)) { xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "drop-target"); } /* Remove target from list of dropable targets */ _xfdashboard_drop_action_targets=g_slist_remove(_xfdashboard_drop_action_targets, self); }
/* Dragged actor was dropped on this drop target */ static void _xfdashboard_workspace_selector_on_drop_drop(XfdashboardLiveWorkspace *self, XfdashboardDragAction *inDragAction, gfloat inX, gfloat inY, gpointer inUserData) { ClutterActor *draggedActor; g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(inDragAction)); g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(inUserData)); /* Get dragged actor */ draggedActor=xfdashboard_drag_action_get_actor(inDragAction); /* Check if dragged actor is a window so move window to workspace */ if(XFDASHBOARD_IS_LIVE_WINDOW(draggedActor)) { XfdashboardWindowTrackerWindow *window; /* Get window */ window=xfdashboard_live_window_get_window(XFDASHBOARD_LIVE_WINDOW(draggedActor)); g_return_if_fail(window); /* Move window to workspace */ xfdashboard_window_tracker_window_move_to_workspace(window, xfdashboard_live_workspace_get_workspace(self)); } /* Check if dragged actor is a application button so launch app at workspace */ if(XFDASHBOARD_IS_APPLICATION_BUTTON(draggedActor)) { XfdashboardApplicationButton *button; GAppLaunchContext *context; /* Get application button */ button=XFDASHBOARD_APPLICATION_BUTTON(draggedActor); /* Launch application at workspace where application button was dropped */ context=xfdashboard_create_app_context(xfdashboard_live_workspace_get_workspace(self)); xfdashboard_application_button_execute(button, context); g_object_unref(context); } }
/* Transform stage coordinates to drop action's target actor coordinates */ static void _xfdashboard_drag_action_transform_stage_point(XfdashboardDropAction *inDropTarget, gfloat inStageX, gfloat inStageY, gfloat *outActorX, gfloat *outActorY) { ClutterActor *actor; gfloat x, y; g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(inDropTarget)); /* Get target actor of drop action and transform coordinates */ actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(inDropTarget)); clutter_actor_transform_stage_point(actor, inStageX, inStageY, &x, &y); /* Set return values */ if(outActorX) *outActorX=x; if(outActorY) *outActorY=y; }
/* Default signal handler for "begin" */ static gboolean _xfdashboard_drop_action_class_real_begin(XfdashboardDropAction *self, XfdashboardDragAction *inDragAction) { XfdashboardDropActionPrivate *priv; ClutterActorMeta *actorMeta; g_return_val_if_fail(XFDASHBOARD_IS_DROP_ACTION(self), FALSE); g_return_val_if_fail(self->priv->actor, FALSE); priv=self->priv; actorMeta=CLUTTER_ACTOR_META(self); /* Return TRUE means we can handle dragged actor on this drop target. This is only * possible if drop target is active, visible and reactive. Otherwise we have to * return FALSE to indicate that we cannot handle dragged actor. */ return(clutter_actor_meta_get_enabled(actorMeta) && CLUTTER_ACTOR_IS_VISIBLE(priv->actor) && CLUTTER_ACTOR_IS_REACTIVE(priv->actor)); }
/* Target actor will be destroyed */ static void _xfdashboard_drop_action_on_target_actor_destroy(XfdashboardDropAction *self, ClutterActor *inTarget) { XfdashboardDropActionPrivate *priv; g_return_if_fail(XFDASHBOARD_IS_DROP_ACTION(self)); g_return_if_fail(CLUTTER_IS_ACTOR(inTarget)); priv=self->priv; /* Check that destroyed actor matches drop action's target actor */ g_return_if_fail(inTarget==priv->actor); /* Disconnect signals */ if(priv->destroySignalID) g_signal_handler_disconnect(priv->actor, priv->destroySignalID); /* Unregister drop target */ _xfdashboard_drop_action_unregister_target(self); priv->destroySignalID=0; priv->actor=NULL; }