/* Actor's reactive state changed */ static void _xfdashboard_actor_on_reactive_changed(GObject *inObject, GParamSpec *inSpec, gpointer inUserData) { XfdashboardActor *self; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inObject)); self=XFDASHBOARD_ACTOR(inObject); /* Add pseudo-class ':insensitive' if actor is now not reactive * and remove this pseudo-class if actor is now reactive. */ if(clutter_actor_get_reactive(CLUTTER_ACTOR(self))) { xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(self), "insensitive"); } else { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "insensitive"); } /* Invalide styling to get it recomputed */ _xfdashboard_actor_invalidate_recursive(CLUTTER_ACTOR(self)); }
static void bar_reactive_notify_cb (GObject *gobject, GParamSpec *arg1, gpointer user_data) { StScrollBar *bar = ST_SCROLL_BAR (gobject); clutter_actor_set_reactive (bar->priv->handle, clutter_actor_get_reactive (CLUTTER_ACTOR (bar))); }
static void st_scroll_bar_notify_reactive (StScrollBar *self) { StScrollBarPrivate *priv = self->priv; gboolean reactive = clutter_actor_get_reactive (CLUTTER_ACTOR (self)); clutter_actor_set_reactive (CLUTTER_ACTOR (priv->trough), reactive); clutter_actor_set_reactive (CLUTTER_ACTOR (priv->handle), reactive); }
/* Check if actor can get focus */ static gboolean _xfdashboard_actor_focusable_can_focus(XfdashboardFocusable *inFocusable) { XfdashboardActor *self; XfdashboardActorPrivate *priv; g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_ACTOR(inFocusable), FALSE); self=XFDASHBOARD_ACTOR(inFocusable); priv=self->priv; /* This actor can only be focused if it is mapped, visible and reactive */ if(priv->canFocus && clutter_actor_is_mapped(CLUTTER_ACTOR(self)) && clutter_actor_is_visible(CLUTTER_ACTOR(self)) && clutter_actor_get_reactive(CLUTTER_ACTOR(self))) { return(TRUE); } /* If we get here this actor does not fulfill the requirements to get focus */ return(FALSE); }
static gboolean on_stage_capture (ClutterActor *actor, ClutterEvent *event, DropContext *context) { MxDroppable *droppable; MxDraggable *draggable; ClutterActor *target; gfloat event_x, event_y; gboolean draggable_reactive; if (!(event->type == CLUTTER_MOTION || event->type == CLUTTER_BUTTON_RELEASE)) return FALSE; draggable = g_object_get_data (G_OBJECT (actor), "mx-drag-actor"); if (G_UNLIKELY (draggable == NULL)) return FALSE; /* get the actor currently under the cursor; we set the draggable * unreactive so that it does not intefere with get_actor_at_pos(); * the paint that get_actor_at_pos() performs is in the back buffer * so the hide/show cycle will not be visible on screen */ clutter_event_get_coords (event, &event_x, &event_y); draggable_reactive = clutter_actor_get_reactive (CLUTTER_ACTOR (draggable)); clutter_actor_set_reactive (CLUTTER_ACTOR (draggable), FALSE); target = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (actor), CLUTTER_PICK_REACTIVE, event_x, event_y); clutter_actor_set_reactive (CLUTTER_ACTOR (draggable), draggable_reactive); if (G_UNLIKELY (target == NULL)) return FALSE; droppable = NULL; if (!MX_IS_DROPPABLE (target)) { ClutterActor *parent = target; /* check if we're not on a child of a droppable */ while (parent != NULL) { parent = clutter_actor_get_parent (parent); if (parent != NULL && MX_IS_DROPPABLE (parent) && mx_droppable_accept_drop (MX_DROPPABLE (parent), draggable)) { droppable = MX_DROPPABLE (parent); break; } } } else { if (mx_droppable_accept_drop (MX_DROPPABLE (target), draggable)) droppable = MX_DROPPABLE (target); } /* we are on a new target, so emit ::over-out and unset the last target */ if (context->last_target && droppable != context->last_target) { g_signal_emit (context->last_target, droppable_signals[OVER_OUT], 0, draggable); context->last_target = NULL; return FALSE; } if (droppable == NULL) return FALSE; if (event->type == CLUTTER_MOTION) { if (context->last_target == NULL) { context->last_target = droppable; g_signal_emit (context->last_target, droppable_signals[OVER_IN], 0, draggable); } } else if (event->type == CLUTTER_BUTTON_RELEASE && context->last_target) { gfloat drop_x, drop_y; gboolean res; ClutterActor *last_target = CLUTTER_ACTOR (context->last_target); drop_x = drop_y = 0; res = clutter_actor_transform_stage_point (last_target, event_x, event_y, &drop_x, &drop_y); if (!res) return FALSE; g_signal_emit (context->last_target, droppable_signals[DROP], 0, draggable, drop_x, drop_y, event->button.button, event->button.modifier_state); context->last_target = NULL; } return FALSE; }
int main (int argc, char **argv) { const ClutterColor grey = { 0x40, 0x40, 0x40, 0xff }; ClutterActor *stage, *tile, *tile2, *image, *image2, *dialog, *tiles; MxApplication *app; ClutterConstraint *constraint; mex_init (&argc, &argv); app = mx_application_new (&argc, &argv, "mex-tile-controls-test", 0); mex_style_load_default (); stage = clutter_stage_get_default (); clutter_stage_set_color (CLUTTER_STAGE (stage), &grey); clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); image = mx_image_new (); mx_image_set_from_file (MX_IMAGE (image), "/home/michael/dev/mex-info-bar/graphic-mapButtons.png", NULL); image2 = mx_image_new (); mx_image_set_from_file (MX_IMAGE (image2), "/home/michael/dev/mex-info-bar/graphic-network.png", NULL); tile = mex_tile_new (); mex_tile_set_label (tile, "Remote mapping"); mex_tile_set_important (tile, TRUE); ClutterActor *button; button = mx_button_new (); mx_bin_set_child (MX_BIN (tile), button); mx_bin_set_child (MX_BIN (button), image); tile2 = mex_tile_new (); mex_tile_set_label (tile2, "Network"); mex_tile_set_important (tile2, TRUE); ClutterActor *button2; button2 = mx_button_new (); mx_bin_set_child (MX_BIN (tile2), button2); mx_bin_set_child (MX_BIN (button2), image2); tiles = mx_box_layout_new (); mx_box_layout_set_spacing (tiles, 10); mx_box_layout_set_orientation (tiles, MX_ORIENTATION_HORIZONTAL); mx_box_layout_add_actor (tiles, tile, 0); mx_box_layout_add_actor (tiles, tile2, 1); g_print (clutter_actor_get_reactive (tile) ? "reactive" : "notreactive"); dialog = mx_dialog_new (); mx_dialog_set_transient_parent (dialog, stage); g_signal_connect (button2, "clicked", G_CALLBACK (focus_in_cb), NULL); g_signal_connect (button, "clicked", G_CALLBACK (focus_in_cb), NULL); clutter_container_add_actor (CLUTTER_CONTAINER (dialog), tiles); clutter_actor_show (dialog); clutter_actor_set_size (stage, 1024, 768); clutter_actor_show (stage); clutter_main (); return 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); } } } } }