merge r6020-6025 from trunk
authorDana Jansens <danakj@orodu.net>
Fri, 4 May 2007 04:29:06 +0000 (04:29 +0000)
committerDana Jansens <danakj@orodu.net>
Fri, 4 May 2007 04:29:06 +0000 (04:29 +0000)
openbox/client.c
openbox/stacking.c

index df0102c7a726403128b629108aebca99422d7b13..c3c59f0a61283d15ef451043e4ede7a1cfbf1544 100644 (file)
@@ -277,7 +277,7 @@ void client_manage(Window window)
     self->wmstate = WithdrawnState; /* make sure it gets updated first time */
     self->layer = -1;
     self->desktop = screen_num_desktops; /* always an invalid value */
-    self->user_time = CurrentTime;
+    self->user_time = focus_client ? focus_client->user_time : CurrentTime;
 
     client_get_all(self);
     /* per-app settings override stuff, and return the settings for other
@@ -915,7 +915,10 @@ static void client_get_all(ObClient *self)
     /* The transient hint is used to pick a type, but the type can also affect
        transiency (dialogs are always made transients of their group if they
        have one). This is Havoc's idea, but it is needed to make some apps
-       work right (eg tsclient). */
+       work right (eg tsclient).
+       I also have made non-application type windows be transients based on
+       their type, like dialogs.
+    */
     client_update_transient_for(self);
     client_get_type(self);/* this can change the mwmhints for special cases */
     client_get_state(self);
@@ -1201,18 +1204,6 @@ void client_update_transient_for(ObClient *self)
                                   c->transient_for != OB_TRAN_GROUP))
                     c->transients = g_slist_append(c->transients, self);
             }
-
-            /* remove all transients which are in the group, that causes
-               circlular pointer hell of doom */
-            for (it = self->group->members; it; it = g_slist_next(it)) {
-                GSList *sit, *next;
-                for (sit = self->transients; sit; sit = next) {
-                    next = g_slist_next(sit);
-                    if (sit->data == it->data)
-                        self->transients =
-                            g_slist_delete_link(self->transients, sit);
-                }
-            }
         } else if (self->transient_for != NULL) { /* transient of window */
             /* add to new parent */
             self->transient_for->transients =
@@ -1655,7 +1646,8 @@ void client_update_wmhints(ObClient *self)
                     {
                         ObClient *c = it->data;
 
-                        if (c != self && !c->transient_for)
+                        if (c != self && (!c->transient_for ||
+                                          c->transient_for != OB_TRAN_GROUP))
                             c->transients = g_slist_remove(c->transients,
                                                            self);
                     }
@@ -1664,12 +1656,23 @@ void client_update_wmhints(ObClient *self)
                 group_remove(self->group, self);
                 self->group = NULL;
             }
+
+            /* because the self->transient flag wont change from this call,
+               we don't need to update the window's type and such, only its
+               transient_for, and the transients lists of other windows in
+               the group may be affected
+
+               do this before adding transients from the group so we know if
+               we are actually transient for the group or not.
+            */
+            client_update_transient_for(self);
+
             if (hints->window_group != None) {
                 self->group = group_add(hints->window_group, self);
 
                 /* i can only have transients from the group if i am not
-                   transient myself */
-                if (!self->transient_for) {
+                   transient for the group myself */
+                if (self->transient_for != OB_TRAN_GROUP) {
                     /* add other transients of the group that are already
                        set up */
                     for (it = self->group->members; it;
@@ -1682,12 +1685,6 @@ void client_update_wmhints(ObClient *self)
                     }
                 }
             }
-
-            /* because the self->transient flag wont change from this call,
-               we don't need to update the window's type and such, only its
-               transient_for, and the transients lists of other windows in
-               the group may be affected */
-            client_update_transient_for(self);
         }
 
         /* the WM_HINTS can contain an icon */
index 32d5a0fcf589812f1b6d7adf58a928b805058ea5..26726c7b4aa2c3ab138a51546b3cf36373ab19fc 100644 (file)
@@ -366,10 +366,44 @@ void stacking_add(ObWindow *win)
     stacking_raise(win);
 }
 
+static GList *find_highest_relative(ObClient *client)
+{    
+    GList *ret = NULL;
+
+    if (client->transient_for) {
+        GList *it;
+        GSList *top;
+
+        /* get all top level relatives of this client */
+        top = client_search_all_top_parents(client);
+
+        /* go from the top of the stacking order down */
+        for (it = stacking_list; !ret && it; it = g_list_next(it)) {
+            if (WINDOW_IS_CLIENT(it->data)) {
+                ObClient *c = it->data;
+                /* only look at windows in the same layer */
+                if (c->layer == client->layer) {
+                    GSList *sit;
+
+                    /* go through each top level parent and see it this window
+                       is related to them */
+                    for (sit = top; !ret && sit; sit = g_slist_next(sit)) {
+                        ObClient *topc = sit->data;
+
+                        /* are they related ? */
+                        if (topc == c || client_search_transient(topc, c))
+                            ret = it;
+                    }
+                }
+            }
+        }
+    }
+    return ret;
+}
+
 void stacking_add_nonintrusive(ObWindow *win)
 {
     ObClient *client;
-    ObClient *parent = NULL;
     GList *it_below = NULL;
 
     if (!WINDOW_IS_CLIENT(win)) {
@@ -379,33 +413,12 @@ void stacking_add_nonintrusive(ObWindow *win)
 
     client = WINDOW_AS_CLIENT(win);
 
-    /* insert above its highest parent */
-    if (client->transient_for) {
-        if (client->transient_for != OB_TRAN_GROUP) {
-            parent = client->transient_for;
-        } else {
-            GSList *sit;
-            GList *it;
-
-            if (client->group)
-                for (it = stacking_list; !parent && it; it = g_list_next(it)) {
-                    if ((sit = g_slist_find(client->group->members, it->data)))
-                        for (sit = client->group->members; !parent && sit;
-                             sit = g_slist_next(sit))
-                        {
-                            ObClient *c = sit->data;
-                            /* checking transient_for prevents infinate loops!
-                             */
-                            if (sit->data == it->data && !c->transient_for)
-                                parent = it->data;
-                        }
-                }
-        }
-    }
+    /* insert above its highest parent (or its highest child !) */
+    it_below = find_highest_relative(client);
 
-    if (!(it_below = g_list_find(stacking_list, parent))) {
-        /* no parent to put above, try find the focused client to go
-           under */
+    if (!it_below) {
+        /* nothing to put it directly above, so try find the focused client to
+           put it underneath it */
         if (focus_client && focus_client->layer == client->layer) {
             if ((it_below = g_list_find(stacking_list, focus_client)))
                 it_below = it_below->next;