diff --git a/client.c b/client.c index cd9e537f..19a2c1a2 100644 --- a/client.c +++ b/client.c @@ -478,7 +478,7 @@ client_resize(client_t *c, area_t geometry, bool hints) if(c->titlebar && !c->ismoving && !c->isfloating && layout != layout_floating) { - titlebar_update_geometry(c, geometry); + titlebar_update_geometry_tiled(c, geometry); geometry = titlebar_geometry_remove(c->titlebar, geometry); } diff --git a/structs.h b/structs.h index 151e9d29..7ecc5098 100644 --- a/structs.h +++ b/structs.h @@ -185,6 +185,12 @@ struct titlebar_t { xcolor_t fg, bg; } colors; + /** Border */ + struct + { + xcolor_t color; + int width; + } border; }; /** Delete a titlebar structure. diff --git a/titlebar.c b/titlebar.c index e2a7e5f1..4c88e836 100644 --- a/titlebar.c +++ b/titlebar.c @@ -137,223 +137,100 @@ titlebar_draw(client_t *c) draw_context_delete(&ctx); } -/** Update the titlebar geometry for a floating client. - * \param c the client - */ void -titlebar_update_geometry_floating(client_t *c) +titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res) { int width, x_offset = 0, y_offset = 0; - if(!c->titlebar || !c->titlebar->sw) - return; - switch(c->titlebar->position) { default: return; case Top: if(c->titlebar->width) - width = MIN(c->titlebar->width, c->geometry.width); + width = MAX(1, MIN(c->titlebar->width, geometry.width - 2 * c->titlebar->border.width)); else - width = c->geometry.width + 2 * c->border; + width = MAX(1, geometry.width + 2 * c->border - 2 * c->titlebar->border.width); switch(c->titlebar->align) { default: break; case AlignRight: - x_offset = 2 * c->border + c->geometry.width - width; - break; - case AlignCenter: - x_offset = (c->geometry.width - width) / 2; - break; - } - simplewindow_moveresize(c->titlebar->sw, - c->geometry.x + x_offset, - c->geometry.y - c->titlebar->sw->geometry.height, - width, - c->titlebar->sw->geometry.height); - break; - case Bottom: - if(c->titlebar->width) - width = MIN(c->titlebar->width, c->geometry.width); - else - width = c->geometry.width + 2 * c->border; - switch(c->titlebar->align) - { - default: - break; - case AlignRight: - x_offset = 2 * c->border + c->geometry.width - width; - break; - case AlignCenter: - x_offset = (c->geometry.width - width) / 2; - break; - } - simplewindow_moveresize(c->titlebar->sw, - c->geometry.x + x_offset, - c->geometry.y + c->geometry.height + 2 * c->border, - width, - c->titlebar->sw->geometry.height); - break; - case Left: - if(c->titlebar->width) - width = MIN(c->titlebar->width, c->geometry.height); - else - width = c->geometry.height + 2 * c->border; - switch(c->titlebar->align) - { - default: - break; - case AlignRight: - y_offset = 2 * c->border + c->geometry.height - width; - break; - case AlignCenter: - y_offset = (c->geometry.height - width) / 2; - break; - } - simplewindow_moveresize(c->titlebar->sw, - c->geometry.x - c->titlebar->sw->geometry.width, - c->geometry.y + y_offset, - c->titlebar->sw->geometry.width, - width); - break; - case Right: - if(c->titlebar->width) - width = MIN(c->titlebar->width, c->geometry.height); - else - width = c->geometry.height + 2 * c->border; - switch(c->titlebar->align) - { - default: - break; - case AlignRight: - y_offset = 2 * c->border + c->geometry.height - width; - break; - case AlignCenter: - y_offset = (c->geometry.height - width) / 2; - break; - } - simplewindow_moveresize(c->titlebar->sw, - c->geometry.x + c->geometry.width + 2 * c->border, - c->geometry.y + y_offset, - c->titlebar->sw->geometry.width, - width); - break; - } - titlebar_draw(c); -} - - -/** Update the titlebar geometry for a tiled client. - * \param c The client. - * \param geometry The geometry the client will receive. - */ -void -titlebar_update_geometry(client_t *c, area_t geometry) -{ - int width, x_offset = 0 , y_offset = 0; - - if(!c->titlebar || !c->titlebar->sw) - return; - - switch(c->titlebar->position) - { - default: - return; - case Top: - if(!c->titlebar->width) - width = geometry.width + 2 * c->border; - else - width = MIN(c->titlebar->width, geometry.width); - switch(c->titlebar->align) - { - default: - break; - case AlignRight: - x_offset = 2 * c->border + geometry.width - width; + x_offset = 2 * c->border + geometry.width - width - 2 * c->titlebar->border.width; break; case AlignCenter: x_offset = (geometry.width - width) / 2; break; } - simplewindow_moveresize(c->titlebar->sw, - geometry.x + x_offset, - geometry.y, - width, - c->titlebar->sw->geometry.height); + res->x = geometry.x + x_offset; + res->y = geometry.y - c->titlebar->height - 2 * c->titlebar->border.width; + res->width = width; + res->height = c->titlebar->height; break; case Bottom: if(c->titlebar->width) - width = geometry.width + 2 * c->border; + width = MAX(1, MIN(c->titlebar->width, geometry.width - 2 * c->titlebar->border.width)); else - width = MIN(c->titlebar->width, geometry.width); + width = MAX(1, geometry.width + 2 * c->border - 2 * c->titlebar->border.width); switch(c->titlebar->align) { default: break; case AlignRight: - x_offset = 2 * c->border + geometry.width - width; + x_offset = 2 * c->border + geometry.width - width - 2 * c->titlebar->border.width; break; case AlignCenter: x_offset = (geometry.width - width) / 2; break; } - simplewindow_moveresize(c->titlebar->sw, - geometry.x + x_offset, - geometry.y + geometry.height - - c->titlebar->sw->geometry.height + 2 * c->border, - width, - c->titlebar->sw->geometry.height); + res->x = geometry.x + x_offset; + res->y = geometry.y + geometry.height + 2 * c->border; + res->width = width; + res->height = c->titlebar->height; break; case Left: - if(!c->titlebar->width) - width = geometry.height + 2 * c->border; + if(c->titlebar->width) + width = MAX(1, MIN(c->titlebar->width, geometry.height - 2 * c->titlebar->border.width)); else - width = MIN(c->titlebar->width, geometry.height); + width = MAX(1, geometry.height + 2 * c->border - 2 * c->titlebar->border.width); switch(c->titlebar->align) { default: break; case AlignRight: - y_offset = 2 * c->border + geometry.height - width; + y_offset = 2 * c->border + geometry.height - width - 2 * c->titlebar->border.width; break; case AlignCenter: y_offset = (geometry.height - width) / 2; break; } - simplewindow_moveresize(c->titlebar->sw, - geometry.x, - geometry.y + y_offset, - c->titlebar->sw->geometry.width, - width); + res->x = geometry.x - c->titlebar->height; + res->y = geometry.y + y_offset; + res->width = c->titlebar->height; + res->height = width; break; case Right: if(c->titlebar->width) - width = geometry.height + 2 * c->border; + width = MAX(1, MIN(c->titlebar->width, geometry.height - 2 * c->titlebar->border.width)); else - width = MIN(c->titlebar->width, geometry.height); + width = MAX(1, geometry.height + 2 * c->border - 2 * c->titlebar->border.width); switch(c->titlebar->align) { default: break; case AlignRight: - y_offset = 2 * c->border + geometry.height - width; + y_offset = 2 * c->border + geometry.height - width - 2 * c->titlebar->border.width; break; case AlignCenter: y_offset = (geometry.height - width) / 2; break; } - simplewindow_moveresize(c->titlebar->sw, - geometry.x + geometry.width - - c->titlebar->sw->geometry.width + 2 * c->border, - geometry.y + y_offset, - c->titlebar->sw->geometry.width, - width); + res->x = geometry.x + geometry.width + 2 * c->border; + res->y = geometry.y + y_offset; + res->width = c->titlebar->height; + res->height = width; break; } - - titlebar_draw(c); } /** Set client titlebar position. @@ -363,6 +240,7 @@ void titlebar_init(client_t *c) { int width = 0, height = 0; + area_t geom; switch(c->titlebar->position) { @@ -372,26 +250,33 @@ titlebar_init(client_t *c) case Top: case Bottom: if(c->titlebar->width) - width = MIN(c->titlebar->width, c->geometry.width); + width = MIN(c->titlebar->width, c->geometry.width - 2 * c->titlebar->border.width); else - width = c->geometry.width + 2 * c->border; + width = c->geometry.width + 2 * c->border - 2 * c->titlebar->border.width; height = c->titlebar->height; break; case Left: case Right: if(c->titlebar->width) - height = MIN(c->titlebar->width, c->geometry.height); + height = MIN(c->titlebar->width, c->geometry.height - 2 * c->titlebar->border.width); else - height = c->geometry.height + 2 * c->border; + height = c->geometry.height + 2 * c->border - 2 * c->titlebar->border.width; width = c->titlebar->height; break; } + + titlebar_geometry_compute(c, c->geometry, &geom); + + c->titlebar->sw = simplewindow_new(globalconf.connection, c->phys_screen, geom.x, geom.y, + geom.width, geom.height, c->titlebar->border.width); + if(c->titlebar->border.width) + xcb_change_window_attributes(globalconf.connection, c->titlebar->sw->window, + XCB_CW_BORDER_PIXEL, &c->titlebar->border.color.pixel); - c->titlebar->sw = simplewindow_new(globalconf.connection, - c->phys_screen, 0, 0, - width, height, 0); titlebar_draw(c); - xcb_map_window(globalconf.connection, c->titlebar->sw->window); + + if(client_isvisible(c, c->screen)) + xcb_map_window(globalconf.connection, c->titlebar->sw->window); } /** Create a new titlebar. @@ -422,20 +307,24 @@ luaA_titlebar_new(lua_State *L) tb->position = position_get_from_str(luaA_getopt_string(L, 1, "position", "top")); - lua_getfield(L, 1, "fg"); - if((color = luaL_optstring(L, -1, NULL))) + if((color = luaA_getopt_string(L, -1, "fg", NULL))) xcolor_new(globalconf.connection, globalconf.default_screen, color, &tb->colors.fg); else tb->colors.fg = globalconf.colors.fg; - lua_getfield(L, 1, "bg"); - if((color = luaL_optstring(L, -1, NULL))) + if((color = luaA_getopt_string(L, 1, "bg", NULL))) xcolor_new(globalconf.connection, globalconf.default_screen, color, &tb->colors.bg); else tb->colors.bg = globalconf.colors.bg; + if((color = luaA_getopt_string(L, 1, "border_color", NULL))) + xcolor_new(globalconf.connection, globalconf.default_screen, + color, &tb->border.color); + + tb->border.width = luaA_getopt_number(L, 1, "border_width", 0); + return luaA_titlebar_userdata_new(tb); } diff --git a/titlebar.h b/titlebar.h index 9763d0d5..af8a4a07 100644 --- a/titlebar.h +++ b/titlebar.h @@ -26,9 +26,8 @@ client_t * client_getbytitlebar(titlebar_t *); client_t * client_getbytitlebarwin(xcb_window_t); +void titlebar_geometry_compute(client_t *, area_t, area_t *); void titlebar_draw(client_t *); -void titlebar_update_geometry_floating(client_t *); -void titlebar_update_geometry(client_t *, area_t); void titlebar_init(client_t *); int luaA_titlebar_userdata_new(titlebar_t *); @@ -45,18 +44,18 @@ titlebar_geometry_add(titlebar_t *t, area_t geometry) switch(t->position) { case Top: - geometry.y -= t->sw->geometry.height; - geometry.height += t->sw->geometry.height; + geometry.y -= t->sw->geometry.height + 2 * t->border.width; + geometry.height += t->sw->geometry.height + 2 * t->border.width; break; case Bottom: - geometry.height += t->sw->geometry.height; + geometry.height += t->sw->geometry.height + 2 * t->border.width; break; case Left: - geometry.x -= t->sw->geometry.width; - geometry.width += t->sw->geometry.width; + geometry.x -= t->sw->geometry.width + 2 * t->border.width; + geometry.width += t->sw->geometry.width + 2 * t->border.width; break; case Right: - geometry.width += t->sw->geometry.width; + geometry.width += t->sw->geometry.width + 2 * t->border.width; break; default: break; @@ -77,18 +76,18 @@ titlebar_geometry_remove(titlebar_t *t, area_t geometry) switch(t->position) { case Top: - geometry.y += t->sw->geometry.height; - geometry.height -= t->sw->geometry.height; + geometry.y += t->sw->geometry.height + 2 * t->border.width; + geometry.height -= t->sw->geometry.height + 2 * t->border.width; break; case Bottom: - geometry.height -= t->sw->geometry.height; + geometry.height -= t->sw->geometry.height + 2 * t->border.width; break; case Left: - geometry.x += t->sw->geometry.width; - geometry.width -= t->sw->geometry.width; + geometry.x += t->sw->geometry.width + 2 * t->border.width; + geometry.width -= t->sw->geometry.width + 2 * t->border.width; break; case Right: - geometry.width -= t->sw->geometry.width; + geometry.width -= t->sw->geometry.width + 2 * t->border.width; break; default: break; @@ -97,5 +96,39 @@ titlebar_geometry_remove(titlebar_t *t, area_t geometry) return geometry; } +/** Update the titlebar geometry for a floating client. + * \param c the client + */ +static inline void +titlebar_update_geometry_floating(client_t *c) +{ + area_t geom; + + if(!c->titlebar || !c->titlebar->sw) + return; + + titlebar_geometry_compute(c, c->geometry, &geom); + simplewindow_moveresize(c->titlebar->sw, geom.x, geom.y, geom.width, geom.height); + titlebar_draw(c); +} + + +/** Update the titlebar geometry for a tiled client. + * \param c The client. + * \param geometry The geometry the client will receive. + */ +static inline void +titlebar_update_geometry_tiled(client_t *c, area_t geometry) +{ + area_t geom; + + if(!c->titlebar || !c->titlebar->sw) + return; + + titlebar_geometry_compute(c, geometry, &geom); + simplewindow_moveresize(c->titlebar->sw, geom.x, geom.y, geom.width, geom.height); + titlebar_draw(c); +} + #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80