client, swindow: switch to a more convient definition of geometry

- In many places i see people correcting for border width and titlebars.
- This new definition is the equivilant of what used to be fullgeometry.
- The internal geometry is now contained to a few functions that few people ever touch.
- This should avoid confusion and make code easier.
- Also protect against several unsigned overflows.

Signed-off-by: Maarten Maathuis <madman2003@gmail.com>
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Maarten Maathuis 2008-12-12 00:01:43 +01:00 committed by Julien Danjou
parent 5f8b34b909
commit 6e199bbd76
18 changed files with 198 additions and 200 deletions

View File

@ -393,7 +393,7 @@ awful.hooks.arrange.register(function (screen)
-- Uncomment if you want mouse warping
--[[
if client.focus then
local c_c = client.focus:fullgeometry()
local c_c = client.focus:geometry()
local m_c = mouse.coords()
if m_c.x < c_c.x or m_c.x >= c_c.x + c_c.width or

129
client.c
View File

@ -174,8 +174,8 @@ client_ban(client_t *c)
{
/* Move all clients out of the physical viewport into negative coordinate space. */
/* They will all be put on top of each other. */
uint32_t request[2] = { - (c->geometry.width + 2 * c->border),
- (c->geometry.height + 2 * c->border) };
uint32_t request[2] = { - (c->geometries.internal.width + 2 * c->border),
- (c->geometries.internal.height + 2 * c->border) };
xcb_configure_window(globalconf.connection, c->win,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
@ -475,8 +475,13 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen,
c->win = w;
c->geometry.x = wgeom->x;
c->geometry.y = wgeom->y;
c->geometry.width = wgeom->width;
c->geometry.height = wgeom->height;
c->geometry.width = wgeom->width + 2 * wgeom->border_width;
c->geometry.height = wgeom->height + 2 * wgeom->border_width;
/* Also set internal geometry (client_ban() needs it). */
c->geometries.internal.x = wgeom->x;
c->geometries.internal.y = wgeom->y;
c->geometries.internal.width = wgeom->width;
c->geometries.internal.height = wgeom->height;
client_setborder(c, wgeom->border_width);
if((icon = ewmh_window_icon_get_reply(ewmh_icon_cookie)))
c->icon = image_ref(&icon);
@ -674,8 +679,11 @@ client_geometry_hints(client_t *c, area_t geometry)
if(c->size_hints.flags & (XCB_SIZE_HINT_P_RESIZE_INC | XCB_SIZE_HINT_BASE_SIZE)
&& c->size_hints.width_inc && c->size_hints.height_inc)
{
geometry.width -= (geometry.width - basew) % c->size_hints.width_inc;
geometry.height -= (geometry.height - baseh) % c->size_hints.height_inc;
uint16_t t1 = geometry.width, t2 = geometry.height;
unsigned_subtract(t1, basew);
unsigned_subtract(t2, baseh);
geometry.width -= t1 % c->size_hints.width_inc;
geometry.height -= t2 % c->size_hints.height_inc;
}
return geometry;
@ -690,42 +698,52 @@ void
client_resize(client_t *c, area_t geometry, bool hints)
{
int new_screen;
area_t geometry_internal;
area_t area;
if(hints)
geometry = client_geometry_hints(c, geometry);
if(geometry.width <= 0 || geometry.height <= 0)
return;
/* offscreen appearance fixes */
area = display_area_get(c->phys_screen, NULL,
&globalconf.screens[c->screen].padding);
if(geometry.x > area.width)
geometry.x = area.width - geometry.width - 2 * c->border;
geometry.x = area.width - geometry.width;
if(geometry.y > area.height)
geometry.y = area.height - geometry.height - 2 * c->border;
if(geometry.x + geometry.width + 2 * c->border < 0)
geometry.y = area.height - geometry.height;
if(geometry.x + geometry.width < 0)
geometry.x = 0;
if(geometry.y + geometry.height + 2 * c->border < 0)
if(geometry.y + geometry.height < 0)
geometry.y = 0;
if(c->geometry.x != geometry.x
|| c->geometry.y != geometry.y
|| c->geometry.width != geometry.width
|| c->geometry.height != geometry.height)
/* Real client geometry, please keep it contained to C code at the very least. */
geometry_internal = titlebar_geometry_remove(c->titlebar, c->border, geometry);
if(hints)
geometry_internal = client_geometry_hints(c, geometry_internal);
if(geometry_internal.width == 0 || geometry_internal.height == 0)
return;
/* Also let client hints propegate to the "official" geometry. */
geometry = titlebar_geometry_add(c->titlebar, c->border, geometry_internal);
if(c->geometries.internal.x != geometry_internal.x
|| c->geometries.internal.y != geometry_internal.y
|| c->geometries.internal.width != geometry_internal.width
|| c->geometries.internal.height != geometry_internal.height)
{
new_screen = screen_getbycoord(c->screen, geometry.x, geometry.y);
new_screen = screen_getbycoord(c->screen, geometry_internal.x, geometry_internal.y);
/* Values to configure a window is an array where values are
* stored according to 'value_mask' */
uint32_t values[4];
c->geometry.x = values[0] = geometry.x;
c->geometry.y = values[1] = geometry.y;
c->geometry.width = values[2] = geometry.width;
c->geometry.height = values[3] = geometry.height;
c->geometries.internal.x = values[0] = geometry_internal.x;
c->geometries.internal.y = values[1] = geometry_internal.y;
c->geometries.internal.width = values[2] = geometry_internal.width;
c->geometries.internal.height = values[3] = geometry_internal.height;
/* Also store geometry including border and titlebar. */
c->geometry = geometry;
titlebar_update_geometry(c);
@ -734,15 +752,15 @@ client_resize(client_t *c, area_t geometry, bool hints)
/* This at least doesn't break expectations about events. */
if (c->isbanned)
{
geometry.x = values[0] = - (geometry.width + 2 * c->border);
geometry.y = values[1] = - (geometry.height + 2 * c->border);
geometry.x = values[0] = - (geometry_internal.width + 2 * c->border);
geometry.y = values[1] = - (geometry_internal.height + 2 * c->border);
}
xcb_configure_window(globalconf.connection, c->win,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
| XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
values);
window_configure(c->win, geometry, c->border);
window_configure(c->win, geometry_internal, c->border);
screen_client_moveto(c, new_screen, true, false);
@ -846,10 +864,6 @@ client_setmaxhoriz(client_t *c, bool s)
&globalconf.screens[c->screen].wiboxes,
&globalconf.screens[c->screen].padding,
true);
/* Remove space needed for titlebar and border. */
geometry = titlebar_geometry_remove(c->titlebar,
c->border,
geometry);
geometry.y = c->geometry.y;
geometry.height = c->geometry.height;
c->geometries.max.x = c->geometry.x;
@ -890,10 +904,6 @@ client_setmaxvert(client_t *c, bool s)
&globalconf.screens[c->screen].wiboxes,
&globalconf.screens[c->screen].padding,
true);
/* Remove space needed for titlebar and border. */
geometry = titlebar_geometry_remove(c->titlebar,
c->border,
geometry);
geometry.x = c->geometry.x;
geometry.width = c->geometry.width;
c->geometries.max.y = c->geometry.y;
@ -1006,12 +1016,12 @@ client_unban(client_t *c)
if(c->isbanned)
{
/* Move the client back where it belongs. */
uint32_t request[2] = { c->geometry.x, c->geometry.y };
uint32_t request[2] = { c->geometries.internal.x, c->geometries.internal.y };
xcb_configure_window(globalconf.connection, c->win,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
request);
window_configure(c->win, c->geometry, c->border);
window_configure(c->win, c->geometries.internal, c->border);
/* Do this manually because the system doesn't know we moved the toolbar.
* Note that !isvisible titlebars are unmapped and for fullscreen it'll
@ -1347,11 +1357,13 @@ luaA_client_unmanage(lua_State *L)
/** Return client geometry.
* \param L The Lua VM state.
* \param full Use titlebar also.
* \return The number of elements pushed on stack.
* \luastack
* \lparam A table with new coordinates, or none.
* \lreturn A table with client coordinates.
*/
static int
luaA_client_handlegeom(lua_State *L, bool full)
luaA_client_geometry(lua_State *L)
{
client_t **c = luaA_checkudata(L, 1, "client");
@ -1373,48 +1385,12 @@ luaA_client_handlegeom(lua_State *L, bool full)
geometry.height = luaA_getopt_number(L, 2, "height", (*c)->geometry.height);
}
if(full)
geometry = titlebar_geometry_remove((*c)->titlebar,
(*c)->border,
geometry);
client_resize(*c, geometry, (*c)->size_hints_honor);
}
if(full)
return luaA_pusharea(L, titlebar_geometry_add((*c)->titlebar,
(*c)->border,
(*c)->geometry));
return luaA_pusharea(L, (*c)->geometry);
}
/** Return client geometry.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lparam A table with new coordinates, or none.
* \lreturn A table with client coordinates.
*/
static int
luaA_client_geometry(lua_State *L)
{
return luaA_client_handlegeom(L, false);
}
/** Return client geometry, using also titlebar and border width.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lparam A table with new coordinates, or none.
* \lreturn A table with client coordinates.
*/
static int
luaA_client_fullgeometry(lua_State *L)
{
return luaA_client_handlegeom(L, true);
}
/** Client newindex.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
@ -1955,7 +1931,6 @@ const struct luaL_reg awesome_client_meta[] =
{
{ "isvisible", luaA_client_isvisible },
{ "geometry", luaA_client_geometry },
{ "fullgeometry", luaA_client_fullgeometry },
{ "buttons", luaA_client_buttons },
{ "tags", luaA_client_tags },
{ "kill", luaA_client_kill },

View File

@ -72,6 +72,14 @@ typedef struct
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define unsigned_subtract(a, b) \
do { \
if (b > a) \
a = 0; \
else \
a -= b; \
} while (0)
#define ssizeof(foo) (ssize_t)sizeof(foo)
#define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))

View File

@ -52,10 +52,7 @@ local function fair(screen, orientation)
g.y = wa.y + cell * g.height
end
g.width = g.width - 2 * c.border_width
g.height = g.height - 2 * c.border_width
c:fullgeometry(g)
c:geometry(g)
cell = cell + 1
if cell == cells then

View File

@ -55,10 +55,10 @@ local function magnifier(_, screen)
else
geometry.x = area.x
geometry.y = area.y
geometry.width = area.width - 2 * focus.border_width
geometry.height = area.height - 2 * focus.border_width
geometry.width = area.width
geometry.height = area.height
end
focus:fullgeometry(geometry)
focus:geometry(geometry)
focus:raise()
if #cls - 1 > 0 then
@ -69,11 +69,7 @@ local function magnifier(_, screen)
for k, c in ipairs(cls) do
if c ~= focus then
geometry.height = geometry.height - 2 * c.border_width
geometry.width = geometry.width - 2 * c.border_width
c:fullgeometry(geometry)
geometry.height = geometry.height + 2 * c.border_width
geometry.width = geometry.width + 2 * c.border_width
c:geometry(geometry)
geometry.y = geometry.y + geometry.height
end
end

View File

@ -27,11 +27,7 @@ local function fmax(screen, fs)
for k, c in pairs(client.visible(screen)) do
if not client.floating.get(c) then
area.width = area.width - 2 * c.border_width
area.height = area.height - 2 * c.border_width
c:fullgeometry(area)
area.width = area.width + 2 * c.border_width
area.height = area.height + 2 * c.border_width
c:geometry(area)
end
end
end

View File

@ -87,8 +87,8 @@ local function tile(_, screen, position)
geometry.y = wa.y
end
geometry.width = mw - 2 * c.border_width
geometry.height = mh - 2 * c.border_width
geometry.width = mw
geometry.height = mh
-- Slave windows
else
@ -98,52 +98,52 @@ local function tile(_, screen, position)
if position == "right" or position == "left" then
if otherwin <= real_ncol then
geometry.height = wa.height - 2 * c.border_width
geometry.height = wa.height
elseif (otherwin % win_by_col) ~= 0 and (current_col == real_ncol - 1) then
geometry.height = math.floor(wa.height / (otherwin % win_by_col)) - 2 * c.border_width
geometry.height = math.floor(wa.height / (otherwin % win_by_col))
else
geometry.height = math.floor(wa.height / win_by_col) - 2 * c.border_width
geometry.height = math.floor(wa.height / win_by_col)
end
geometry.width = math.floor((wa.width - mw) / real_ncol) - 2 * c.border_width
geometry.width = math.floor((wa.width - mw) / real_ncol)
if otherwin <= real_ncol then
geometry.y = wa.y
else
geometry.y = wa.y + ((i - 1 - nmaster) % win_by_col) *
(geometry.height + 2 * c.border_width)
geometry.height
end
geometry.x = wa.x + current_col * (geometry.width + 2 * c.border_width)
geometry.x = wa.x + current_col * geometry.width
if position == "right" then
geometry.x = geometry.x + mw
end
else
if otherwin <= real_ncol then
geometry.width = wa.width - 2 * c.border_width
geometry.width = wa.width
elseif (otherwin % win_by_col) ~= 0 and (current_col == real_ncol - 1) then
geometry.width = math.floor(wa.width / (otherwin % win_by_col)) - 2 * c.border_width
geometry.width = math.floor(wa.width / (otherwin % win_by_col))
else
geometry.width = math.floor(wa.width / win_by_col) - 2 * c.border_width
geometry.width = math.floor(wa.width / win_by_col)
end
geometry.height = math.floor((wa.height - mh) / real_ncol) - 2 * c.border_width
geometry.height = math.floor((wa.height - mh) / real_ncol)
if otherwin <= real_ncol then
geometry.x = wa.x
else
geometry.x = wa.x + ((i - 1 - nmaster) % win_by_col) *
(geometry.width + 2 * c.border_width)
geometry.width
end
geometry.y = wa.y + current_col * (geometry.height + 2 * c.border_width)
geometry.y = wa.y + current_col * geometry.height
if position == "bottom" then
geometry.y = geometry.y + mh
end
end
end
c:fullgeometry(geometry)
c:geometry(geometry)
end
end

View File

@ -199,19 +199,19 @@ local function set_coords(menu, screen_idx)
menu.w = menu.parent.w
menu.h = menu.parent.h
local p_w = (menu.h + menu.theme.border_width) * (menu.num - 1)
local m_h = menu.theme.border_width + (menu.h + menu.theme.border_width) * #menu.items
local m_w = menu.w + menu.theme.border_width
local p_w = menu.h * (menu.num - 1)
local m_h = menu.h * #menu.items
local m_w = menu.w
menu.y = menu.parent.y + p_w + m_h > screen_h and screen_h - m_h or menu.parent.y + p_w
menu.x = menu.parent.x + menu.w*2 + menu.theme.border_width > screen_w and menu.parent.x - m_w or menu.parent.x + m_w
menu.x = menu.parent.x + menu.w > screen_w and menu.parent.x - m_w or menu.parent.x + m_w
else
local m_coords = capi.mouse.coords()
menu.y = m_coords.y < s_geometry.y and s_geometry.y or m_coords.y
menu.x = m_coords.x < s_geometry.x and s_geometry.x or m_coords.x
local m_h = menu.theme.border_width + (menu.h + menu.theme.border_width) * #menu.items
local m_w = menu.w + menu.theme.border_width*2
local m_h = menu.h * #menu.items
local m_w = menu.w
menu.y = menu.y + m_h > screen_h and screen_h - m_h or menu.y
menu.x = menu.x + m_w > screen_w and screen_w - m_w or menu.x
end
@ -227,7 +227,7 @@ function show(menu)
width = menu.w,
height = menu.h,
x = menu.x,
y = menu.y + (num - 1) * (menu.h + menu.theme.border_width)
y = menu.y + (num - 1) * menu.h
})
item.screen = screen_index
end

View File

@ -86,8 +86,8 @@ end
function client.snap(c, snap, x, y, fixed_x, fixed_y)
local snap = snap or 8
local c = c or client.focus
local cur_geom = c:fullgeometry()
local geom = c:fullgeometry()
local cur_geom = c:geometry()
local geom = c:geometry()
geom.x = x or geom.x
geom.y = y or geom.y
@ -96,7 +96,7 @@ function client.snap(c, snap, x, y, fixed_x, fixed_y)
for k, snapper in ipairs(aclient.visible(c.screen)) do
if snapper ~= c then
geom = snap_outside(geom, snapper:fullgeometry(), snap)
geom = snap_outside(geom, snapper:geometry(), snap)
end
end
@ -124,7 +124,7 @@ function client.move(c, snap)
c:raise()
local orig = c:fullgeometry()
local orig = c:geometry()
local m_c = capi.mouse.coords()
local dist_x = m_c.x - orig.x
local dist_y = m_c.y - orig.y
@ -134,7 +134,7 @@ function client.move(c, snap)
local function ug(c, prop)
if prop == "geometry" then
local g = c:fullgeometry()
local g = c:geometry()
capi.mouse.coords({ x = g.x + dist_x, y = g.y + dist_y })
end
end
@ -147,7 +147,7 @@ function client.move(c, snap)
if lay == layout.suit.floating or aclient.floating.get(c) then
local x = mouse.x - dist_x
local y = mouse.y - dist_y
c:fullgeometry(client.snap(c, snap, x, y, fixed_x, fixed_y))
c:geometry(client.snap(c, snap, x, y, fixed_x, fixed_y))
if layout.get(c.screen) ~= layout.suit.floating and not aclient.floating.get(c) then
hooks.property.register(ug)
end
@ -389,9 +389,9 @@ local function client_resize_floating(c, corner, fixed_x, fixed_y)
end
if ng.width <= 0 then ng.width = nil end
if ng.height <= 0 then ng.height = nil end
if fixed_x then ng.width = width end
if fixed_y then ng.height = height end
c:geometry({ width = ng.width, height = ng.height })
if fixed_x then ng.width = g.width ng.x = g.x end
if fixed_y then ng.height = g.height ng.y = g.y end
c:geometry(ng)
-- Get real geometry that has been applied
-- in case we honor size hints
-- XXX: This should be rewritten when size

View File

@ -101,7 +101,7 @@ end
--- Place the client without it being outside the screen.
-- @param c The client.
function no_offscreen(c)
local geometry = c:fullgeometry()
local geometry = c:geometry()
local screen_geometry = capi.screen[c.screen].workarea
if geometry.x + geometry.width > screen_geometry.x + screen_geometry.width then
@ -116,7 +116,7 @@ function no_offscreen(c)
geometry.y = screen_geometry.y
end
c:fullgeometry(geometry)
c:geometry(geometry)
end
--- Place the client where there's place available with minimum overlap.
@ -126,10 +126,9 @@ function no_overlap(c)
local layout = layout.get()
local areas = { capi.screen[c.screen].workarea }
local geometry = c:geometry()
local fullgeometry = c:fullgeometry()
for i, cl in pairs(cls) do
if cl ~= c and (client.get.floating(cl) or layout == layout.suit.floating) then
areas = area_remove(areas, cl:fullgeometry())
areas = area_remove(areas, cl:geometry())
end
end
@ -137,8 +136,8 @@ function no_overlap(c)
local found = false
local new = { x = geometry.x, y = geometry.y, width = 0, height = 0 }
for i, r in ipairs(areas) do
if r.width >= fullgeometry.width
and r.height >= fullgeometry.height
if r.width >= geometry.width
and r.height >= geometry.height
and r.width * r.height > new.width * new.height then
found = true
new = r

View File

@ -113,12 +113,12 @@ function add(c, args)
closef = closef, close = close }
-- Store old geometry (including borders)
local old_geom = c:fullgeometry()
local old_geom = c:geometry()
c.titlebar = tb
-- Resize the client so the same amount of space is occupied as before.
c:fullgeometry(old_geom)
c:geometry(old_geom)
update(c)
update(c, "geometry")
@ -142,10 +142,10 @@ function update(c, prop)
if data[c].width then
if c.titlebar.position == "top"
or c.titlebar.position == "bottom" then
local w = math.min(data[c].width, c:geometry().width + 2 * c.border_width)
local w = math.min(data[c].width, c:geometry().width)
c.titlebar:geometry({ width = w })
else
local w = math.min(data[c].width, c:geometry().height + 2 * c.border_width)
local w = math.min(data[c].width, c:geometry().height)
c.titlebar:geometry({ height = w })
end
end
@ -167,11 +167,11 @@ end
--- Remove a titlebar from a client.
-- @param c The client.
function remove(c)
local old_geom = c:fullgeometry()
local old_geom = c:geometry()
c.titlebar = nil
data[c] = nil
-- Resize the client so the same amount of space is occupied as before.
c:fullgeometry(old_geom)
c:geometry(old_geom)
end
-- Register standards hooks

View File

@ -159,20 +159,20 @@ local function get_offset(screen, position, idx, width, height)
if position:match("left") then
v.x = ws.x + config.padding
else
v.x = ws.x + ws.width - (width + config.border_width*2 + config.padding)
v.x = ws.x + ws.width - (width + config.padding)
end
-- calculate existing popups' height
local existing = 0
for i = 1, idx-1, 1 do
existing = existing + notifications[screen][position][i].height + config.spacing + config.border_width*2
existing = existing + notifications[screen][position][i].height + config.spacing
end
-- calculate y
if position:match("top") then
v.y = ws.y + config.padding + existing
else
v.y = ws.y + ws.height - (config.padding + config.border_width*2 + height + existing)
v.y = ws.y + ws.height - (config.padding + height + existing)
end
-- if positioned outside workarea, destroy oldest popup and recalculate

View File

@ -162,6 +162,8 @@ struct client_t
area_t fullscreen;
/** Client geometry when (un)-max */
area_t max;
/** Internal geometry (matching X11 protocol) */
area_t internal;
} geometries;
/** Strut */
strut_t strut;

View File

@ -48,14 +48,14 @@ simplewindow_draw_context_update(simple_window_t *sw, xcb_screen_t *s)
xcb_create_pixmap(globalconf.connection,
s->root_depth,
sw->ctx.pixmap, s->root,
sw->geometry.height, sw->geometry.width);
sw->geometry.height, sw->geometries.internal.width);
draw_context_init(&sw->ctx, phys_screen,
sw->geometry.height, sw->geometry.width,
sw->geometry.height, sw->geometries.internal.width,
sw->ctx.pixmap, &fg, &bg);
break;
case East:
draw_context_init(&sw->ctx, phys_screen,
sw->geometry.width, sw->geometry.height,
sw->geometries.internal.width, sw->geometries.internal.height,
sw->pixmap, &fg, &bg);
break;
}
@ -88,6 +88,13 @@ simplewindow_init(simple_window_t *sw,
sw->geometry.width = geometry.width;
sw->geometry.height = geometry.height;
sw->border.width = border_width;
/* The real protocol window. */
sw->geometries.internal.x = geometry.x;
sw->geometries.internal.y = geometry.y;
sw->geometries.internal.width = geometry.width - 2*border_width;
sw->geometries.internal.height = geometry.height - 2*border_width;
sw->orientation = orientation;
sw->ctx.fg = *fg;
sw->ctx.bg = *bg;
@ -102,14 +109,14 @@ simplewindow_init(simple_window_t *sw,
sw->window = xcb_generate_id(globalconf.connection);
xcb_create_window(globalconf.connection, s->root_depth, sw->window, s->root,
geometry.x, geometry.y, geometry.width, geometry.height,
sw->geometries.internal.x, sw->geometries.internal.y, sw->geometries.internal.width, sw->geometries.internal.height,
border_width, XCB_COPY_FROM_PARENT, s->root_visual,
XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
create_win_val);
sw->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root,
geometry.width, geometry.height);
sw->geometries.internal.width, sw->geometries.internal.height);
sw->ctx.phys_screen = phys_screen;
simplewindow_draw_context_update(sw, s);
@ -153,10 +160,10 @@ simplewindow_move(simple_window_t *sw, int x, int y)
{
const uint32_t move_win_vals[] = { x, y };
if(x != sw->geometry.x || y != sw->geometry.y)
if(x != sw->geometries.internal.x || y != sw->geometries.internal.y)
{
sw->geometry.x = x;
sw->geometry.y = y;
sw->geometry.x = sw->geometries.internal.x = x;
sw->geometry.y = sw->geometries.internal.y = y;
xcb_configure_window(globalconf.connection, sw->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
move_win_vals);
@ -171,19 +178,25 @@ simplewindow_move(simple_window_t *sw, int x, int y)
void
simplewindow_resize(simple_window_t *sw, int w, int h)
{
if(w > 0 && h > 0 && (sw->geometry.width != w || sw->geometry.height != h))
int iw = w - 2 * sw->border.width;
int ih = h - 2 * sw->border.width;
if(iw > 0 && ih > 0 &&
(sw->geometries.internal.width != iw || sw->geometries.internal.height != ih))
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
uint32_t resize_win_vals[2];
sw->geometry.width = resize_win_vals[0] = w;
sw->geometry.height = resize_win_vals[1] = h;
sw->geometries.internal.width = resize_win_vals[0] = iw;
sw->geometries.internal.height = resize_win_vals[1] = ih;
sw->geometry.width = w;
sw->geometry.height = h;
xcb_free_pixmap(globalconf.connection, sw->pixmap);
/* orientation != East */
if(sw->pixmap != sw->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
sw->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, w, h);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, iw, ih);
xcb_configure_window(globalconf.connection, sw->window,
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
resize_win_vals);
@ -193,7 +206,7 @@ simplewindow_resize(simple_window_t *sw, int w, int h)
/** Move and resize a window in one call.
* \param sw The simple window to move and resize.
* \param geom The new gometry.
* \param geom The new geometry.
*/
void
simplewindow_moveresize(simple_window_t *sw, area_t geom)
@ -201,10 +214,14 @@ simplewindow_moveresize(simple_window_t *sw, area_t geom)
uint32_t moveresize_win_vals[4], mask_vals = 0;
xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
if(sw->geometry.x != geom.x || sw->geometry.y != geom.y)
area_t geom_internal = geom;
geom_internal.width -= 2 * sw->border.width;
geom_internal.height -= 2* sw->border.width;
if(sw->geometries.internal.x != geom_internal.x || sw->geometries.internal.y != geom_internal.y)
{
sw->geometry.x = moveresize_win_vals[0] = geom.x;
sw->geometry.y = moveresize_win_vals[1] = geom.y;
sw->geometries.internal.x = moveresize_win_vals[0] = geom_internal.x;
sw->geometries.internal.y = moveresize_win_vals[1] = geom_internal.y;
mask_vals |= XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
}
@ -212,13 +229,13 @@ simplewindow_moveresize(simple_window_t *sw, area_t geom)
{
if(mask_vals)
{
sw->geometry.width = moveresize_win_vals[2] = geom.width;
sw->geometry.height = moveresize_win_vals[3] = geom.height;
sw->geometries.internal.width = moveresize_win_vals[2] = geom_internal.width;
sw->geometries.internal.height = moveresize_win_vals[3] = geom_internal.height;
}
else
{
sw->geometry.width = moveresize_win_vals[0] = geom.width;
sw->geometry.height = moveresize_win_vals[1] = geom.height;
sw->geometries.internal.width = moveresize_win_vals[0] = geom_internal.width;
sw->geometries.internal.height = moveresize_win_vals[1] = geom_internal.height;
}
mask_vals |= XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
xcb_free_pixmap(globalconf.connection, sw->pixmap);
@ -226,10 +243,13 @@ simplewindow_moveresize(simple_window_t *sw, area_t geom)
if(sw->pixmap != sw->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
sw->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, geom.width, geom.height);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, geom_internal.width, geom_internal.height);
simplewindow_draw_context_update(sw, s);
}
/* Also save geometry including border. */
sw->geometry = geom;
xcb_configure_window(globalconf.connection, sw->window, mask_vals, moveresize_win_vals);
}

View File

@ -36,6 +36,11 @@ typedef struct simple_window_t
xcb_gcontext_t gc;
/** The window geometry. */
area_t geometry;
struct
{
/** Internal geometry (matching X11 protocol) */
area_t internal;
} geometries;
/** The window border */
struct
{

View File

@ -64,83 +64,83 @@ client_getbytitlebarwin(xcb_window_t win)
void
titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res)
{
int width, x_offset = 0, y_offset = 0;
int height, width, x_offset = 0, y_offset = 0;
switch(c->titlebar->position)
{
default:
return;
case Top:
width = MAX(1, geometry.width + 2 * c->border - 2 * c->titlebar->sw.border.width);
width = MAX(1, geometry.width);
switch(c->titlebar->align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + geometry.width - width - 2 * c->titlebar->sw.border.width;
x_offset = geometry.width - width;
break;
case AlignCenter:
x_offset = (geometry.width - width) / 2;
break;
}
res->x = geometry.x + x_offset;
res->y = geometry.y - c->titlebar->sw.geometry.height - 2 * c->titlebar->sw.border.width + c->border;
res->y = geometry.y;
res->width = width;
res->height = c->titlebar->sw.geometry.height;
break;
case Bottom:
width = MAX(1, geometry.width + 2 * c->border - 2 * c->titlebar->sw.border.width);
width = MAX(1, geometry.width);
switch(c->titlebar->align)
{
default:
break;
case AlignRight:
x_offset = 2 * c->border + geometry.width - width - 2 * c->titlebar->sw.border.width;
x_offset = geometry.width - width;
break;
case AlignCenter:
x_offset = (geometry.width - width) / 2;
break;
}
res->x = geometry.x + x_offset;
res->y = geometry.y + geometry.height + c->border;
res->y = geometry.y + geometry.height - c->titlebar->sw.geometry.height;
res->width = width;
res->height = c->titlebar->sw.geometry.height;
break;
case Left:
width = MAX(1, geometry.height + 2 * c->border - 2 * c->titlebar->sw.border.width);
height = MAX(1, geometry.height);
switch(c->titlebar->align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + geometry.height - width - 2 * c->titlebar->sw.border.width;
y_offset = geometry.height - height;
break;
case AlignCenter:
y_offset = (geometry.height - width) / 2;
y_offset = (geometry.height - height) / 2;
break;
}
res->x = geometry.x - c->titlebar->sw.geometry.width + c->border;
res->x = geometry.x;
res->y = geometry.y + y_offset;
res->width = c->titlebar->sw.geometry.width;
res->height = width;
res->height = height;
break;
case Right:
width = MAX(1, geometry.height + 2 * c->border - 2 * c->titlebar->sw.border.width);
height = MAX(1, geometry.height);
switch(c->titlebar->align)
{
default:
break;
case AlignRight:
y_offset = 2 * c->border + geometry.height - width - 2 * c->titlebar->sw.border.width;
y_offset = geometry.height - height;
break;
case AlignCenter:
y_offset = (geometry.height - width) / 2;
y_offset = (geometry.height - height) / 2;
break;
}
res->x = geometry.x + geometry.width + c->border;
res->x = geometry.x + geometry.width - c->titlebar->sw.geometry.width;
res->y = geometry.y + y_offset;
res->width = c->titlebar->sw.geometry.width;
res->height = width;
res->height = height;
break;
}
}

View File

@ -51,18 +51,18 @@ titlebar_geometry_add(wibox_t *t, int border, area_t geometry)
switch(t->position)
{
case Top:
geometry.y -= t->sw.geometry.height + 2 * t->sw.border.width;
geometry.height += t->sw.geometry.height + 2 * t->sw.border.width;
geometry.y -= t->sw.geometry.height;
geometry.height += t->sw.geometry.height;
break;
case Bottom:
geometry.height += t->sw.geometry.height + 2 * t->sw.border.width;
geometry.height += t->sw.geometry.height;
break;
case Left:
geometry.x -= t->sw.geometry.width + 2 * t->sw.border.width;
geometry.width += t->sw.geometry.width + 2 * t->sw.border.width;
geometry.x -= t->sw.geometry.width;
geometry.width += t->sw.geometry.width;
break;
case Right:
geometry.width += t->sw.geometry.width + 2 * t->sw.border.width;
geometry.width += t->sw.geometry.width;
break;
default:
break;
@ -92,26 +92,26 @@ titlebar_geometry_remove(wibox_t *t, int border, area_t geometry)
switch(t->position)
{
case Top:
geometry.y += t->sw.geometry.height + 2 * t->sw.border.width;
geometry.height -= t->sw.geometry.height + 2 * t->sw.border.width;
geometry.y += t->sw.geometry.height;
unsigned_subtract(geometry.height, t->sw.geometry.height);
break;
case Bottom:
geometry.height -= t->sw.geometry.height + 2 * t->sw.border.width;
unsigned_subtract(geometry.height, t->sw.geometry.height);
break;
case Left:
geometry.x += t->sw.geometry.width + 2 * t->sw.border.width;
geometry.width -= t->sw.geometry.width + 2 * t->sw.border.width;
geometry.x += t->sw.geometry.width;
unsigned_subtract(geometry.width, t->sw.geometry.width);
break;
case Right:
geometry.width -= t->sw.geometry.width + 2 * t->sw.border.width;
unsigned_subtract(geometry.width, t->sw.geometry.width);
break;
default:
break;
}
/* Adding a border to a client only changes width and height, x and y are including border. */
geometry.width -= 2 * border;
geometry.height -= 2 * border;
unsigned_subtract(geometry.width, 2*border);
unsigned_subtract(geometry.height, 2*border);
return geometry;
}

14
wibox.c
View File

@ -366,9 +366,9 @@ wibox_position_update(wibox_t *wibox)
switch(wibox->position)
{
case Right:
wingeom.height = area.height - 2 * wibox->sw.border.width;
wingeom.height = area.height;
wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
wingeom.x = area.x + area.width - wingeom.width - 2 * wibox->sw.border.width;
wingeom.x = area.x + area.width - wingeom.width;
switch(wibox->align)
{
default:
@ -383,13 +383,13 @@ wibox_position_update(wibox_t *wibox)
}
break;
case Left:
wingeom.height = area.height - 2 * wibox->sw.border.width;
wingeom.height = area.height;
wingeom.width = wibox->sw.geometry.width > 0 ? wibox->sw.geometry.width : 1.5 * globalconf.font->height;
wingeom.x = area.x;
switch(wibox->align)
{
default:
wingeom.y = (area.y + area.height) - wingeom.height - 2 * wibox->sw.border.width;
wingeom.y = (area.y + area.height) - wingeom.height;
break;
case AlignRight:
wingeom.y = area.y;
@ -400,8 +400,8 @@ wibox_position_update(wibox_t *wibox)
break;
case Bottom:
wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
wingeom.width = area.width - 2 * wibox->sw.border.width;
wingeom.y = (area.y + area.height) - wingeom.height - 2 * wibox->sw.border.width;
wingeom.width = area.width;
wingeom.y = (area.y + area.height) - wingeom.height;
wingeom.x = area.x;
switch(wibox->align)
{
@ -417,7 +417,7 @@ wibox_position_update(wibox_t *wibox)
break;
case Top:
wingeom.height = wibox->sw.geometry.height > 0 ? wibox->sw.geometry.height : 1.5 * globalconf.font->height;
wingeom.width = area.width - 2 * wibox->sw.border.width;
wingeom.width = area.width;
wingeom.x = area.x;
wingeom.y = area.y;
switch(wibox->align)