/* 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)); }
/* The active workspace has changed */ static void _xfdashboard_workspace_selector_on_active_workspace_changed(XfdashboardWorkspaceSelector *self, XfdashboardWindowTrackerWorkspace *inPrevWorkspace, gpointer inUserData) { XfdashboardWorkspaceSelectorPrivate *priv; XfdashboardLiveWorkspace *liveWorkspace; XfdashboardWindowTrackerWorkspace *workspace; g_return_if_fail(XFDASHBOARD_IS_WORKSPACE_SELECTOR(self)); priv=self->priv; /* Unmark previous workspace */ if(inPrevWorkspace) { liveWorkspace=_xfdashboard_workspace_selector_find_actor_for_workspace(self, inPrevWorkspace); if(liveWorkspace) xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(liveWorkspace), "active"); priv->activeWorkspace=NULL; } /* Mark new active workspace */ workspace=xfdashboard_window_tracker_get_active_workspace(priv->windowTracker); if(workspace) { priv->activeWorkspace=workspace; liveWorkspace=_xfdashboard_workspace_selector_find_actor_for_workspace(self, priv->activeWorkspace); if(liveWorkspace) xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(liveWorkspace), "active"); } }
/* Set press state */ static void _xfdashboard_click_action_set_pressed(XfdashboardClickAction *self, gboolean isPressed) { XfdashboardClickActionPrivate *priv; ClutterActor *actor; g_return_if_fail(XFDASHBOARD_IS_CLICK_ACTION(self)); priv=self->priv; /* Set value if changed */ isPressed=!!isPressed; if(priv->isPressed!=isPressed) { /* Set value */ priv->isPressed=isPressed; /* Style state */ actor=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self)); if(XFDASHBOARD_IS_ACTOR(actor)) { if(priv->isPressed) xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(actor), "pressed"); else xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(actor), "pressed"); } /* Notify about property change */ g_object_notify_by_pspec(G_OBJECT(self), XfdashboardClickActionProperties[PROP_PRESSED]); } }
/* 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"); } }
/* Call virtual function "set_focus" */ void xfdashboard_focusable_set_focus(XfdashboardFocusable *self) { XfdashboardFocusableInterface *iface; ClutterActor *selection; g_return_if_fail(XFDASHBOARD_IS_FOCUSABLE(self)); iface=XFDASHBOARD_FOCUSABLE_GET_IFACE(self); /* Call virtual function */ if(iface->set_focus) { iface->set_focus(self); } /* Style newly focused actor */ if(XFDASHBOARD_IS_STYLABLE(self)) { xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(self), "focus"); } /* If actor supports selection get current selection and style it */ if(xfdashboard_focusable_supports_selection(self)) { /* Get current selection. If no selection is available then select first item. */ selection=xfdashboard_focusable_get_selection(self); if(!selection) { selection=xfdashboard_focusable_find_selection(self, NULL, XFDASHBOARD_SELECTION_TARGET_FIRST); if(selection) xfdashboard_focusable_set_selection(self, selection); } /* Style selection if available */ if(selection && XFDASHBOARD_IS_STYLABLE(selection)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(selection), "selected"); } g_debug("Set selection to %s for focused actor %s", G_OBJECT_TYPE_NAME(self), selection ? G_OBJECT_TYPE_NAME(selection) : "<nil>"); } /* Emit signal */ g_signal_emit(self, XfdashboardFocusableSignals[SIGNAL_FOCUS_GAINED], 0, self); g_debug("Emitted signal 'focus-gained' for focused actor %s", G_OBJECT_TYPE_NAME(self)); }
/* Default signal handler for "drag-enter" */ static void _xfdashboard_drop_action_class_real_drag_enter(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_add_pseudo_class(XFDASHBOARD_STYLABLE(priv->actor), "drop-target"); } }
/* Pointer entered actor */ static gboolean _xfdashboard_actor_enter_event(ClutterActor *inActor, ClutterCrossingEvent *inEvent) { XfdashboardActor *self; ClutterActorClass *parentClass; g_return_val_if_fail(XFDASHBOARD_IS_ACTOR(inActor), CLUTTER_EVENT_PROPAGATE); self=XFDASHBOARD_ACTOR(inActor); /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->enter_event) { parentClass->enter_event(inActor, inEvent); } /* Add pseudo-class ":hover" because pointer entered actor */ xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "hover"); return(CLUTTER_EVENT_PROPAGATE); }
void xfdashboard_text_box_set_editable(XfdashboardTextBox *self, gboolean isEditable) { XfdashboardTextBoxPrivate *priv; const gchar *text; g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self)); priv=self->priv; /* Set value if changed */ if(priv->isEditable!=isEditable) { priv->isEditable=isEditable; if(priv->isEditable) xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "editable"); else xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(self), "editable"); /* Set up actors */ clutter_text_set_selectable(CLUTTER_TEXT(priv->actorTextBox), priv->isEditable); clutter_text_set_editable(CLUTTER_TEXT(priv->actorTextBox), priv->isEditable); text=clutter_text_get_text(CLUTTER_TEXT(priv->actorTextBox)); if((text==NULL || *text==0) && priv->isEditable) { clutter_actor_show(priv->actorHintLabel); } else { clutter_actor_hide(priv->actorHintLabel); } clutter_actor_queue_relayout(CLUTTER_ACTOR(self)); /* Notify about property change */ g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_EDITABLE]); } }
/* Actor is shown */ static void _xfdashboard_actor_show(ClutterActor *inActor) { XfdashboardActor *self; ClutterActorClass *parentClass; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inActor)); self=XFDASHBOARD_ACTOR(inActor); /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->show) { parentClass->show(inActor); } /* If actor is visible now check if pointer is inside this actor * then add pseudo-class ":hover" to it */ if(clutter_actor_has_pointer(inActor)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "hover"); } }
/* Call virtual function "set_selection" */ gboolean xfdashboard_focusable_set_selection(XfdashboardFocusable *self, ClutterActor *inSelection) { XfdashboardFocusableInterface *iface; ClutterActor *oldSelection; gboolean success; g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(self), FALSE); g_return_val_if_fail(!inSelection || CLUTTER_IS_ACTOR(inSelection), FALSE); iface=XFDASHBOARD_FOCUSABLE_GET_IFACE(self); /* If this focusable actor does not support selection we should ask for * the current selection and avoid the warning being printed if this * virtual function was not overridden. */ if(!xfdashboard_focusable_supports_selection(self)) return(FALSE); /* First get current selection */ oldSelection=xfdashboard_focusable_get_selection(self); /* Do nothing if new selection is the same as the current one */ if(inSelection==oldSelection) return(TRUE); /* Call virtual function */ if(iface->set_selection) { /* Call virtual function to set selection */ success=iface->set_selection(self, inSelection); /* If new selection could be set successfully, remove signal handlers * from old selection and set up signal handlers for new selection. */ if(success) { /* Remove signal handlers and styles from old selection */ if(oldSelection) { /* Remove signal handlers at old selection*/ g_signal_handlers_disconnect_by_func(oldSelection, G_CALLBACK(_xfdashboard_focusable_on_selection_unavailable), self); /* Remove style from old selection */ if(XFDASHBOARD_IS_STYLABLE(oldSelection)) { xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(oldSelection), "selected"); } } /* Set up signal handlers and styles at new selection */ if(inSelection) { /* Set up signal handlers to get notified if new selection * is going to be unavailable (e.g. hidden or destroyed) */ g_signal_connect_swapped(inSelection, "destroy", G_CALLBACK(_xfdashboard_focusable_on_selection_unavailable), self); g_signal_connect_swapped(inSelection, "hide", G_CALLBACK(_xfdashboard_focusable_on_selection_unavailable), self); /* Style new selection if this focusable actor has the focus */ if(_xfdashboard_focusable_has_focus(self) && XFDASHBOARD_IS_STYLABLE(inSelection)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(inSelection), "selected"); } } /* Emit signal */ g_signal_emit(self, XfdashboardFocusableSignals[SIGNAL_SELECTION_CHANGED], 0, oldSelection, inSelection); } /* Return result of calling virtual function */ return(success); } /* If we get here the virtual function was not overridden */ XFDASHBOARD_FOCUSABLE_WARN_NOT_IMPLEMENTED(self, "set_selection"); return(FALSE); }
/* The current selection of a focusable actor (if focussed or not) is not available anymore * (e.g. hidden or destroyed). So move selection at focusable actor to next available and * selectable item. */ static void _xfdashboard_focusable_on_selection_unavailable(XfdashboardFocusable *self, gpointer inUserData) { XfdashboardFocusableInterface *iface; ClutterActor *oldSelection; ClutterActor *newSelection; gboolean success; XfdashboardApplication *application; g_return_if_fail(XFDASHBOARD_IS_FOCUSABLE(self)); g_return_if_fail(CLUTTER_IS_ACTOR(inUserData)); iface=XFDASHBOARD_FOCUSABLE_GET_IFACE(self); oldSelection=CLUTTER_ACTOR(inUserData); newSelection=NULL; success=FALSE; /* If application is not quitting then call virtual function to set selection * which have to be available because this signal handler was set in * xfdashboard_focusable_set_selection() when this virtual function was available * and successfully called. * If setting new selection was unsuccessful we set selection to nothing (NULL); */ application=xfdashboard_application_get_default(); if(!xfdashboard_application_is_quitting(application)) { /* Get next selection */ newSelection=xfdashboard_focusable_find_selection(self, oldSelection, XFDASHBOARD_SELECTION_TARGET_NEXT); /* Set new selection */ success=iface->set_selection(self, newSelection); if(!success) { success=iface->set_selection(self, newSelection); if(!success) { g_critical(_("Old selection %s at %s is unavailable but setting new selection either to %s or nothing failed!"), G_OBJECT_TYPE_NAME(oldSelection), G_OBJECT_TYPE_NAME(self), newSelection ? G_OBJECT_TYPE_NAME(newSelection) : "<nil>"); } /* Now reset new selection to NULL regardless if setting selection at * focusable actor was successful or not. A critical warning was displayed * if is was unsuccessful because setting nothing (NULL) must succeed usually. */ newSelection=NULL; } } /* Regardless if setting selection was successful, remove signal handlers * and styles from old selection. */ if(oldSelection) { /* Remove signal handlers at old selection*/ g_signal_handlers_disconnect_by_func(oldSelection, G_CALLBACK(_xfdashboard_focusable_on_selection_unavailable), self); /* Remove style from old selection */ if(XFDASHBOARD_IS_STYLABLE(oldSelection)) { xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(oldSelection), "selected"); } } /* If setting selection was successful, set up signal handlers and styles at new selection */ if(success && newSelection) { /* Set up signal handlers to get notified if new selection * is going to be unavailable (e.g. hidden or destroyed) */ g_signal_connect_swapped(newSelection, "destroy", G_CALLBACK(_xfdashboard_focusable_on_selection_unavailable), self); g_signal_connect_swapped(newSelection, "hide", G_CALLBACK(_xfdashboard_focusable_on_selection_unavailable), self); /* Check if this focusable actor has the focus because if it has * the have to style new selection. */ if(_xfdashboard_focusable_has_focus(self) && XFDASHBOARD_IS_STYLABLE(newSelection)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(newSelection), "selected"); } } /* Emit signal because at least old selection has changed */ g_signal_emit(self, XfdashboardFocusableSignals[SIGNAL_SELECTION_CHANGED], 0, oldSelection, newSelection); }
/* 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); } }