[Xfce4-commits] [xfce/xfwm4] 02/02: stacking: Raise all transients together

noreply at xfce.org noreply at xfce.org
Fri Apr 19 23:30:26 CEST 2019


This is an automated email from the git hooks/post-receive script.

o   l   i   v   i   e   r       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository xfce/xfwm4.

commit fa9517eae823e35d0c85276b2d0c31beede5022f
Author: Olivier Fourdan <fourdan at xfce.org>
Date:   Fri Apr 19 23:16:40 2019 +0200

    stacking: Raise all transients together
    
    Bug 15303
    
    Xfwm4 would raise the transients of a given window along with the parent
    window, to keep the transients above their parents, but would not raise
    the parents along with the transient windows.
    
    Rework the stacking code to raise the deepest parent of a transient
    being raised so that all parents window of a transient get raised along
    with it.
---
 src/client.c     |   8 +-
 src/stacking.c   | 373 +++++++++++++++++++++++++++++--------------------------
 src/transients.c |  68 ++++++----
 3 files changed, 241 insertions(+), 208 deletions(-)

diff --git a/src/client.c b/src/client.c
index ef043c1..ed0cbad 100644
--- a/src/client.c
+++ b/src/client.c
@@ -2597,12 +2597,10 @@ clientActivate (Client *c, guint32 timestamp, gboolean source_is_application)
                 workspaceSwitch (screen_info, c->win_workspace, NULL, FALSE, timestamp);
             }
         }
+
         clientShow (ancestor, TRUE);
-        if (c != ancestor || !screen_info->params->click_to_focus)
-        {
-            clientRaise (ancestor, None);
-            clientSetLastRaise (c);
-        }
+        clientRaise (c, None);
+
         if (!source_is_application || screen_info->params->click_to_focus || (c->type & WINDOW_TYPE_DONT_FOCUS))
         {
             /*
diff --git a/src/stacking.c b/src/stacking.c
index 2239ac7..185127a 100644
--- a/src/stacking.c
+++ b/src/stacking.c
@@ -164,7 +164,7 @@ gboolean
 clientIsTopMost (Client *c)
 {
     ScreenInfo *screen_info;
-    GList *list, *list2;
+    GList *list, *l2;
     Client *c2;
 
     g_return_val_if_fail (c != NULL, FALSE);
@@ -176,15 +176,15 @@ clientIsTopMost (Client *c)
     list = g_list_find (screen_info->windows_stack, (gconstpointer) c);
     if (list)
     {
-        list2 = g_list_next (list);
-        while (list2)
+        l2 = g_list_next (list);
+        while (l2)
         {
-            c2 = (Client *) list2->data;
+            c2 = (Client *) l2->data;
             if (FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_VISIBLE) && (c2->win_layer == c->win_layer))
             {
                 return FALSE;
             }
-            list2 = g_list_next (list2);
+            l2 = g_list_next (l2);
         }
     }
     return TRUE;
@@ -279,163 +279,179 @@ clientAtPosition (ScreenInfo *screen_info, int x, int y, GList * exclude_list)
     return c;
 }
 
-void
-clientRaise (Client * c, Window wsibling)
+static void
+clientRaiseInternal (Client * c, Client * client_sibling)
 {
     ScreenInfo *screen_info;
-    DisplayInfo *display_info;
-    Client *c2, *c3, *client_sibling;
+    Client *c2, *c3;
+    GList *l1, *l2;
     GList *transients;
-    GList *sibling;
-    GList *list1, *list2;
     GList *windows_stack_copy;
-
-    g_return_if_fail (c != NULL);
-
-    TRACE ("client \"%s\" (0x%lx) above (0x%lx)", c->name, c->window, wsibling);
+    GList *sibling;
 
     screen_info = c->screen_info;
-    display_info = screen_info->display_info;
-    client_sibling = NULL;
     transients = NULL;
+
+    /* Copy the existing window stack temporarily as reference */
+    windows_stack_copy = g_list_copy (screen_info->windows_stack);
+    screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c);
     sibling = NULL;
 
-    if (c == screen_info->last_raise)
+    if (client_sibling)
     {
-        TRACE ("client \"%s\" (0x%lx) already raised", c->name, c->window);
-        return;
+        /* If there is one, look for its place in the list */
+        sibling = g_list_find (screen_info->windows_stack, (gconstpointer) client_sibling);
+        /* Place the raised window just before it */
+        screen_info->windows_stack = g_list_insert_before (screen_info->windows_stack, sibling, c);
     }
-
-    /*
-     * If the raised window is the one that has focus, fine, we can
-     * release the grab we have on it since there is no use for it
-     * anymore.
-     *
-     * However, if the raised window is not the focused one, then we
-     * end up with some kind of indermination, so we need to regrab
-     * the buttons for the user to be able to raise or focus the window
-     * by clicking inside.
-     */
-
-    if (g_list_length (screen_info->windows_stack) < 1)
+    else
     {
-        return;
+        /* There will be no window on top of the raised window, so place it at the end of list */
+        screen_info->windows_stack = g_list_append (screen_info->windows_stack, c);
     }
-
-    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
+    /* Now, look for transients, transients of transients, etc. */
+    for (l1 = windows_stack_copy; l1; l1 = g_list_next (l1))
     {
-        /* Copy the existing window stack temporarily as reference */
-        windows_stack_copy = g_list_copy (screen_info->windows_stack);
-        /* Search for the window that will be just on top of the raised window  */
-        if (wsibling)
+        c2 = (Client *) l1->data;
+        if (c2)
         {
-            c2 = myDisplayGetClientFromWindow (display_info, wsibling, SEARCH_FRAME | SEARCH_WINDOW);
-            if (c2)
+            if ((c2 != c) && clientIsTransientOrModalFor (c2, c) && (c2->win_layer <= c->win_layer))
             {
-                sibling = g_list_find (screen_info->windows_stack, (gconstpointer) c2);
+                transients = g_list_append (transients, c2);
                 if (sibling)
                 {
-                    list1 = g_list_next (sibling);
-                    if (list1)
+                    /* Make sure client_sibling is not c2 otherwise we create a circular linked list */
+                    if (client_sibling != c2)
                     {
-                        client_sibling = (Client *) list1->data;
-                        /* Do not place window under higher layers though */
-                        if ((client_sibling) && (client_sibling->win_layer < c->win_layer))
-                        {
-                            client_sibling = NULL;
-                        }
-                    }
-                }
-            }
-        }
-        if (!client_sibling)
-        {
-            client_sibling = clientGetNextTopMost (screen_info, c->win_layer, c);
-        }
-        screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c);
-        if (client_sibling)
-        {
-            /* If there is one, look for its place in the list */
-            sibling = g_list_find (screen_info->windows_stack, (gconstpointer) client_sibling);
-            /* Place the raised window just before it */
-            screen_info->windows_stack = g_list_insert_before (screen_info->windows_stack, sibling, c);
-        }
-        else
-        {
-            /* There will be no window on top of the raised window, so place it at the end of list */
-            screen_info->windows_stack = g_list_append (screen_info->windows_stack, c);
-        }
-        /* Now, look for transients, transients of transients, etc. */
-        for (list1 = windows_stack_copy; list1; list1 = g_list_next (list1))
-        {
-            c2 = (Client *) list1->data;
-            if (c2)
-            {
-                if ((c2 != c) && clientIsTransientOrModalFor (c2, c) && (c2->win_layer <= c->win_layer))
-                {
-                    transients = g_list_append (transients, c2);
-                    if (sibling)
-                    {
-                        /* Make sure client_sibling is not c2 otherwise we create a circular linked list */
-                        if (client_sibling != c2)
-                        {
-                            /* Place the transient window just before sibling */
-                            screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c2);
-                            screen_info->windows_stack = g_list_insert_before (screen_info->windows_stack, sibling, c2);
-                        }
-                    }
-                    else
-                    {
-                        /* There will be no window on top of the transient window, so place it at the end of list */
+                        /* Place the transient window just before sibling */
                         screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c2);
-                        screen_info->windows_stack = g_list_append (screen_info->windows_stack, c2);
+                        screen_info->windows_stack = g_list_insert_before (screen_info->windows_stack, sibling, c2);
                     }
                 }
                 else
                 {
-                    for (list2 = transients; list2; list2 = g_list_next (list2))
+                    /* There will be no window on top of the transient window, so place it at the end of list */
+                    screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c2);
+                    screen_info->windows_stack = g_list_append (screen_info->windows_stack, c2);
+                }
+            }
+            else
+            {
+                for (l2 = transients; l2; l2 = g_list_next (l2))
+                {
+                    c3 = (Client *) l2->data;
+                    if ((c3 != c2) && clientIsTransientOrModalFor (c2, c3))
                     {
-                        c3 = (Client *) list2->data;
-                        if ((c3 != c2) && clientIsTransientOrModalFor (c2, c3))
+                        transients = g_list_append (transients, c2);
+                        if (sibling)
                         {
-                            transients = g_list_append (transients, c2);
-                            if (sibling)
-                            {
-                                /* Again, make sure client_sibling is not c2 to avoid a circular linked list */
-                                if (client_sibling != c2)
-                                {
-                                    /* Place the transient window just before sibling */
-                                    screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c2);
-                                    screen_info->windows_stack = g_list_insert_before (screen_info->windows_stack, sibling, c2);
-                                }
-                            }
-                            else
+                            /* Again, make sure client_sibling is not c2 to avoid a circular linked list */
+                            if (client_sibling != c2)
                             {
-                                /* There will be no window on top of the transient window, so place it at the end of list */
+                                /* Place the transient window just before sibling */
                                 screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c2);
-                                screen_info->windows_stack = g_list_append (screen_info->windows_stack, c2);
+                                screen_info->windows_stack = g_list_insert_before (screen_info->windows_stack, sibling, c2);
                             }
-                            break;
                         }
+                        else
+                        {
+                            /* There will be no window on top of the transient window, so place it at the end of list */
+                            screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c2);
+                            screen_info->windows_stack = g_list_append (screen_info->windows_stack, c2);
+                        }
+                        break;
                     }
                 }
             }
         }
-        if (transients)
-        {
-            g_list_free (transients);
-        }
-        if (windows_stack_copy)
+    }
+
+    if (transients)
+    {
+        g_list_free (transients);
+    }
+
+    if (windows_stack_copy)
+    {
+        g_list_free (windows_stack_copy);
+    }
+}
+
+void
+clientRaise (Client * c, Window wsibling)
+{
+    ScreenInfo *screen_info;
+    DisplayInfo *display_info;
+    Client *ancestor;
+    Client *client_sibling;
+    Client *c2;
+    GList *sibling;
+    GList *above_sibling;
+
+    g_return_if_fail (c != NULL);
+
+    TRACE ("client \"%s\" (0x%lx) above (0x%lx)", c->name, c->window, wsibling);
+
+    if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
+    {
+        return;
+    }
+
+    screen_info = c->screen_info;
+    display_info = screen_info->display_info;
+
+    if (c == screen_info->last_raise)
+    {
+        TRACE ("client \"%s\" (0x%lx) already raised", c->name, c->window);
+        return;
+    }
+
+    if (g_list_length (screen_info->windows_stack) < 2)
+    {
+        return;
+    }
+
+    /* Search for the window that will be just on top of the raised window  */
+    if (wsibling)
+    {
+        c2 = myDisplayGetClientFromWindow (display_info, wsibling, SEARCH_FRAME | SEARCH_WINDOW);
+        if (c2)
         {
-            g_list_free (windows_stack_copy);
+            sibling = g_list_find (screen_info->windows_stack, (gconstpointer) c2);
+            if (sibling)
+            {
+                above_sibling = g_list_next (sibling);
+                if (above_sibling)
+                {
+                    client_sibling = (Client *) above_sibling->data;
+                    /* Do not place window under higher layers though */
+                    if ((client_sibling) && (client_sibling->win_layer < c->win_layer))
+                    {
+                        client_sibling = NULL;
+                    }
+                }
+            }
         }
-        /* Now, screen_info->windows_stack contains the correct window stack
-           We still need to tell the X Server to reflect the changes
-         */
-        clientApplyStackList (screen_info);
-        clientSetNetClientList (c->screen_info, display_info->atoms[NET_CLIENT_LIST_STACKING], screen_info->windows_stack);
-        screen_info->last_raise = c;
     }
+
+    if (!client_sibling)
+    {
+        client_sibling = clientGetNextTopMost (screen_info, c->win_layer, c);
+    }
+
+    ancestor = clientGetTransientFor(c);
+    clientRaiseInternal (ancestor, client_sibling);
+    if (ancestor != c)
+    {
+        clientRaiseInternal (c, client_sibling);
+    }
+
+    /* Now, screen_info->windows_stack contains the correct window stack
+       We still need to tell the X Server to reflect the changes
+     */
+    clientApplyStackList (screen_info);
+    clientSetNetClientList (screen_info, display_info->atoms[NET_CLIENT_LIST_STACKING], screen_info->windows_stack);
+    screen_info->last_raise = c;
 }
 
 void
@@ -452,82 +468,87 @@ clientLower (Client * c, Window wsibling)
 
     TRACE ("client \"%s\" (0x%lx) below (0x%lx)", c->name, c->window, wsibling);
 
+    if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
+    {
+        return;
+    }
+
     screen_info = c->screen_info;
     display_info = screen_info->display_info;
     client_sibling = NULL;
     sibling = NULL;
     c2 = NULL;
 
-    if (g_list_length (screen_info->windows_stack) < 1)
+    if (g_list_length (screen_info->windows_stack) < 2)
     {
         return;
     }
 
-    if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
+    if (clientIsTransientOrModalForGroup (c))
     {
-        if (clientIsTransientOrModalForGroup (c))
-        {
-            client_sibling = clientGetTopMostForGroup (c);
-        }
-        else if (clientIsTransient (c))
-        {
-            client_sibling = clientGetTransient (c);
-        }
-        else if (wsibling)
+        client_sibling = clientGetTopMostForGroup (c);
+    }
+    else if (clientIsTransient (c))
+    {
+        client_sibling = clientGetTransient (c);
+    }
+    else if (wsibling)
+    {
+        c2 = myDisplayGetClientFromWindow (display_info, wsibling, SEARCH_FRAME | SEARCH_WINDOW);
+        if (c2)
         {
-            c2 = myDisplayGetClientFromWindow (display_info, wsibling, SEARCH_FRAME | SEARCH_WINDOW);
-            if (c2)
+            sibling = g_list_find (screen_info->windows_stack, (gconstpointer) c2);
+            if (sibling)
             {
-                sibling = g_list_find (screen_info->windows_stack, (gconstpointer) c2);
-                if (sibling)
+                list = g_list_previous (sibling);
+                if (list)
                 {
-                    list = g_list_previous (sibling);
-                    if (list)
+                    client_sibling = (Client *) list->data;
+                    /* Do not place window above lower layers though */
+                    if ((client_sibling) && (client_sibling->win_layer > c->win_layer))
                     {
-                        client_sibling = (Client *) list->data;
-                        /* Do not place window above lower layers though */
-                        if ((client_sibling) && (client_sibling->win_layer > c->win_layer))
-                        {
-                            client_sibling = NULL;
-                        }
+                        client_sibling = NULL;
                     }
                 }
             }
         }
-        if ((!client_sibling) ||
-            (client_sibling && (client_sibling->win_layer < c->win_layer)))
-        {
-            client_sibling = clientGetBottomMost (screen_info, c->win_layer, c);
-        }
-        if (client_sibling != c)
+    }
+
+    if ((!client_sibling) ||
+        (client_sibling && (client_sibling->win_layer < c->win_layer)))
+    {
+        client_sibling = clientGetBottomMost (screen_info, c->win_layer, c);
+    }
+
+    if (client_sibling != c)
+    {
+        screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c);
+        /* Paranoid check to avoid circular linked list */
+        if (client_sibling)
         {
-            screen_info->windows_stack = g_list_remove (screen_info->windows_stack, (gconstpointer) c);
-            /* Paranoid check to avoid circular linked list */
-            if (client_sibling)
-            {
-                sibling = g_list_find (screen_info->windows_stack, (gconstpointer) client_sibling);
-                position = g_list_position (screen_info->windows_stack, sibling) + 1;
+            sibling = g_list_find (screen_info->windows_stack, (gconstpointer) client_sibling);
+            position = g_list_position (screen_info->windows_stack, sibling) + 1;
 
-                screen_info->windows_stack = g_list_insert (screen_info->windows_stack, c, position);
-                TRACE ("lowest client is \"%s\" (0x%lx) at position %i",
-                        client_sibling->name, client_sibling->window, position);
-            }
-            else
-            {
-                screen_info->windows_stack = g_list_prepend (screen_info->windows_stack, c);
-            }
+            screen_info->windows_stack = g_list_insert (screen_info->windows_stack, c, position);
+            TRACE ("lowest client is \"%s\" (0x%lx) at position %i",
+                    client_sibling->name, client_sibling->window, position);
         }
-        /* Now, screen_info->windows_stack contains the correct window stack
-           We still need to tell the X Server to reflect the changes
-         */
-        clientApplyStackList (screen_info);
-        clientSetNetClientList (screen_info, display_info->atoms[NET_CLIENT_LIST_STACKING], screen_info->windows_stack);
-        clientPassFocus (screen_info, c, NULL);
-        if (screen_info->last_raise == c)
+        else
         {
-            screen_info->last_raise = NULL;
+            screen_info->windows_stack = g_list_prepend (screen_info->windows_stack, c);
         }
     }
+
+    /* Now, screen_info->windows_stack contains the correct window stack
+       We still need to tell the X Server to reflect the changes
+     */
+    clientApplyStackList (screen_info);
+    clientSetNetClientList (screen_info, display_info->atoms[NET_CLIENT_LIST_STACKING], screen_info->windows_stack);
+    clientPassFocus (screen_info, c, NULL);
+    if (screen_info->last_raise == c)
+    {
+        screen_info->last_raise = NULL;
+    }
 }
 
 gboolean
diff --git a/src/transients.c b/src/transients.c
index 5e1844e..48cd7c2 100644
--- a/src/transients.c
+++ b/src/transients.c
@@ -315,36 +315,52 @@ clientGetModalFor (Client * c)
     return NULL;
 }
 
+/* Find the deepest parent of that window */
 Client *
 clientGetTransientFor (Client * c)
 {
     ScreenInfo *screen_info;
-    Client *latest_transient;
+    Client *first_parent;
     Client *c2;
-    GList *list;
+    GList *l1, *l2;
+    GList *parents;
 
     g_return_val_if_fail (c != NULL, NULL);
     TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
 
-    latest_transient = c;
+    first_parent = c;
+    parents = g_list_append (NULL, c);
+
     screen_info = c->screen_info;
-    for (list = g_list_last(screen_info->windows_stack); list; list = g_list_previous (list))
+    for (l1 = g_list_last(screen_info->windows_stack); l1; l1 = g_list_previous (l1))
     {
-        if (!clientIsTransient (latest_transient))
+        Client *c2 = (Client *) l1->data;
+        if (c2 == c)
         {
-            break;
+            continue;
         }
-        c2 = (Client *) list->data;
-        if (c2)
+
+        if (clientIsTransientFor (c, c2))
         {
-            if (clientIsTransientFor (latest_transient, c2))
+            parents = g_list_append (parents, c2);
+            first_parent = c2;
+        }
+        else
+        {
+            for (l2 = parents; l2; l2 = g_list_next (l2))
             {
-                latest_transient = c2;
+                Client *c3 = (Client *) l2->data;
+                if ((c3 != c2) && clientIsTransientFor (c3, c2))
+                {
+                    parents = g_list_append (parents, c2);
+                    first_parent = c2;
+                }
             }
         }
     }
+    g_list_free (parents);
 
-    return latest_transient;
+    return first_parent;
 }
 
 /* Build a GList of clients that have a transient relationship */
@@ -354,17 +370,17 @@ clientListTransient (Client * c)
     ScreenInfo *screen_info;
     Client *c2, *c3;
     GList *transients;
-    GList *list1, *list2;
+    GList *l1, *l2;
 
     g_return_val_if_fail (c != NULL, NULL);
     TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
 
-    transients = NULL;
+    transients = g_list_append (NULL, c);
+
     screen_info = c->screen_info;
-    transients = g_list_append (transients, c);
-    for (list1 = screen_info->windows_stack; list1; list1 = g_list_next (list1))
+    for (l1 = screen_info->windows_stack; l1; l1 = g_list_next (l1))
     {
-        c2 = (Client *) list1->data;
+        c2 = (Client *) l1->data;
         if (c2 != c)
         {
             if (clientIsTransientFor (c2, c))
@@ -373,10 +389,9 @@ clientListTransient (Client * c)
             }
             else
             {
-                for (list2 = transients; list2;
-                    list2 = g_list_next (list2))
+                for (l2 = transients; l2; l2 = g_list_next (l2))
                 {
-                    c3 = (Client *) list2->data;
+                    c3 = (Client *) l2->data;
                     if ((c3 != c2) && clientIsTransientFor (c2, c3))
                     {
                         transients = g_list_append (transients, c2);
@@ -396,17 +411,17 @@ clientListTransientOrModal (Client * c)
     ScreenInfo *screen_info;
     Client *c2, *c3;
     GList *transients;
-    GList *list1, *list2;
+    GList *l1, *l2;
 
     g_return_val_if_fail (c != NULL, NULL);
     TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
 
+    transients = g_list_append (NULL, c);
+
     screen_info = c->screen_info;
-    transients = NULL;
-    transients = g_list_append (transients, c);
-    for (list1 = screen_info->windows_stack; list1; list1 = g_list_next (list1))
+    for (l1 = screen_info->windows_stack; l1; l1 = g_list_next (l1))
     {
-        c2 = (Client *) list1->data;
+        c2 = (Client *) l1->data;
         if (c2 != c)
         {
             if (clientIsTransientOrModalFor (c2, c))
@@ -415,10 +430,9 @@ clientListTransientOrModal (Client * c)
             }
             else
             {
-                for (list2 = transients; list2;
-                    list2 = g_list_next (list2))
+                for (l2 = transients; l2; l2 = g_list_next (l2))
                 {
-                    c3 = (Client *) list2->data;
+                    c3 = (Client *) l2->data;
                     if ((c3 != c2) && clientIsTransientOrModalFor (c2, c3))
                     {
                         transients = g_list_append (transients, c2);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list