/* Find live workspace actor for native workspace */ static XfdashboardLiveWorkspace* _xfdashboard_workspace_selector_find_actor_for_workspace(XfdashboardWorkspaceSelector *self, XfdashboardWindowTrackerWorkspace *inWorkspace) { ClutterActorIter iter; ClutterActor *child; XfdashboardLiveWorkspace *liveWorkspace; g_return_val_if_fail(XFDASHBOARD_IS_WORKSPACE_SELECTOR(self), NULL); g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace), NULL); /* Iterate through workspace actor and lookup the one handling requesting workspace */ clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self)); while(clutter_actor_iter_next(&iter, &child)) { if(XFDASHBOARD_IS_LIVE_WORKSPACE(child)) { liveWorkspace=XFDASHBOARD_LIVE_WORKSPACE(child); if(xfdashboard_live_workspace_get_workspace(liveWorkspace)==inWorkspace) { return(liveWorkspace); } } } return(NULL); }
/* 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); }
/* This actor was clicked */ static void _xfdashboard_live_workspace_on_clicked(XfdashboardLiveWorkspace *self, ClutterActor *inActor, gpointer inUserData) { g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); /* Emit "clicked" signal */ g_signal_emit(self, XfdashboardLiveWorkspaceSignals[SIGNAL_CLICKED], 0); }
/* A window's workspace has changed */ static void _xfdashboard_live_workspace_on_window_workspace_changed(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow, XfdashboardWindowTrackerWorkspace *inWorkspace, gpointer inUserData) { XfdashboardLiveWorkspacePrivate *priv; ClutterActor *windowActor; g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow)); priv=self->priv; /* Check if window was removed from workspace or added */ if(inWorkspace!=priv->workspace) { /* Find actor for window */ windowActor=_xfdashboard_live_workspace_find_by_window(self, inWindow); /* Destroy window actor */ if(windowActor) clutter_actor_destroy(windowActor); } else { /* Add window actor */ _xfdashboard_live_workspace_create_and_add_window_actor(self, inWindow); } }
/* Window stacking has changed */ static void _xfdashboard_live_workspace_on_window_stacking_changed(XfdashboardLiveWorkspace *self, gpointer inUserData) { XfdashboardLiveWorkspacePrivate *priv=XFDASHBOARD_LIVE_WORKSPACE(self)->priv; GList *windows; XfdashboardWindowTrackerWindow *window; ClutterActor *actor; g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); priv=self->priv; /* Get stacked order of windows */ windows=xfdashboard_window_tracker_get_windows_stacked(priv->windowTracker); /* Iterate through list of stacked window from beginning to end * and reinsert each window found to bottom of this actor */ for( ; windows; windows=g_list_next(windows)) { /* Get window and find corresponding actor */ window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(windows->data); if(!window) continue; actor=_xfdashboard_live_workspace_find_by_window(self, window); if(!actor) continue; /* If we get here the window actor was found so move to bottom */ g_object_ref(actor); clutter_actor_remove_child(CLUTTER_ACTOR(self), actor); clutter_actor_insert_child_above(CLUTTER_ACTOR(self), actor, NULL); g_object_unref(actor); } }
/* Find live window actor by window */ static ClutterActor* _xfdashboard_live_workspace_find_by_window(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow) { ClutterActor *child; ClutterActorIter iter; ClutterContent *content; XfdashboardWindowTrackerWindow *window; g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self), NULL); g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL); /* Iterate through list of current actors and find the one for requested window */ clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self)); while(clutter_actor_iter_next(&iter, &child)) { content=clutter_actor_get_content(child); if(!content || !XFDASHBOARD_IS_WINDOW_CONTENT(content)) continue; window=xfdashboard_window_content_get_window(XFDASHBOARD_WINDOW_CONTENT(content)); if(window==inWindow) return(child); } /* If we get here we did not find the window and we return NULL */ return(NULL); }
/* A window's position and/or size has changed */ static void _xfdashboard_live_workspace_on_window_geometry_changed(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow, gpointer inUserData) { g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow)); /* Actor's allocation may change because of new geometry so relayout */ clutter_actor_queue_relayout(CLUTTER_ACTOR(self)); }
/* A window was opened */ static void _xfdashboard_live_workspace_on_window_opened(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow, gpointer inUserData) { g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow)); /* Check if window is visible on this workspace */ if(!_xfdashboard_live_workspace_is_visible_window(self, inWindow)) return; /* Create actor for window */ _xfdashboard_live_workspace_create_and_add_window_actor(self, inWindow); }
/* A window was closed */ static void _xfdashboard_live_workspace_on_window_closed(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow, gpointer inUserData) { ClutterActor *windowActor; g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow)); /* Find and destroy actor */ windowActor=_xfdashboard_live_workspace_find_by_window(self, inWindow); if(windowActor) clutter_actor_destroy(windowActor); }
/* A live workspace was clicked */ static void _xfdashboard_workspace_selector_on_workspace_clicked(XfdashboardWorkspaceSelector *self, gpointer inUserData) { XfdashboardLiveWorkspace *liveWorkspace; g_return_if_fail(XFDASHBOARD_IS_WORKSPACE_SELECTOR(self)); g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(inUserData)); liveWorkspace=XFDASHBOARD_LIVE_WORKSPACE(inUserData); /* Active workspace */ xfdashboard_window_tracker_workspace_activate(xfdashboard_live_workspace_get_workspace(liveWorkspace)); /* Quit application */ xfdashboard_application_quit(); }
/* Activate selection */ static gboolean _xfdashboard_workspace_selector_focusable_activate_selection(XfdashboardFocusable *inFocusable, ClutterActor *inSelection) { XfdashboardWorkspaceSelector *self; XfdashboardLiveWorkspace *actor; XfdashboardWindowTrackerWorkspace *workspace; g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_WORKSPACE_SELECTOR(inFocusable), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(inSelection), FALSE); self=XFDASHBOARD_WORKSPACE_SELECTOR(inFocusable); actor=XFDASHBOARD_LIVE_WORKSPACE(inSelection); workspace=NULL; /* Check that selection is a child of this actor */ if(!xfdashboard_actor_contains_child_deep(CLUTTER_ACTOR(self), inSelection)) { ClutterActor *parent; parent=clutter_actor_get_parent(inSelection); g_warning(_("%s is a child of %s and cannot be selected at %s"), G_OBJECT_TYPE_NAME(inSelection), parent ? G_OBJECT_TYPE_NAME(parent) : "<nil>", G_OBJECT_TYPE_NAME(self)); } /* Get workspace of new selection and set new selection*/ workspace=xfdashboard_live_workspace_get_workspace(actor); if(workspace) { /* Activate workspace */ xfdashboard_window_tracker_workspace_activate(workspace); /* Quit application */ xfdashboard_application_quit(); /* Activation was successful */ return(TRUE); } /* Activation was unsuccessful if we get here */ g_warning(_("Could not determine workspace of %s to set selection at %s"), G_OBJECT_TYPE_NAME(actor), G_OBJECT_TYPE_NAME(self)); return(FALSE); }
/* 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); } }
/* Check if window should be shown */ static gboolean _xfdashboard_live_workspace_is_visible_window(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow) { XfdashboardLiveWorkspacePrivate *priv; g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), FALSE); priv=self->priv; /* Determine if windows should be shown depending on its state */ if(xfdashboard_window_tracker_window_is_skip_pager(inWindow) || xfdashboard_window_tracker_window_is_skip_tasklist(inWindow) || (priv->workspace && !xfdashboard_window_tracker_window_is_visible_on_workspace(inWindow, priv->workspace)) || xfdashboard_window_tracker_window_is_stage(inWindow)) { return(FALSE); } /* If we get here the window should be shown */ return(TRUE); }
/* A window's state has changed */ static void _xfdashboard_live_workspace_on_window_state_changed(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow, gpointer inUserData) { /* We need to see it from the point of view of a workspace. * If a window is visible on the workspace but we have no actor * for this window then create it. If a window is not visible anymore * on this workspace then destroy the corresponding actor. * That is why initially we set any window to invisible because if * changed window is not visible on this workspace it will do nothing. */ ClutterActor *windowActor; gboolean newVisible; gboolean currentVisible; g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow)); currentVisible=FALSE; /* Find window and get current visibility state */ windowActor=_xfdashboard_live_workspace_find_by_window(self, inWindow); if(windowActor) { currentVisible=!!CLUTTER_ACTOR_IS_VISIBLE(windowActor); } /* Check if window's visibility has changed */ newVisible=_xfdashboard_live_workspace_is_visible_window(self, inWindow); if(newVisible!=currentVisible) { if(newVisible) _xfdashboard_live_workspace_create_and_add_window_actor(self, inWindow); else if(windowActor) clutter_actor_destroy(windowActor); } }
void xfdashboard_live_workspace_set_workspace(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWorkspace *inWorkspace) { XfdashboardLiveWorkspacePrivate *priv; ClutterContent *content; XfdashboardWindowTrackerWindow *window; ClutterActor *child; ClutterActorIter iter; GList *windows; ClutterActor *actor; g_return_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self)); g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WORKSPACE(inWorkspace)); priv=self->priv; /* Only set value if it changes */ if(inWorkspace==priv->workspace) return; /* Release old value */ if(priv->workspace) { g_signal_handlers_disconnect_by_data(priv->workspace, self); priv->workspace=NULL; } /* Set new value * Window tracker objects should never be refed or unrefed, so just set new value */ priv->workspace=inWorkspace; /* Destroy all window actors */ clutter_actor_iter_init(&iter, CLUTTER_ACTOR(self)); while(clutter_actor_iter_next(&iter, &child)) { /* Get window actor */ if(!CLUTTER_IS_ACTOR(child)) continue; /* Check if it is really a window actor by retrieving associated window */ content=clutter_actor_get_content(child); if(!content || !XFDASHBOARD_IS_WINDOW_CONTENT(content)) continue; /* Destroy window actor */ clutter_actor_destroy(child); } /* Create windows for new workspace in stacked order */ windows=xfdashboard_window_tracker_get_windows_stacked(priv->windowTracker); for( ; windows; windows=g_list_next(windows)) { /* Get window */ window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(windows->data); if(!window) continue; /* Create window actor if window is visible */ if(!_xfdashboard_live_workspace_is_visible_window(self, window)) continue; actor=clutter_actor_new(); content=xfdashboard_window_content_new_for_window(window); clutter_actor_set_content(actor, content); g_object_unref(content); /* Insert new actor at bottom */ clutter_actor_insert_child_above(CLUTTER_ACTOR(self), actor, NULL); } /* Notify about property change */ g_object_notify_by_pspec(G_OBJECT(self), XfdashboardLiveWorkspaceProperties[PROP_WORKSPACE]); }
/* Create actor for window but respect window stacking when adding */ static ClutterActor* _xfdashboard_live_workspace_create_and_add_window_actor(XfdashboardLiveWorkspace *self, XfdashboardWindowTrackerWindow *inWindow) { XfdashboardLiveWorkspacePrivate *priv; ClutterActor *actor; ClutterContent *content; GList *windows; ClutterActor *lastWindowActor; XfdashboardWindowTrackerWindow *window; g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self), NULL); g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL); priv=self->priv; /* We cannot assume that each window newly opened or moved to this workspace * will be on top of all other windows. We need to respect window stacking. * Therefore we iterate through list of windows in stacking order and find * the last window we have an actor for before we the window requested. */ lastWindowActor=NULL; windows=xfdashboard_window_tracker_get_windows_stacked(priv->windowTracker); for( ; windows; windows=g_list_next(windows)) { /* Get window from list */ window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(windows->data); if(!window) continue; /* We do not need to check if window would be visible on this workspace * as it should not have been created if it is not visible. */ lastWindowActor=_xfdashboard_live_workspace_find_by_window(self, window); if(lastWindowActor) break; } /* Check if we have to "move" an existing window actor or if we have to create * a new actor for window */ actor=_xfdashboard_live_workspace_find_by_window(self, inWindow); if(actor) { /* Move existing window actor to new stacking position */ g_object_ref(actor); clutter_actor_remove_child(CLUTTER_ACTOR(self), actor); clutter_actor_insert_child_above(CLUTTER_ACTOR(self), actor, lastWindowActor); g_object_unref(actor); } else { /* Create actor */ actor=clutter_actor_new(); content=xfdashboard_window_content_new_for_window(inWindow); clutter_actor_set_content(actor, content); g_object_unref(content); /* Add new actor at right stacking position */ clutter_actor_insert_child_above(CLUTTER_ACTOR(self), actor, lastWindowActor); } return(actor); }
/* Find requested selection target depending of current selection */ static ClutterActor* _xfdashboard_workspace_selector_focusable_find_selection(XfdashboardFocusable *inFocusable, ClutterActor *inSelection, XfdashboardSelectionTarget inDirection) { XfdashboardWorkspaceSelector *self; XfdashboardWorkspaceSelectorPrivate *priv; XfdashboardLiveWorkspace *selection; ClutterActor *newSelection; g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), NULL); g_return_val_if_fail(XFDASHBOARD_IS_WORKSPACE_SELECTOR(inFocusable), NULL); g_return_val_if_fail(!inSelection || XFDASHBOARD_IS_LIVE_WORKSPACE(inSelection), NULL); self=XFDASHBOARD_WORKSPACE_SELECTOR(inFocusable); priv=self->priv; newSelection=NULL; selection=NULL; /* Find actor for current active workspace which is also the current selection */ if(priv->activeWorkspace) { selection=_xfdashboard_workspace_selector_find_actor_for_workspace(self, priv->activeWorkspace); } if(!selection) return(NULL); /* If there is nothing selected return currently determined actor which is * the current active workspace. */ if(!inSelection) { g_debug("No selection at %s, so select first child %s for direction %u", G_OBJECT_TYPE_NAME(self), selection ? G_OBJECT_TYPE_NAME(selection) : "<nil>", inDirection); return(CLUTTER_ACTOR(selection)); } /* Check that selection is a child of this actor otherwise return NULL */ if(!xfdashboard_actor_contains_child_deep(CLUTTER_ACTOR(self), inSelection)) { ClutterActor *parent; parent=clutter_actor_get_parent(inSelection); g_warning(_("Cannot lookup selection target at %s because %s is a child of %s"), G_OBJECT_TYPE_NAME(self), G_OBJECT_TYPE_NAME(inSelection), parent ? G_OBJECT_TYPE_NAME(parent) : "<nil>"); return(NULL); } /* Find target selection */ switch(inDirection) { case XFDASHBOARD_SELECTION_TARGET_LEFT: if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { newSelection=clutter_actor_get_previous_sibling(CLUTTER_ACTOR(selection)); } break; case XFDASHBOARD_SELECTION_TARGET_UP: if(priv->orientation==CLUTTER_ORIENTATION_VERTICAL) { newSelection=clutter_actor_get_previous_sibling(CLUTTER_ACTOR(selection)); } break; case XFDASHBOARD_SELECTION_TARGET_RIGHT: if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { newSelection=clutter_actor_get_next_sibling(CLUTTER_ACTOR(selection)); } break; case XFDASHBOARD_SELECTION_TARGET_DOWN: if(priv->orientation==CLUTTER_ORIENTATION_VERTICAL) { newSelection=clutter_actor_get_next_sibling(CLUTTER_ACTOR(selection)); } break; case XFDASHBOARD_SELECTION_TARGET_FIRST: case XFDASHBOARD_SELECTION_TARGET_PAGE_UP: case XFDASHBOARD_SELECTION_TARGET_PAGE_LEFT: if(inDirection==XFDASHBOARD_SELECTION_TARGET_FIRST || (inDirection==XFDASHBOARD_SELECTION_TARGET_PAGE_UP && priv->orientation==CLUTTER_ORIENTATION_VERTICAL) || (inDirection==XFDASHBOARD_SELECTION_TARGET_PAGE_LEFT && priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)) { newSelection=clutter_actor_get_first_child(CLUTTER_ACTOR(self)); } break; case XFDASHBOARD_SELECTION_TARGET_LAST: case XFDASHBOARD_SELECTION_TARGET_PAGE_DOWN: case XFDASHBOARD_SELECTION_TARGET_PAGE_RIGHT: if(inDirection==XFDASHBOARD_SELECTION_TARGET_LAST || (inDirection==XFDASHBOARD_SELECTION_TARGET_PAGE_DOWN && priv->orientation==CLUTTER_ORIENTATION_VERTICAL) || (inDirection==XFDASHBOARD_SELECTION_TARGET_PAGE_RIGHT && priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL)) { newSelection=clutter_actor_get_last_child(CLUTTER_ACTOR(self)); } break; case XFDASHBOARD_SELECTION_TARGET_NEXT: newSelection=clutter_actor_get_next_sibling(CLUTTER_ACTOR(selection)); if(!newSelection) newSelection=clutter_actor_get_previous_sibling(CLUTTER_ACTOR(selection)); break; default: { gchar *valueName; valueName=xfdashboard_get_enum_value_name(XFDASHBOARD_TYPE_SELECTION_TARGET, inDirection); g_critical(_("Focusable object %s does not handle selection direction of type %s."), G_OBJECT_TYPE_NAME(self), valueName); g_free(valueName); } break; } /* If new selection could be found override current selection with it */ if(newSelection && XFDASHBOARD_IS_LIVE_WORKSPACE(newSelection)) { selection=XFDASHBOARD_LIVE_WORKSPACE(newSelection); } /* Return new selection found */ g_debug("Selecting %s at %s for current selection %s in direction %u", selection ? G_OBJECT_TYPE_NAME(selection) : "<nil>", G_OBJECT_TYPE_NAME(self), inSelection ? G_OBJECT_TYPE_NAME(inSelection) : "<nil>", inDirection); return(CLUTTER_ACTOR(selection)); }
/* Get/set window to show */ XfdashboardWindowTrackerWorkspace* xfdashboard_live_workspace_get_workspace(XfdashboardLiveWorkspace *self) { g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WORKSPACE(self), NULL); return(self->priv->workspace); }