add anotehr stacking_add function.
authorDana Jansens <danakj@orodu.net>
Fri, 16 May 2003 15:16:33 +0000 (15:16 +0000)
committerDana Jansens <danakj@orodu.net>
Fri, 16 May 2003 15:16:33 +0000 (15:16 +0000)
make stacking_add take care of raising also.
make new windows that dont get focus also not raise above the focused window.

openbox/client.c
openbox/menu.c
openbox/moveresize.c
openbox/popup.c
openbox/slit.c
openbox/stacking.c
openbox/stacking.h

index 0a2fd29..828b158 100644 (file)
@@ -178,6 +178,7 @@ void client_manage(Window window)
     XWindowAttributes attrib;
     XSetWindowAttributes attrib_set;
     XWMHints *wmhint;
+    gboolean activate = FALSE;
 
     grab_server(TRUE);
 
@@ -241,30 +242,18 @@ void client_manage(Window window)
     client_apply_startup_state(self);
 
     grab_server(FALSE);
-     
+
+    /* add to client list/map */
     client_list = g_list_append(client_list, self);
-    stacking_add(self);
-    g_assert(!g_hash_table_lookup(client_map, &self->window));
     g_hash_table_insert(client_map, &self->window, self);
 
     /* update the focus lists */
     focus_order_add_new(self);
 
-    stacking_raise(CLIENT_AS_WINDOW(self));
-
-    screen_update_struts();
-
-    dispatch_client(Event_Client_New, self, 0, 0);
-
-    client_showhide(self);
-
     /* focus the new window? */
-    if (ob_state != State_Starting) {
-        Client *parent;
+    if (ob_state != State_Starting && config_focus_new) {
         gboolean group_foc = FALSE;
         
-        parent = NULL;
-
         if (self->group) {
             GSList *it;
 
@@ -274,39 +263,42 @@ void client_manage(Window window)
                     break;
                 }
         }
-        if (!group_foc && self->transient_for) {
-            if (self->transient_for != TRAN_GROUP) {/* transient of a window */
-                parent = self->transient_for;
-            } else { /* transient of a group */
-                GSList *it;
-
-                for (it = self->group->members; it; it = it->next)
-                    if (it->data != self &&
-                        ((Client*)it->data)->transient_for != TRAN_GROUP)
-                        parent = it->data;
-            }
-        }
-        /* note the check against Type_Normal, not client_normal(self), which
-           would also include dialog types. in this case we want more strict
-           rules for focus */
-        if ((config_focus_new &&
-             (self->type == Type_Normal ||
+        /* note the check against Type_Normal/Dialog, not client_normal(self),
+           which would also include other types. in this case we want more
+           strict rules for focus */
+        if (((self->type == Type_Normal ||
               (self->type == Type_Dialog &&
                (group_foc ||
-                (!parent && (!self->group ||
-                             !self->group->members->next)))))) ||
-            (parent && (client_focused(parent) ||
-                        client_search_focus_tree(parent)))) {
-            client_focus(self);
+                (!self->transient_for && (!self->group ||
+                                          !self->group->members->next)))))) ||
+            client_search_focus_tree_full(self) ||
+            !focus_client ||
+            !client_normal(focus_client)) {
+            /* activate the window */
+            stacking_add(CLIENT_AS_WINDOW(self));
+            activate = TRUE;
+        } else {
+            /* try to not get in the way */
+            stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
         }
+    } else {
+        stacking_add(CLIENT_AS_WINDOW(self));
     }
 
-    /* update the list hints */
-    client_set_list();
+    screen_update_struts();
 
     /* make sure the window is visible */
     client_move_onscreen(self);
 
+    dispatch_client(Event_Client_New, self, 0, 0);
+
+    client_showhide(self);
+
+    if (activate) client_activate(self);
+
+    /* update the list hints */
+    client_set_list();
+
     dispatch_client(Event_Client_Mapped, self, 0, 0);
 
     g_message("Managed window 0x%lx", window);
index 425a753..17f96b4 100644 (file)
@@ -200,7 +200,7 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
     g_hash_table_insert(menu_map, &self->items, self);
     g_hash_table_insert(menu_hash, g_strdup(name), self);
 
-    stacking_add(self);
+    stacking_add(MENU_AS_WINDOW(self));
     stacking_raise(MENU_AS_WINDOW(self));
 
     return self;
index 9a1b431..871e965 100644 (file)
@@ -55,7 +55,7 @@ void moveresize_startup()
     opaque_window.win = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
                                       render_depth, InputOutput, render_visual,
                                       CWSaveUnder, &attrib);
-    stacking_add(&opaque_window);
+    stacking_add(INTERNAL_AS_WINDOW(&opaque_window));
     stacking_raise(INTERNAL_AS_WINDOW(&opaque_window));
 
     /* a GC to invert stuff */
index 17462d3..efde075 100644 (file)
@@ -34,7 +34,7 @@ Popup *popup_new(gboolean hasicon)
     self->gravity = NorthWestGravity;
     self->x = self->y = self->w = self->h = 0;
     self->mapped = FALSE;
-    stacking_add(self);
+    stacking_add(INTERNAL_AS_WINDOW(self));
     stacking_raise(INTERNAL_AS_WINDOW(self));
     return self;
 }
index 311cd6a..81f0b89 100644 (file)
@@ -48,7 +48,7 @@ void slit_startup()
         XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
 
         g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]);
-        stacking_add(&slit[i]);
+        stacking_add(SLIT_AS_WINDOW(&slit[i]));
         stacking_raise(SLIT_AS_WINDOW(&slit[i]));
     }
 }
index 0dda3a0..eac4025 100644 (file)
@@ -113,9 +113,10 @@ void stacking_raise(ObWindow *window)
     if (WINDOW_IS_CLIENT(window)) {
         Client *client = WINDOW_AS_CLIENT(window);
         /* move up the transient chain as far as possible first */
-        while (client->transient_for) {
+        if (client->transient_for) {
             if (client->transient_for != TRAN_GROUP) {
-                client = client->transient_for;
+                stacking_raise(CLIENT_AS_WINDOW(client->transient_for));
+                return;
             } else {
                 GSList *it;
 
@@ -125,15 +126,12 @@ void stacking_raise(ObWindow *window)
                 for (it = client->group->members; it; it = it->next) {
                     Client *c = it->data;
 
-                    if (c != client && c->transient_for != TRAN_GROUP) {
-                        client = it->data;
-                        break;
-                    }
+                    if (c != client && c->transient_for != TRAN_GROUP)
+                        stacking_raise(it->data);
                 }
-                if (it == NULL) break;
+                if (it == NULL) return;
             }
         }
-        window = CLIENT_AS_WINDOW(client);
     }
 
     raise_recursive(window);
@@ -180,7 +178,8 @@ void stacking_lower(ObWindow *window)
         /* move up the transient chain as far as possible first */
         while (client->transient_for) {
             if (client->transient_for != TRAN_GROUP) {
-                client = client->transient_for;
+                stacking_lower(CLIENT_AS_WINDOW(client->transient_for));
+                return;
             } else {
                 GSList *it;
 
@@ -190,12 +189,10 @@ void stacking_lower(ObWindow *window)
                 for (it = client->group->members; it; it = it->next) {
                     Client *c = it->data;
 
-                    if (c != client && c->transient_for != TRAN_GROUP) {
-                        client = it->data;
-                        break;
-                    }
+                    if (c != client && c->transient_for != TRAN_GROUP)
+                        stacking_lower(it->data);
                 }
-                if (it == NULL) break;
+                if (it == NULL) return;
             }
         }
         window = CLIENT_AS_WINDOW(client);
@@ -205,3 +202,67 @@ void stacking_lower(ObWindow *window)
 
     stacking_set_list();
 }
+
+void stacking_add(ObWindow *win)
+{
+    stacking_list = g_list_append(stacking_list, win);
+    stacking_raise(win);
+}
+
+void stacking_add_nonintrusive(ObWindow *win)
+{
+    Window wins[2];  /* only ever restack 2 windows. */
+
+    if (!WINDOW_IS_CLIENT(win))
+        stacking_add(win); /* no special rules for others */
+    else {
+        Client *client = WINDOW_AS_CLIENT(win);
+        Client *parent = NULL;
+        GList *it_before = NULL;
+
+        /* insert above its highest parent */
+        if (client->transient_for) {
+            if (client->transient_for != TRAN_GROUP) {
+                parent = client->transient_for;
+            } else {
+                GSList *sit;
+                GList *it;
+
+                /* the check for TRAN_GROUP is to prevent an infinate loop with
+                   2 transients of the same group at the head of the group's
+                   members list */
+                for (it = stacking_list; !parent && it; it = it->next) {
+                    for (sit = client->group->members; !parent && sit;
+                         sit = sit->next) {
+                        Client *c = sit->data;
+                        if (sit->data == it->data &&
+                            c->transient_for != TRAN_GROUP)
+                            parent = it->data;
+                    }
+                }
+            }
+        }
+
+        if (!(it_before = g_list_find(stacking_list, parent))) {
+            /* no parent to put above, try find the focused client to go
+               under */
+            if ((it_before = g_list_find(stacking_list, focus_client)))
+                it_before = it_before->next;
+            else {
+                /* out of ideas, just add it normally... */
+                stacking_add(win);
+                return;
+            }
+        }
+        stacking_list = g_list_insert_before(stacking_list, it_before, win);
+
+        it_before = g_list_find(stacking_list, win)->prev;
+        if (!it_before)
+            wins[0] = focus_backup;
+        else
+            wins[0] = window_top(it_before->data);
+        wins[1] = window_top(win);
+
+        XRestackWindows(ob_display, wins, 2);
+    }
+}
index 118cc5c..d27e8c0 100644 (file)
@@ -24,7 +24,8 @@ extern GList  *stacking_list;
   stacking_list */
 void stacking_set_list();
 
-#define stacking_add(win) stacking_list = g_list_append(stacking_list, win);
+void stacking_add(ObWindow *win);
+void stacking_add_nonintrusive(ObWindow *win);
 #define stacking_remove(win) stacking_list = g_list_remove(stacking_list, win);
 
 /*! Raises a window above all others in its stacking layer