[Xfce4-commits] [apps/xfdashboard] 02/02: Add support to show sub-windows of main windows at XfdashboardLiveWindow as they are used in windows view (XfdashboardWindowsView).
noreply at xfce.org
noreply at xfce.org
Fri Feb 3 13:13:47 CET 2017
This is an automated email from the git hooks/post-receive script.
nomad pushed a commit to branch master
in repository apps/xfdashboard.
commit af97b4484f9a6058a3f2a061b16c406380f0e3b1
Author: Stephan Haller <nomad at froevel.de>
Date: Fri Feb 3 13:12:50 2017 +0100
Add support to show sub-windows of main windows at XfdashboardLiveWindow as they are used in windows view (XfdashboardWindowsView).
---
libxfdashboard/live-window.c | 548 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 463 insertions(+), 85 deletions(-)
diff --git a/libxfdashboard/live-window.c b/libxfdashboard/live-window.c
index 232eeaf..22b9c2e 100644
--- a/libxfdashboard/live-window.c
+++ b/libxfdashboard/live-window.c
@@ -64,6 +64,7 @@ struct _XfdashboardLiveWindowPrivate
/* Instance related */
XfdashboardWindowTracker *windowTracker;
+ ClutterActor *actorSubwindowsLayer;
ClutterActor *actorControlLayer;
ClutterActor *actorClose;
ClutterActor *actorWindowNumber;
@@ -98,6 +99,233 @@ static guint XfdashboardLiveWindowSignals[SIGNAL_LAST]={ 0, };
/* IMPLEMENTATION: Private variables and methods */
+/* Check if the requested window is a sub-window of this window */
+static gboolean _xfdashboard_live_window_is_subwindow(XfdashboardLiveWindow *self,
+ XfdashboardWindowTrackerWindow *inWindow)
+{
+ XfdashboardWindowTrackerWindow *thisWindow;
+ XfdashboardWindowTrackerWindow *requestedWindowParent;
+
+ g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self), FALSE);
+ g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), FALSE);
+
+ /* Check if window opened belong to this window (is transient for this one) */
+ thisWindow=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(self));
+ if(!thisWindow) return(FALSE);
+
+ requestedWindowParent=xfdashboard_window_tracker_window_get_parent_window(inWindow);
+ if(!requestedWindowParent) return(FALSE);
+
+ if(requestedWindowParent!=thisWindow) return(FALSE);
+
+ /* All checks succeeded so it is a sub-window and we return TRUE here */
+ return(TRUE);
+}
+
+/* Check if requested sub-window should be displayed */
+static gboolean _xfdashboard_live_window_should_display_subwindow(XfdashboardLiveWindow *self,
+ XfdashboardWindowTrackerWindow *inWindow)
+{
+ g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self), FALSE);
+ g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), FALSE);
+
+ /* Check if window opened belong to this window (is transient for this one) */
+ if(!_xfdashboard_live_window_is_subwindow(self, inWindow)) return(FALSE);
+
+ /* Check if window opened is visible */
+ if(!xfdashboard_window_tracker_window_is_visible(inWindow)) return(FALSE);
+
+ /* Check if window is either pinned. If it is not then check if it is on the
+ * same workspace as its parent window. We can do this simple check because
+ * the window opened is transient window of its parent and it looks like it
+ * will inherit the same "pin" state.
+ */
+ if(!xfdashboard_window_tracker_window_is_pinned(inWindow))
+ {
+ XfdashboardWindowTrackerWindow *thisWindow;
+ XfdashboardWindowTrackerWorkspace *workspace;
+
+ thisWindow=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(self));
+ workspace=xfdashboard_window_tracker_window_get_workspace(thisWindow);
+ if(workspace && !xfdashboard_window_tracker_window_is_on_workspace(inWindow, workspace)) return(FALSE);
+ }
+
+ /* All checks passed and we should display this sub-window, so return TRUE */
+ return(TRUE);
+
+}
+
+/* Find actor for requested sub-window */
+static ClutterActor* _xfdashboard_live_window_find_subwindow_actor(XfdashboardLiveWindow *self,
+ XfdashboardWindowTrackerWindow *inWindow)
+{
+ XfdashboardLiveWindowPrivate *priv;
+ ClutterActorIter iter;
+ ClutterActor *child;
+ XfdashboardWindowTrackerWindow *childWindow;
+
+ g_return_val_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self), NULL);
+ g_return_val_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow), NULL);
+
+ priv=self->priv;
+
+ /* Iterate through actors at sub-windows layer and return the actor handling
+ * the requested window.
+ */
+ if(priv->actorSubwindowsLayer)
+ {
+ clutter_actor_iter_init(&iter, priv->actorSubwindowsLayer);
+ while(clutter_actor_iter_next(&iter, &child))
+ {
+ /* Skip actor not handling live windows */
+ if(!XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(child)) continue;
+
+ /* Check if this actor handles the requested window */
+ childWindow=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(child));
+ if(childWindow==inWindow) return(child);
+ }
+ }
+
+ /* If we get here, we did not find any actor handling the requested window.
+ * So return NULL.
+ */
+ return(NULL);
+}
+
+/* A sub-window changed workspace, so check if this sub-window should not be
+ * shown anymore and find associated actor to destroy.
+ */
+static void _xfdashboard_live_window_on_subwindow_actor_workspace_changed(XfdashboardLiveWindow *self,
+ gpointer inUserData)
+{
+ XfdashboardWindowTrackerWindow *window;
+ ClutterActor *actor;
+
+ g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self));
+ g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inUserData));
+
+ window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(inUserData);
+
+ /* Check if we should display this window at all. If it should still be
+ * display, return immediately.
+ */
+ if(_xfdashboard_live_window_should_display_subwindow(self, window)) return;
+
+ /* This window should not displayed anymore. Find associated actor and
+ * destroy it.
+ */
+ actor=_xfdashboard_live_window_find_subwindow_actor(self, window);
+ if(actor) clutter_actor_destroy(actor);
+}
+
+/* A sub-window changed its state, so check if this sub-window should not be
+ * shown anymore and find associated actor to destroy it
+ */
+static void _xfdashboard_live_window_on_subwindow_actor_state_changed(XfdashboardLiveWindow *self,
+ gint inChangedMask,
+ gint inNewState,
+ gpointer inUserData)
+{
+ XfdashboardWindowTrackerWindow *window;
+ ClutterActor *actor;
+
+ g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self));
+ g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inUserData));
+
+ window=XFDASHBOARD_WINDOW_TRACKER_WINDOW(inUserData);
+
+ /* Check if we should display this window at all. If it should still be
+ * display, return immediately.
+ */
+ if(_xfdashboard_live_window_should_display_subwindow(self, window)) return;
+
+ /* This window should not displayed anymore. Find associated actor and
+ * destroy it.
+ */
+ actor=_xfdashboard_live_window_find_subwindow_actor(self, window);
+ if(actor) clutter_actor_destroy(actor);
+}
+
+/* A sub-window actor is going to be destroyed, so clean up */
+static void _xfdashboard_live_window_on_subwindow_actor_destroyed(XfdashboardLiveWindow *self,
+ gpointer inUserData)
+{
+ ClutterActor *actor;
+ XfdashboardWindowTrackerWindow *window;
+
+ g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self));
+ g_return_if_fail(CLUTTER_IS_ACTOR(inUserData));
+
+ actor=CLUTTER_ACTOR(inUserData);
+
+ /* Check if the actor going to be destroyed is an actor showing live windows */
+ if(!XFDASHBOARD_IS_LIVE_WINDOW_SIMPLE(actor)) return;
+
+ /* Get associated window of the live window actor going to be destroyed */
+ window=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(actor));
+ if(!window) return;
+
+ /* Disconnect signals to prevent them get called even when this actor does
+ * not exist anymore.
+ */
+ g_signal_handlers_disconnect_by_func(window, _xfdashboard_live_window_on_subwindow_actor_workspace_changed, self);
+ g_signal_handlers_disconnect_by_func(window, _xfdashboard_live_window_on_subwindow_actor_state_changed, self);
+}
+
+/* A window was opened and might be a sub-window of this one and should be shown */
+static void _xfdashboard_live_window_on_subwindow_opened(XfdashboardLiveWindow *self,
+ XfdashboardWindowTrackerWindow *inWindow,
+ gpointer inUserData)
+{
+ XfdashboardLiveWindowPrivate *priv;
+ ClutterActor *actor;
+
+ g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self));
+ g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
+
+ priv=self->priv;
+
+ /* Check if we should display this window at all */
+ if(!_xfdashboard_live_window_should_display_subwindow(self, inWindow)) return;
+
+ /* Before adding an actor for this window, check if an actor already exists */
+ if(_xfdashboard_live_window_find_subwindow_actor(self, inWindow)) return;
+
+ /* Add child to this window */
+ actor=xfdashboard_live_window_simple_new_for_window(inWindow);
+ clutter_actor_set_reactive(actor, FALSE);
+ clutter_actor_show(actor);
+ clutter_actor_add_child(priv->actorSubwindowsLayer, actor);
+
+ /* Connect signals */
+ g_signal_connect_swapped(actor, "destroy", G_CALLBACK(_xfdashboard_live_window_on_subwindow_actor_destroyed), self);
+
+ g_signal_connect_swapped(inWindow, "workspace-changed", G_CALLBACK(_xfdashboard_live_window_on_subwindow_actor_workspace_changed), self);
+ g_signal_connect_swapped(inWindow, "state-changed", G_CALLBACK(_xfdashboard_live_window_on_subwindow_actor_state_changed), self);
+}
+
+/* A window has changed workspace and might be a sub-window of this one
+ * which should be shown.
+ */
+static void _xfdashboard_live_window_on_subwindow_workspace_changed(XfdashboardLiveWindow *self,
+ XfdashboardWindowTrackerWindow *inWindow,
+ XfdashboardWindowTrackerWorkspace *inWorkspace,
+ gpointer inUserData)
+{
+ g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(self));
+ g_return_if_fail(XFDASHBOARD_IS_WINDOW_TRACKER_WINDOW(inWindow));
+
+ /* Just call signal handler hanlding new windows opened because it will
+ * perform all needed checks to determine if this window is a sub-window and
+ * should be shown. It will also create the actor needed.
+ * In case the window moved away from the workspace the signal handler
+ * connect to the window directly will perform all check to determine if
+ * this window should not be displayed anymore and destroy the associated
+ * actor in this case. So not need to check this here.
+ */
+ _xfdashboard_live_window_on_subwindow_opened(self, inWindow, NULL);
+}
+
/* This actor was clicked */
static void _xfdashboard_live_window_on_clicked(XfdashboardLiveWindow *self,
ClutterActor *inActor,
@@ -275,6 +503,8 @@ static void _xfdashboard_live_window_on_window_changed(GObject *inObject,
XfdashboardLiveWindow *self;
XfdashboardLiveWindowPrivate *priv;
XfdashboardWindowTrackerWindow *window;
+ GList *windowList;
+ XfdashboardWindowTrackerWindow *subwindow;
g_return_if_fail(XFDASHBOARD_IS_LIVE_WINDOW(inObject));
@@ -288,6 +518,23 @@ static void _xfdashboard_live_window_on_window_changed(GObject *inObject,
_xfdashboard_live_window_on_actions_changed(self, window, priv->windowTracker);
_xfdashboard_live_window_on_icon_changed(self, window, priv->windowTracker);
_xfdashboard_live_window_on_name_changed(self, window, priv->windowTracker);
+
+ /* Destroy all sub-windows and create the ones belonging to this new window */
+ clutter_actor_destroy_all_children(priv->actorSubwindowsLayer);
+
+ windowList=xfdashboard_window_tracker_get_windows_stacked(priv->windowTracker);
+ for( ; windowList; windowList=g_list_next(windowList))
+ {
+ /* Get window at current position of iterator */
+ subwindow=XFDASHBOARD_WINDOW_TRACKER_WINDOW(windowList->data);
+ if(!subwindow) continue;
+
+ /* Call signal handler for the event when a window is opened. It will
+ * check if this window is a visible child of this window and it will
+ * create the actor if needed.
+ */
+ _xfdashboard_live_window_on_subwindow_opened(self, subwindow, priv->windowTracker);
+ }
}
/* IMPLEMENTATION: ClutterActor */
@@ -301,12 +548,29 @@ static void _xfdashboard_live_window_get_preferred_height(ClutterActor *self,
XfdashboardLiveWindowPrivate *priv=XFDASHBOARD_LIVE_WINDOW(self)->priv;
gfloat minHeight, naturalHeight;
gfloat childMinHeight, childNaturalHeight;
+ ClutterActorIter iter;
+ ClutterActor *child;
minHeight=naturalHeight=0.0f;
/* Chain up to determine size of window of this actor (should usually be the largest actor) */
CLUTTER_ACTOR_CLASS(xfdashboard_live_window_parent_class)->get_preferred_height(self, inForWidth, &minHeight, &naturalHeight);
+ /* Determine size of each sub-window */
+ clutter_actor_iter_init(&iter, priv->actorSubwindowsLayer);
+ while(clutter_actor_iter_next(&iter, &child))
+ {
+ if(clutter_actor_is_visible(child))
+ {
+ clutter_actor_get_preferred_height(child,
+ inForWidth,
+ &childMinHeight,
+ &childNaturalHeight);
+ if(childMinHeight>minHeight) minHeight=childMinHeight;
+ if(childNaturalHeight>naturalHeight) naturalHeight=childNaturalHeight;
+ }
+ }
+
/* Determine size of title actor if visible */
if(clutter_actor_is_visible(priv->actorTitle))
{
@@ -359,12 +623,29 @@ static void _xfdashboard_live_window_get_preferred_width(ClutterActor *self,
XfdashboardLiveWindowPrivate *priv=XFDASHBOARD_LIVE_WINDOW(self)->priv;
gfloat minWidth, naturalWidth;
gfloat childMinWidth, childNaturalWidth;
+ ClutterActorIter iter;
+ ClutterActor *child;
minWidth=naturalWidth=0.0f;
/* Chain up to determine size of window of this actor (should usually be the largest actor) */
CLUTTER_ACTOR_CLASS(xfdashboard_live_window_parent_class)->get_preferred_width(self, inForHeight, &minWidth, &naturalWidth);
+ /* Determine size of each sub-window */
+ clutter_actor_iter_init(&iter, priv->actorSubwindowsLayer);
+ while(clutter_actor_iter_next(&iter, &child))
+ {
+ if(clutter_actor_is_visible(child))
+ {
+ clutter_actor_get_preferred_width(child,
+ inForHeight,
+ &childMinWidth,
+ &childNaturalWidth);
+ if(childMinWidth>minWidth) minWidth=childMinWidth;
+ if(childNaturalWidth>naturalWidth) naturalWidth=childNaturalWidth;
+ }
+ }
+
/* Determine size of title actor if visible */
if(clutter_actor_is_visible(priv->actorTitle))
{
@@ -414,105 +695,184 @@ static void _xfdashboard_live_window_allocate(ClutterActor *self,
const ClutterActorBox *inBox,
ClutterAllocationFlags inFlags)
{
- XfdashboardLiveWindowPrivate *priv=XFDASHBOARD_LIVE_WINDOW(self)->priv;
- ClutterActorBox *boxActorControlLayer=NULL;
- ClutterActorBox *boxActorTitle=NULL;
- ClutterActorBox *boxActorClose=NULL;
- ClutterActorBox *boxActorWindowNumber=NULL;
- ClutterActorBox *referedBoxActor;
- gfloat maxWidth;
- gfloat titleWidth, titleHeight;
- gfloat closeWidth, closeHeight;
- gfloat windowNumberWidth, windowNumberHeight;
- gfloat left, top, right, bottom;
+ XfdashboardLiveWindowPrivate *priv=XFDASHBOARD_LIVE_WINDOW(self)->priv;
/* Chain up to store the allocation of the actor */
CLUTTER_ACTOR_CLASS(xfdashboard_live_window_parent_class)->allocate(self, inBox, inFlags);
- /* Set allocation on control layer which matches the actor's allocation at
- * width and height but with origin position.
- */
- boxActorControlLayer=clutter_actor_box_copy(inBox);
- clutter_actor_box_set_origin(boxActorControlLayer, 0.0f, 0.0f);
- clutter_actor_allocate(priv->actorControlLayer, boxActorControlLayer, inFlags);
-
- /* Set allocation on close actor */
- clutter_actor_get_preferred_size(priv->actorClose,
- NULL, NULL,
- &closeWidth, &closeHeight);
-
- right=clutter_actor_box_get_x(boxActorControlLayer)+clutter_actor_box_get_width(boxActorControlLayer)-priv->paddingClose;
- left=MAX(right-closeWidth, priv->paddingClose);
- top=clutter_actor_box_get_y(boxActorControlLayer)+priv->paddingClose;
- bottom=top+closeHeight;
-
- right=MAX(left, right);
- bottom=MAX(top, bottom);
-
- boxActorClose=clutter_actor_box_new(floor(left), floor(top), floor(right), floor(bottom));
- clutter_actor_allocate(priv->actorClose, boxActorClose, inFlags);
-
- /* Set allocation on window number actor (expand to size of close button if needed) */
- clutter_actor_get_preferred_size(priv->actorWindowNumber,
- NULL, NULL,
- &windowNumberWidth, &windowNumberHeight);
-
- right=clutter_actor_box_get_x(boxActorControlLayer)+clutter_actor_box_get_width(boxActorControlLayer)-priv->paddingClose;
- left=MAX(right-windowNumberWidth, priv->paddingClose);
- top=clutter_actor_box_get_y(boxActorControlLayer)+priv->paddingClose;
- bottom=top+windowNumberHeight;
-
- left=MIN(left, clutter_actor_box_get_x(boxActorClose));
- right=MAX(left, right);
- bottom=MAX(top, bottom);
- bottom=MAX(bottom, clutter_actor_box_get_y(boxActorClose)+clutter_actor_box_get_height(boxActorClose));
-
- boxActorWindowNumber=clutter_actor_box_new(floor(left), floor(top), floor(right), floor(bottom));
- clutter_actor_allocate(priv->actorWindowNumber, boxActorWindowNumber, inFlags);
-
- /* Set allocation on title actor
- * But prevent that title overlaps close button
- */
- if(priv->windowNumber>0) referedBoxActor=boxActorWindowNumber;
- else referedBoxActor=boxActorClose;
-
- clutter_actor_get_preferred_size(priv->actorTitle,
- NULL, NULL,
- &titleWidth, &titleHeight);
-
- maxWidth=clutter_actor_box_get_width(boxActorControlLayer)-(2*priv->paddingTitle);
- if(titleWidth>maxWidth) titleWidth=maxWidth;
-
- left=clutter_actor_box_get_x(boxActorControlLayer)+((clutter_actor_box_get_width(boxActorControlLayer)-titleWidth)/2.0f);
- right=left+titleWidth;
- bottom=clutter_actor_box_get_y(boxActorControlLayer)+clutter_actor_box_get_height(boxActorControlLayer)-(2*priv->paddingTitle);
- top=bottom-titleHeight;
- if(left>right) left=right-1.0f;
- if(top<(clutter_actor_box_get_y(referedBoxActor)+clutter_actor_box_get_height(referedBoxActor)))
+ /* Set allocation of sub-windows layer if available */
+ if(priv->actorSubwindowsLayer)
{
- if(right>=clutter_actor_box_get_x(referedBoxActor))
+ ClutterActorBox boxActorLayer;
+ ClutterActorBox boxActorChild;
+ ClutterActorIter iter;
+ ClutterActor *child;
+ XfdashboardWindowTrackerWindow *window;
+ gfloat largestWidth, largestHeight;
+ gfloat childWidth, childHeight;
+ gfloat scaleWidth, scaleHeight;
+ gfloat layerWidth, layerHeight;
+ gfloat left, right, top, bottom;
+
+ /* Calculate and set allocation at each sub-window on sub-windows layer.
+ * They need to be scaled down and to keep their aspect ratio to fit into
+ * allocation of sub-windows layer.
+ */
+ largestWidth=largestHeight=0.0f;
+
+ window=xfdashboard_live_window_simple_get_window(XFDASHBOARD_LIVE_WINDOW_SIMPLE(self));
+ if(window)
{
- right=clutter_actor_box_get_x(referedBoxActor)-MIN(priv->paddingTitle, priv->paddingClose);
+ gint windowWidth, windowHeight;
+
+ xfdashboard_window_tracker_window_get_size(window, &windowWidth, &windowHeight);
+ if(windowWidth>largestWidth) largestWidth=windowWidth;
+ if(windowHeight>largestHeight) largestHeight=windowHeight;
}
- if(top<clutter_actor_box_get_y(referedBoxActor))
+ clutter_actor_iter_init(&iter, priv->actorSubwindowsLayer);
+ while(clutter_actor_iter_next(&iter, &child))
+ {
+ if(clutter_actor_is_visible(child))
+ {
+ clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight);
+ if(childWidth>largestWidth) largestWidth=childWidth;
+ if(childHeight>largestHeight) largestHeight=childHeight;
+ }
+ }
+
+ /* Set allocation on sub-windows layer which covers the largest width and
+ * largest height of all windows (including main window of this actor itself)
+ * scaled down to fit into this actor's allocation and centered position.
+ */
+ scaleWidth=clutter_actor_box_get_width(inBox)/largestWidth;
+ scaleHeight=clutter_actor_box_get_height(inBox)/largestHeight;
+
+ layerWidth=largestWidth*scaleWidth;
+ left=(clutter_actor_box_get_width(inBox)-layerWidth)/2.0f;
+ right=left+layerWidth;
+
+ layerHeight=largestHeight*scaleHeight;
+ top=(clutter_actor_box_get_height(inBox)-layerHeight)/2.0f;
+ bottom=top+layerHeight;
+
+ clutter_actor_box_init(&boxActorLayer, floor(left), floor(top), floor(right), floor(bottom));
+ clutter_actor_allocate(priv->actorSubwindowsLayer, &boxActorLayer, inFlags);
+
+ clutter_actor_iter_init(&iter, priv->actorSubwindowsLayer);
+ while(clutter_actor_iter_next(&iter, &child))
{
- top=clutter_actor_box_get_y(referedBoxActor);
- bottom=top+titleHeight;
+ if(clutter_actor_is_visible(child))
+ {
+ /* Get natural size of sub-window */
+ clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight);
+
+ /* Scale down to fit size of allocation of sub-windows layer */
+ childWidth=childWidth*scaleWidth;
+ childHeight=childHeight*scaleHeight;
+
+ /* Center sub-window in allocation of sub-windows layer */
+ left=(layerWidth-childWidth)/2.0f;
+ right=left+childWidth;
+
+ top=(layerHeight-childHeight)/2.0f;
+ bottom=top+childHeight;
+
+ /* Set allocation of sub-window */
+ clutter_actor_box_init(&boxActorChild, floor(left), floor(top), floor(right), floor(bottom));
+ clutter_actor_allocate(child, &boxActorChild, inFlags);
+ }
}
}
- right=MAX(left, right);
- bottom=MAX(top, bottom);
+ /* Set allocation of controls layer if available */
+ if(priv->actorControlLayer)
+ {
+ ClutterActorBox boxActorLayer;
+ ClutterActorBox boxActorClose;
+ ClutterActorBox boxActorWindowNumber;
+ ClutterActorBox boxActorTitle;
+ ClutterActorBox *referedBoxActor;
+ gfloat layerWidth, layerHeight;
+ gfloat closeWidth, closeHeight;
+ gfloat windowNumberWidth, windowNumberHeight;
+ gfloat titleWidth, titleHeight;
+ gfloat left, top, right, bottom;
+ gfloat maxWidth;
+
+ /* Set allocation on control layer which matches the actor's allocation at
+ * width and height but with origin position.
+ */
+ clutter_actor_box_get_size(inBox, &layerWidth, &layerHeight);
+ clutter_actor_box_init(&boxActorLayer, 0.0f, 0.0f, layerWidth, layerHeight);
+ clutter_actor_allocate(priv->actorControlLayer, &boxActorLayer, inFlags);
+
+ /* Set allocation on close actor */
+ clutter_actor_get_preferred_size(priv->actorClose, NULL, NULL, &closeWidth, &closeHeight);
+
+ right=clutter_actor_box_get_x(&boxActorLayer)+clutter_actor_box_get_width(&boxActorLayer)-priv->paddingClose;
+ left=MAX(right-closeWidth, priv->paddingClose);
+ top=clutter_actor_box_get_y(&boxActorLayer)+priv->paddingClose;
+ bottom=top+closeHeight;
+
+ right=MAX(left, right);
+ bottom=MAX(top, bottom);
+
+ clutter_actor_box_init(&boxActorClose, floor(left), floor(top), floor(right), floor(bottom));
+ clutter_actor_allocate(priv->actorClose, &boxActorClose, inFlags);
+
+ /* Set allocation on window number actor (expand to size of close button if needed) */
+ clutter_actor_get_preferred_size(priv->actorWindowNumber, NULL, NULL, &windowNumberWidth, &windowNumberHeight);
+
+ right=clutter_actor_box_get_x(&boxActorLayer)+clutter_actor_box_get_width(&boxActorLayer)-priv->paddingClose;
+ left=MAX(right-windowNumberWidth, priv->paddingClose);
+ top=clutter_actor_box_get_y(&boxActorLayer)+priv->paddingClose;
+ bottom=top+windowNumberHeight;
+
+ left=MIN(left, clutter_actor_box_get_x(&boxActorClose));
+ right=MAX(left, right);
+ bottom=MAX(top, bottom);
+ bottom=MAX(bottom, clutter_actor_box_get_y(&boxActorClose)+clutter_actor_box_get_height(&boxActorClose));
- boxActorTitle=clutter_actor_box_new(floor(left), floor(top), floor(right), floor(bottom));
- clutter_actor_allocate(priv->actorTitle, boxActorTitle, inFlags);
+ clutter_actor_box_init(&boxActorWindowNumber, floor(left), floor(top), floor(right), floor(bottom));
+ clutter_actor_allocate(priv->actorWindowNumber, &boxActorWindowNumber, inFlags);
- /* Release allocated resources */
- if(boxActorControlLayer) clutter_actor_box_free(boxActorControlLayer);
- if(boxActorWindowNumber) clutter_actor_box_free(boxActorWindowNumber);
- if(boxActorTitle) clutter_actor_box_free(boxActorTitle);
- if(boxActorClose) clutter_actor_box_free(boxActorClose);
+ /* Set allocation on title actor
+ * But prevent that title overlaps close button
+ */
+ if(priv->windowNumber>0) referedBoxActor=&boxActorWindowNumber;
+ else referedBoxActor=&boxActorClose;
+
+ clutter_actor_get_preferred_size(priv->actorTitle, NULL, NULL, &titleWidth, &titleHeight);
+
+ maxWidth=clutter_actor_box_get_width(&boxActorLayer)-(2*priv->paddingTitle);
+ if(titleWidth>maxWidth) titleWidth=maxWidth;
+
+ left=clutter_actor_box_get_x(&boxActorLayer)+((clutter_actor_box_get_width(&boxActorLayer)-titleWidth)/2.0f);
+ right=left+titleWidth;
+ bottom=clutter_actor_box_get_y(&boxActorLayer)+clutter_actor_box_get_height(&boxActorLayer)-(2*priv->paddingTitle);
+ top=bottom-titleHeight;
+ if(left>right) left=right-1.0f;
+ if(top<(clutter_actor_box_get_y(referedBoxActor)+clutter_actor_box_get_height(referedBoxActor)))
+ {
+ if(right>=clutter_actor_box_get_x(referedBoxActor))
+ {
+ right=clutter_actor_box_get_x(referedBoxActor)-MIN(priv->paddingTitle, priv->paddingClose);
+ }
+
+ if(top<clutter_actor_box_get_y(referedBoxActor))
+ {
+ top=clutter_actor_box_get_y(referedBoxActor);
+ bottom=top+titleHeight;
+ }
+ }
+
+ right=MAX(left, right);
+ bottom=MAX(top, bottom);
+
+ clutter_actor_box_init(&boxActorTitle, floor(left), floor(top), floor(right), floor(bottom));
+ clutter_actor_allocate(priv->actorTitle, &boxActorTitle, inFlags);
+ }
}
/* IMPLEMENTATION: GObject */
@@ -555,6 +915,12 @@ static void _xfdashboard_live_window_dispose(GObject *inObject)
priv->actorControlLayer=NULL;
}
+ if(priv->actorSubwindowsLayer)
+ {
+ clutter_actor_destroy(priv->actorSubwindowsLayer);
+ priv->actorSubwindowsLayer=NULL;
+ }
+
/* Call parent's class dispose method */
G_OBJECT_CLASS(xfdashboard_live_window_parent_class)->dispose(inObject);
}
@@ -710,8 +1076,18 @@ static void xfdashboard_live_window_init(XfdashboardLiveWindow *self)
priv->paddingTitle=0.0f;
priv->paddingClose=0.0f;
+ /* Set up container for sub-windows and add it before the container for controls
+ * to keep the controls on top.
+ */
+ priv->actorSubwindowsLayer=xfdashboard_actor_new();
+ xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->actorSubwindowsLayer), "subwindows-layer");
+ clutter_actor_set_reactive(priv->actorSubwindowsLayer, FALSE);
+ clutter_actor_show(priv->actorSubwindowsLayer);
+ clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorSubwindowsLayer);
+
/* Set up container for controls and add child actors (order is important) */
priv->actorControlLayer=xfdashboard_actor_new();
+ xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->actorControlLayer), "controls-layer");
clutter_actor_set_reactive(priv->actorControlLayer, FALSE);
clutter_actor_show(priv->actorControlLayer);
clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorControlLayer);
@@ -743,6 +1119,8 @@ static void xfdashboard_live_window_init(XfdashboardLiveWindow *self)
g_signal_connect_swapped(priv->windowTracker, "window-actions-changed", G_CALLBACK(_xfdashboard_live_window_on_actions_changed), self);
g_signal_connect_swapped(priv->windowTracker, "window-icon-changed", G_CALLBACK(_xfdashboard_live_window_on_icon_changed), self);
g_signal_connect_swapped(priv->windowTracker, "window-name-changed", G_CALLBACK(_xfdashboard_live_window_on_name_changed), self);
+ g_signal_connect_swapped(priv->windowTracker, "window-opened", G_CALLBACK(_xfdashboard_live_window_on_subwindow_opened), self);
+ g_signal_connect_swapped(priv->windowTracker, "window-workspace-changed", G_CALLBACK(_xfdashboard_live_window_on_subwindow_workspace_changed), self);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the Xfce4-commits
mailing list