G_MODULE_EXPORT int test_drag_main (int argc, char *argv[]) { ClutterActor *stage, *handle; ClutterAction *action; GError *error; error = NULL; clutter_init_with_args (&argc, &argv, "test-drag", entries, NULL, &error); if (error != NULL) { g_print ("Unable to run test-drag: %s\n", error->message); g_error_free (error); return EXIT_FAILURE; } stage = clutter_stage_new (); clutter_stage_set_title (CLUTTER_STAGE (stage), "Drag Test"); clutter_actor_set_size (stage, 800, 600); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); handle = clutter_rectangle_new (); clutter_rectangle_set_color (CLUTTER_RECTANGLE (handle), CLUTTER_COLOR_SkyBlue); clutter_actor_set_size (handle, 128, 128); clutter_actor_set_position (handle, (800 - 128) / 2, (600 - 128) / 2); clutter_actor_set_reactive (handle, TRUE); clutter_container_add_actor (CLUTTER_CONTAINER (stage), handle); g_signal_connect (handle, "enter-event", G_CALLBACK (on_enter), NULL); g_signal_connect (handle, "leave-event", G_CALLBACK (on_leave), NULL); action = clutter_drag_action_new (); clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action), x_drag_threshold, y_drag_threshold); clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action), get_drag_axis (drag_axis)); g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL); g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL); clutter_actor_add_action (handle, action); clutter_actor_add_effect_with_name (handle, "disable", clutter_desaturate_effect_new (0.0)); clutter_actor_add_effect_with_name (handle, "curl", clutter_page_turn_effect_new (0.0, 45.0, 12.0)); clutter_actor_show (stage); clutter_main (); return EXIT_SUCCESS; }
static void clutter_drag_action_get_property (GObject *gobject, guint prop_id, GValue *value, GParamSpec *pspec) { ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (gobject)->priv; switch (prop_id) { case PROP_X_DRAG_THRESHOLD: g_value_set_uint (value, priv->x_drag_threshold); break; case PROP_Y_DRAG_THRESHOLD: g_value_set_uint (value, priv->y_drag_threshold); break; case PROP_DRAG_HANDLE: g_value_set_object (value, priv->drag_handle); break; case PROP_DRAG_AXIS: g_value_set_enum (value, priv->drag_axis); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); } }
static void clutter_drag_action_dispose (GObject *gobject) { ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (gobject)->priv; if (priv->capture_id != 0) { if (priv->stage != NULL) g_signal_handler_disconnect (priv->stage, priv->capture_id); priv->capture_id = 0; priv->stage = NULL; } if (priv->button_press_id != 0) { ClutterActor *actor; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)); g_signal_handler_disconnect (actor, priv->button_press_id); priv->button_press_id = 0; } G_OBJECT_CLASS (clutter_drag_action_parent_class)->dispose (gobject); }
static void clutter_drag_action_set_actor (ClutterActorMeta *meta, ClutterActor *actor) { ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (meta)->priv; if (priv->button_press_id != 0) { ClutterActor *old_actor; old_actor = clutter_actor_meta_get_actor (meta); g_signal_handler_disconnect (old_actor, priv->button_press_id); if (priv->capture_id != 0) g_signal_handler_disconnect (old_actor, priv->capture_id); priv->button_press_id = 0; priv->capture_id = 0; priv->stage = NULL; } if (actor != NULL) priv->button_press_id = g_signal_connect (actor, "button-press-event", G_CALLBACK (on_button_press), meta); CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor); }
/* Drag handle has changed so unset styles on old handle and set style on new one */ static void _xfdashboard_drag_action_on_drag_handle_changed(XfdashboardDragAction *self, GParamSpec *inSpec, gpointer inUserData) { XfdashboardDragActionPrivate *priv; gchar *styleClass; g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(self)); priv=self->priv; /* Unset styles on current drag handle */ if(priv->dragHandle && XFDASHBOARD_IS_ACTOR(priv->dragHandle)) { /* Unset style */ 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"); /* Forget drag handle */ priv->dragHandle=NULL; } /* Remember new drag handle and set styles */ priv->dragHandle=clutter_drag_action_get_drag_handle(CLUTTER_DRAG_ACTION(self)); if(priv->dragHandle && XFDASHBOARD_IS_ACTOR(priv->dragHandle)) { /* Set style */ 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"); } }
static void clutter_widget_init ( ClutterWidget *_self ) { ClutterWidgetPrivate *priv; ClutterAction *action; ClutterState *state; _self->priv = priv = CLUTTER_WIDGET_GET_PRIVATE (_self); priv->borderColor = *CLUTTER_COLOR_LightGray; clutter_actor_set_reactive ( CLUTTER_ACTOR(_self), TRUE ); // TODO: only in drag-bar { action = clutter_drag_action_new (); clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action), 0, 0); clutter_drag_action_set_drag_axis ( CLUTTER_DRAG_ACTION (action), CLUTTER_DRAG_X_AXIS&CLUTTER_DRAG_Y_AXIS ); g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL); g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL); clutter_actor_add_action (CLUTTER_ACTOR(_self), action); clutter_actor_add_effect_with_name (CLUTTER_ACTOR(_self), "disable", clutter_desaturate_effect_new (0.0)); // } TODO end // init state machine state = clutter_state_new (); g_object_set_data_full ( G_OBJECT (_self), "hover-state-machine", state, g_object_unref ); g_signal_connect ( _self, "enter-event", G_CALLBACK (on_enter), state ); g_signal_connect ( _self, "leave-event", G_CALLBACK (on_leave), state ); clutter_state_set ( state, NULL, "normal", _self, "border-color", CLUTTER_LINEAR, CLUTTER_COLOR_DarkGray, NULL ); clutter_state_set ( state, NULL, "hover", _self, "border-color", CLUTTER_LINEAR, CLUTTER_COLOR_LightSkyBlue, NULL ); clutter_state_set_duration ( state, NULL, NULL, 200 ); // set init state clutter_state_set_state (state, "normal"); }
/* The dragged actor is going to be destroy. Cancel drag action */ static void _xfdashboard_drag_action_on_dragged_actor_destroyed(XfdashboardDragAction *self, gpointer inUserData) { XfdashboardDragActionPrivate *priv; gfloat x, y; g_return_if_fail(XFDASHBOARD_IS_DRAG_ACTION(self)); priv=self->priv; x=y=0.0f; /* Remove signal from dragged actor although it is going to be destroyed now */ g_signal_handler_disconnect(priv->actor, priv->actorDestroySignalID); priv->actorDestroySignalID=0; /* Mark drag action being cancelled */ priv->dragCancelled=TRUE; /* Emit "drag-end" signal */ clutter_drag_action_get_motion_coords(CLUTTER_DRAG_ACTION(self), &x, &y); g_signal_emit_by_name(self, "drag-end", priv->actor, x, y, 0, NULL); }
/* 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); } }