- WINDOW_TYPE_DOCK are chosen first.
- Top/Bottom take precedence over Left/Right.
- Struts are automatically updated.
- Automatically avoid overlap with other struts or wibox'es.
---
 client.c               |  168 ++++++++++++++++++++++++++++++++++++++++++++++++
 client.h               |    1 +
 layout.c               |    2 +
 lib/awful/mouse.lua.in |   14 ----
 screen.c               |    2 +-
 structs.h              |    2 +
 wibox.c                |    3 +-
 7 files changed, 176 insertions(+), 16 deletions(-)

diff --git a/client.c b/client.c
index 439d9f7..423bb3a 100644
--- a/client.c
+++ b/client.c
@@ -779,6 +779,174 @@ client_resize(client_t *c, area_t geometry, bool hints)
     return false;
 }
 
+/** Update the position of all window with struts on a specific screen.
+ * \param screen The screen that should be processed.
+ */
+void
+client_update_strut_positions(int screen)
+{
+    client_t *c;
+    area_t allowed_area, geom;
+
+    /* Ignore all struts for starters. */
+    for(c = globalconf.clients; c; c = c->next) {
+        if (c->screen != screen || !client_hasstrut(c))
+            continue;
+
+        c->ignore_strut = true;
+    }
+
+    /* Rationale:
+     * Top and bottom panels are common, so they take precendence.
+     * WINDOW_TYPE_DOCK really wants to be at the side, so choose them first.
+     */
+
+    /* WINDOW_TYPE_DOCK: top + bottom. */
+    for(c = globalconf.clients; c; c = c->next) {
+        if(c->screen != screen || !client_hasstrut(c) || c->type != 
WINDOW_TYPE_DOCK)
+            continue;
+
+        /* Screen area, minus padding, wibox'es and already processed struts. 
*/
+        allowed_area = screen_area_get(c->screen,
+                        &globalconf.screens[c->screen].wiboxes,
+                        &globalconf.screens[c->screen].padding,
+                        true);
+
+        geom = c->geometry;
+
+        if(c->strut.top || c->strut.top_start_x || c->strut.top_end_x) {
+            geom.y = allowed_area.y;
+            if (geom.x < allowed_area.x ||
+                    geom.x + geom.width > allowed_area.x + allowed_area.width) 
{
+                geom.x = allowed_area.x;
+                if(geom.width > allowed_area.width)
+                    geom.width = allowed_area.width;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        } else if(c->strut.bottom || c->strut.bottom_start_x || 
c->strut.bottom_end_x) {
+            geom.y = allowed_area.y + allowed_area.height - geom.height;
+            if (geom.x < allowed_area.x || 
+                    geom.x + geom.width > allowed_area.x + allowed_area.width) 
{
+                geom.x = allowed_area.x;
+                if(geom.width > allowed_area.width)
+                    geom.width = allowed_area.width;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        }
+    }
+
+    /* WINDOW_TYPE_DOCK: left + right. */
+    for(c = globalconf.clients; c; c = c->next) {
+        if(c->screen != screen || !client_hasstrut(c) || c->type != 
WINDOW_TYPE_DOCK)
+            continue;
+
+        /* Screen area, minus padding, wibox'es and already processed struts. 
*/
+        allowed_area = screen_area_get(c->screen,
+                        &globalconf.screens[c->screen].wiboxes,
+                        &globalconf.screens[c->screen].padding,
+                        true);
+
+        geom = c->geometry;
+
+        if(c->strut.left || c->strut.left_start_y || c->strut.left_end_y) {
+            geom.x = allowed_area.x;
+            if (geom.y < allowed_area.y ||
+                    geom.y + geom.height > allowed_area.y + 
allowed_area.height) {
+                geom.y = allowed_area.y;
+                if (geom.height > allowed_area.height)
+                    geom.height = allowed_area.height;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        } else if(c->strut.right || c->strut.right_start_y || 
c->strut.right_end_y) {
+            geom.x = allowed_area.x + allowed_area.width - geom.width;
+            if (geom.y < allowed_area.y ||
+                    geom.y + geom.height > allowed_area.y + 
allowed_area.height) {
+                geom.y = allowed_area.y;
+                if (geom.height > allowed_area.height)
+                    geom.height = allowed_area.height;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        }
+    }
+
+    /* not WINDOW_TYPE_DOCK: top + bottom. */
+    for(c = globalconf.clients; c; c = c->next) {
+        if(c->screen != screen || !client_hasstrut(c) || c->type == 
WINDOW_TYPE_DOCK)
+            continue;
+
+        /* Screen area, minus padding, wibox'es and already processed struts. 
*/
+        allowed_area = screen_area_get(c->screen,
+                        &globalconf.screens[c->screen].wiboxes,
+                        &globalconf.screens[c->screen].padding,
+                        true);
+
+        geom = c->geometry;
+
+        if(c->strut.top || c->strut.top_start_x || c->strut.top_end_x) {
+            geom.y = allowed_area.y;
+            if (geom.x < allowed_area.x ||
+                    geom.x + geom.width > allowed_area.x + allowed_area.width) 
{
+                geom.x = allowed_area.x;
+                if(geom.width > allowed_area.width)
+                    geom.width = allowed_area.width;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        } else if(c->strut.bottom || c->strut.bottom_start_x || 
c->strut.bottom_end_x) {
+            geom.y = allowed_area.y + allowed_area.height - geom.height;
+            if (geom.x < allowed_area.x || 
+                    geom.x + geom.width > allowed_area.x + allowed_area.width) 
{
+                geom.x = allowed_area.x;
+                if(geom.width > allowed_area.width)
+                    geom.width = allowed_area.width;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        }
+    }
+
+    /* not WINDOW_TYPE_DOCK: left + right. */
+    for(c = globalconf.clients; c; c = c->next) {
+        if(c->screen != screen || !client_hasstrut(c) || c->type == 
WINDOW_TYPE_DOCK)
+            continue;
+
+        /* Screen area, minus padding, wibox'es and already processed struts. 
*/
+        allowed_area = screen_area_get(c->screen,
+                        &globalconf.screens[c->screen].wiboxes,
+                        &globalconf.screens[c->screen].padding,
+                        true);
+
+        geom = c->geometry;
+
+        if(c->strut.left || c->strut.left_start_y || c->strut.left_end_y) {
+            geom.x = allowed_area.x;
+            if (geom.y < allowed_area.y ||
+                    geom.y + geom.height > allowed_area.y + 
allowed_area.height) {
+                geom.y = allowed_area.y;
+                if (geom.height > allowed_area.height)
+                    geom.height = allowed_area.height;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        } else if(c->strut.right || c->strut.right_start_y || 
c->strut.right_end_y) {
+            geom.x = allowed_area.x + allowed_area.width - geom.width;
+            if (geom.y < allowed_area.y ||
+                    geom.y + geom.height > allowed_area.y + 
allowed_area.height) {
+                geom.y = allowed_area.y;
+                if (geom.height > allowed_area.height)
+                    geom.height = allowed_area.height;
+            }
+            c->ignore_strut = false;
+            client_resize(c, geom, false);
+        }
+    }
+}
+
+
 /** Set a client minimized, or not.
  * \param c The client.
  * \param s Set or not the client minimized.
diff --git a/client.h b/client.h
index 0a944e2..6a91b9e 100644
--- a/client.h
+++ b/client.h
@@ -59,6 +59,7 @@ void client_unban(client_t *);
 void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, int, bool);
 area_t client_geometry_hints(client_t *, area_t);
 bool client_resize(client_t *, area_t, bool);
+void client_update_strut_positions(int);
 void client_unmanage(client_t *);
 void client_kill(client_t *);
 void client_setsticky(client_t *, bool);
diff --git a/layout.c b/layout.c
index db60f2e..ef8541a 100644
--- a/layout.c
+++ b/layout.c
@@ -59,6 +59,8 @@ arrange(int screen)
             client_ban(c);
     }
 
+    client_update_strut_positions(screen);
+
     /* Reset status before calling arrange hook.
      * This is needed if you call a function that relies
      * on need_arrange while arrange is in progress.
diff --git a/lib/awful/mouse.lua.in b/lib/awful/mouse.lua.in
index 9d1a2b8..a5b5931 100644
--- a/lib/awful/mouse.lua.in
+++ b/lib/awful/mouse.lua.in
@@ -574,18 +574,4 @@ function client.resize(c, corner)
     end
 end
 
--- Disable struts when resizing
-local function update_struts(c, prop)
-    if prop == "geometry" then
-        local struts = c:struts()
-        struts['left'] = 0
-        struts['right'] = 0
-        struts['top'] = 0
-        struts['bottom'] = 0
-        c:struts(struts)
-    end
-end
-
-hooks.property.register(update_struts)
-
 -- vim: 
filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
diff --git a/screen.c b/screen.c
index a815fbc..554ef27 100644
--- a/screen.c
+++ b/screen.c
@@ -181,7 +181,7 @@ screen_area_get(int screen, wibox_array_t *wiboxes,
     {
         client_t *c;
         for(c = globalconf.clients; c; c = c->next)
-            if(client_isvisible(c, screen))
+            if(client_isvisible(c, screen) && !c->ignore_strut)
             {
                 if(c->strut.top_start_x || c->strut.top_end_x)
                 {
diff --git a/structs.h b/structs.h
index 5d1c385..0f0268b 100644
--- a/structs.h
+++ b/structs.h
@@ -180,6 +180,8 @@ struct client_t
     } geometries;
     /** Strut */
     strut_t strut;
+    /** Ignore strut temporarily. */
+    bool ignore_strut;
     /** Border width and pre-fullscreen border width */
     int border, border_fs;
     xcolor_t border_color;
diff --git a/wibox.c b/wibox.c
index b7d7170..c67f592 100644
--- a/wibox.c
+++ b/wibox.c
@@ -294,8 +294,9 @@ wibox_position_update(wibox_t *wibox)
 
     globalconf.screens[wibox->screen].need_arrange = true;
 
+    /* Place wibox'es at the edge of the screen, struts come later. */
     area = screen_area_get(wibox->screen, NULL,
-                           &globalconf.screens[wibox->screen].padding, true);
+                           &globalconf.screens[wibox->screen].padding, false);
 
     /* Top and Bottom wibox_t have prio */
     if(wibox->position != Floating)
-- 
1.6.2


-- 
To unsubscribe, send mail to awesome-devel-unsubscr...@naquadah.org.

Reply via email to