make fullscreen windows more xinerama and multi-screen aware
authorDana Jansens <danakj@orodu.net>
Sat, 2 Feb 2008 14:01:56 +0000 (09:01 -0500)
committerDana Jansens <danakj@orodu.net>
Sat, 2 Feb 2008 14:03:13 +0000 (09:03 -0500)
instead of calling it every time a window loses focus, it is only called when a window gains focus.  then, check fullscreen layered windows, if they should be moved to a lower layer.
when moving a window between monitors, also check its layer and that of any fullscreen windows.
let a window stay in the fullscreen layer even when it is not focused, if it is on a non-visible desktop, or if it is on a different monitor from the focused window, or if nothing else is focused

openbox/client.c
openbox/client.h
openbox/event.c

index a0ba343..e7290ca 100644 (file)
@@ -2471,7 +2471,15 @@ static ObStackingLayer calc_layer(ObClient *self)
               (self->decorations == 0 &&
                !(self->max_horz && self->max_vert) &&
                RECT_EQUAL(self->area, *monitor))) &&
-             (client_focused(self) || client_search_focus_tree(self)))
+             /* you are fullscreen while you or your children are focused.. */
+             (client_focused(self) || client_search_focus_tree(self) ||
+              /* you can be fullscreen if you're on another desktop */
+              (self->desktop != screen_desktop &&
+               self->desktop != DESKTOP_ALL) ||
+              /* and you can also be fullscreen if the focused client is on
+                 another monitor, or nothing else is focused */
+              (!focus_client ||
+               client_monitor(focus_client) != client_monitor(self))))
         l = OB_STACKING_LAYER_FULLSCREEN;
     else if (self->above) l = OB_STACKING_LAYER_ABOVE;
     else if (self->below) l = OB_STACKING_LAYER_BELOW;
@@ -2497,23 +2505,54 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig,
         stacking_add_nonintrusive(CLIENT_AS_WINDOW(self));
     }
 
+    /* we've been restacked */
+    self->visited = TRUE;
+
     for (it = self->transients; it; it = g_slist_next(it))
         client_calc_layer_recursive(it->data, orig,
                                     self->layer);
 }
 
+static void client_calc_layer_internal(ObClient *self)
+{
+    GSList *sit;
+
+    /* transients take on the layer of their parents */
+    sit = client_search_all_top_parents(self);
+
+    for (; sit; sit = g_slist_next(sit))
+        client_calc_layer_recursive(sit->data, self, 0);
+}
+
 void client_calc_layer(ObClient *self)
 {
-    ObClient *orig;
-    GSList *it;
+    GList *it;
 
-    orig = self;
+    /* skip over stuff above fullscreen layer */
+    for (it = stacking_list; it; it = g_list_next(it))
+        if (window_layer(it->data) <= OB_STACKING_LAYER_FULLSCREEN) break;
 
-    /* transients take on the layer of their parents */
-    it = client_search_all_top_parents(self);
+    /* find the windows in the fullscreen layer, and mark them not-visited */
+    for (; it; it = g_list_next(it)) {
+        if (window_layer(it->data) < OB_STACKING_LAYER_FULLSCREEN) break;
+        else if (WINDOW_IS_CLIENT(it->data))
+            WINDOW_AS_CLIENT(it->data)->visited = FALSE;
+    }
+
+    client_calc_layer_internal(self);
 
-    for (; it; it = g_slist_next(it))
-        client_calc_layer_recursive(it->data, orig, 0);
+    /* skip over stuff above fullscreen layer */
+    for (it = stacking_list; it; it = g_list_next(it))
+        if (window_layer(it->data) <= OB_STACKING_LAYER_FULLSCREEN) break;
+
+    /* now recalc any windows in the fullscreen layer which have not
+       had their layer recalced already */
+    for (; it; it = g_list_next(it)) {
+        if (window_layer(it->data) < OB_STACKING_LAYER_FULLSCREEN) break;
+        else if (WINDOW_IS_CLIENT(it->data) &&
+                 !WINDOW_AS_CLIENT(it->data)->visited)
+            client_calc_layer_internal(it->data);
+    }
 }
 
 gboolean client_should_show(ObClient *self)
@@ -2931,6 +2970,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
 void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
                       gboolean user, gboolean final, gboolean force_reply)
 {
+    Rect oldframe;
     gint oldw, oldh;
     gboolean send_resize_client;
     gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
@@ -2953,6 +2993,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
 
     oldw = self->area.width;
     oldh = self->area.height;
+    oldframe = self->frame->area;
     RECT_SET(self->area, x, y, w, h);
 
     /* for app-requested resizes, always resize if 'resized' is true.
@@ -3057,6 +3098,14 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
     }
 
     XFlush(ob_display);
+
+    /* if it moved between monitors, then this can affect the stacking
+       layer of this window or others - for fullscreen windows */
+    if (screen_find_monitor(&self->frame->area) !=
+        screen_find_monitor(&oldframe))
+    {
+        client_calc_layer(self);
+    }
 }
 
 void client_fullscreen(ObClient *self, gboolean fs)
index 0efeb19..84da49a 100644 (file)
@@ -304,6 +304,9 @@ struct _ObClient
 
     /*! Where the window should iconify to/from */
     Rect icon_geometry;
+
+    /*! A boolean used for algorithms which need to mark clients as visited */
+    gboolean visited;
 };
 
 extern GList      *client_list;
index 535e9f1..9362c80 100644 (file)
@@ -519,7 +519,6 @@ static void event_process(const XEvent *ec, gpointer data)
                window with RevertToParent focus */
             frame_adjust_focus(client->frame, FALSE);
             /* focus_set_client(NULL) has already been called */
-            client_calc_layer(client);
         }
         else if (e->xfocus.detail == NotifyPointerRoot ||
                  e->xfocus.detail == NotifyDetailNone ||
@@ -629,7 +628,6 @@ static void event_process(const XEvent *ec, gpointer data)
             frame_adjust_focus(client->frame, FALSE);
             /* focus_set_client(NULL) has already been called in this
                section or by focus_fallback */
-            client_calc_layer(client);
         }
     }
     else if (client)