diff --git a/client.c b/client.c index 741bd2de..3d9c8a7c 100644 --- a/client.c +++ b/client.c @@ -779,6 +779,195 @@ 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)) + 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 0a944e2d..6a91b9e5 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 db60f2ea..ef8541ad 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 9d1a2b81..a5b5931d 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 bfab8cc0..c75453fc 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 5d1c3855..0f0268b6 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 b7d71704..c67f5929 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)