client: handle struts (a lot) better
- 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. Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
addfd7b39f
commit
264a81f3fb
189
client.c
189
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.
|
||||
|
|
1
client.h
1
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);
|
||||
|
|
2
layout.c
2
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.
|
||||
|
|
|
@ -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
|
||||
|
|
2
screen.c
2
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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
3
wibox.c
3
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)
|
||||
|
|
Loading…
Reference in New Issue