=== Hiding vertical borders
You can hide vertical borders adjacent to the screen edges using
-+hide_edge_borders+. This is useful if you are using scrollbars. This option is
-disabled by default.
++hide_edge_borders+. This is useful if you are using scrollbars, or do not want
+to waste even two pixels in displayspace. Default is none.
*Syntax*:
----------------------------
-hide_edge_borders <yes|no>
+hide_edge_borders <none|vertical|horizontal|both>
----------------------------
*Example*:
----------------------
-hide_edge_borders yes
+hide_edge_borders vertical
----------------------
=== Arbitrary commands for specific windows (for_window)
* It is not planned to add any different focus models. */
bool disable_focus_follows_mouse;
- /** Remove vertical borders if they are adjacent to the screen edge.
+ /** Remove borders if they are adjacent to the screen edge.
* This is useful if you are reaching scrollbar on the edge of the
- * screen. By default, this is disabled. */
- bool hide_edge_borders;
+ * screen or do not want to waste a single pixel of displayspace.
+ * By default, this is disabled. */
+ adjacent_t hide_edge_borders;
/** By default, a workspace bar is drawn at the bottom of the screen.
* If you want to have a more fancy bar, it is recommended to replace
/** describes if the window is adjacent to the output (physical screen) edges. */
typedef enum { ADJ_NONE = 0,
- ADJ_LEFT_SCREEN_EDGE = 1,
- ADJ_RIGHT_SCREEN_EDGE = 2} adjacent_t;
+ ADJ_LEFT_SCREEN_EDGE = (1 << 0),
+ ADJ_RIGHT_SCREEN_EDGE = (1 << 1),
+ ADJ_UPPER_SCREEN_EDGE = (1 << 2),
+ ADJ_LOWER_SCREEN_EDGE = (1 << 4)} adjacent_t;
enum {
BIND_NONE = 0,
none { return TOK_NONE; }
1pixel { return TOK_1PIXEL; }
hide_edge_borders { return TOK_HIDE_EDGE_BORDERS; }
+both { return TOK_BOTH; }
focus_follows_mouse { return TOKFOCUSFOLLOWSMOUSE; }
force_focus_wrapping { return TOK_FORCE_FOCUS_WRAPPING; }
force_xinerama { return TOK_FORCE_XINERAMA; }
%token TOK_NONE "none"
%token TOK_1PIXEL "1pixel"
%token TOK_HIDE_EDGE_BORDERS "hide_edge_borders"
+%token TOK_BOTH "both"
%token TOKFOCUSFOLLOWSMOUSE "focus_follows_mouse"
%token TOK_FORCE_FOCUS_WRAPPING "force_focus_wrapping"
%token TOK_FORCE_XINERAMA "force_xinerama"
%type <number> layout_mode
%type <number> border_style
%type <number> new_window
+%type <number> hide_edge_borders
+%type <number> edge_hiding_mode
%type <number> new_float
%type <number> colorpixel
%type <number> bool
;
hide_edge_borders:
- TOK_HIDE_EDGE_BORDERS bool
+ TOK_HIDE_EDGE_BORDERS edge_hiding_mode
{
DLOG("hide edge borders = %d\n", $2);
config.hide_edge_borders = $2;
}
;
+edge_hiding_mode:
+ TOK_NONE { $$ = ADJ_NONE; }
+ | TOK_VERT { $$ = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE; }
+ | TOK_HORIZ { $$ = ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE; }
+ | TOK_BOTH { $$ = ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE | ADJ_UPPER_SCREEN_EDGE | ADJ_LOWER_SCREEN_EDGE; }
+ | bool { $$ = ($1 ? ADJ_LEFT_SCREEN_EDGE | ADJ_RIGHT_SCREEN_EDGE : ADJ_NONE); }
+ ;
+
focus_follows_mouse:
TOKFOCUSFOLLOWSMOUSE bool
{
*
*/
Rect con_border_style_rect(Con *con) {
- adjacent_t adjacent_to = ADJ_NONE;
+ adjacent_t borders_to_hide = ADJ_NONE;
Rect result;
- if (config.hide_edge_borders)
- adjacent_to = con_adjacent_borders(con);
+ borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
switch (con_border_style(con)) {
case BS_NORMAL:
result = (Rect){2, 0, -(2 * 2), -2};
- if (adjacent_to & ADJ_LEFT_SCREEN_EDGE) {
+ if (borders_to_hide & ADJ_LEFT_SCREEN_EDGE) {
result.x -= 2;
result.width += 2;
}
- if (adjacent_to & ADJ_RIGHT_SCREEN_EDGE) {
+ if (borders_to_hide & ADJ_RIGHT_SCREEN_EDGE) {
result.width += 2;
}
+ /* With normal borders we never hide the upper border */
+ if (borders_to_hide & ADJ_LOWER_SCREEN_EDGE) {
+ result.height += 2;
+ }
return result;
case BS_1PIXEL:
result = (Rect){1, 1, -2, -2};
- if (adjacent_to & ADJ_LEFT_SCREEN_EDGE) {
+ if (borders_to_hide & ADJ_LEFT_SCREEN_EDGE) {
result.x -= 1;
result.width += 1;
}
- if (adjacent_to & ADJ_RIGHT_SCREEN_EDGE) {
+ if (borders_to_hide & ADJ_RIGHT_SCREEN_EDGE) {
result.width += 1;
}
+ if (borders_to_hide & ADJ_UPPER_SCREEN_EDGE) {
+ result.y -= 1;
+ result.height += 1;
+ }
+ if (borders_to_hide & ADJ_LOWER_SCREEN_EDGE) {
+ result.height += 1;
+ }
return result;
case BS_NONE:
*/
adjacent_t con_adjacent_borders(Con *con) {
adjacent_t result = ADJ_NONE;
- Con *output = con_get_output(con);
- if (con->rect.x == output->rect.x)
+ Con *workspace = con_get_workspace(con);
+ if (con->rect.x == workspace->rect.x)
result |= ADJ_LEFT_SCREEN_EDGE;
- if (con->rect.x + con->rect.width == output->rect.x + output->rect.width)
+ if (con->rect.x + con->rect.width == workspace->rect.x + workspace->rect.width)
result |= ADJ_RIGHT_SCREEN_EDGE;
+ if (con->rect.y == workspace->rect.y)
+ result |= ADJ_UPPER_SCREEN_EDGE;
+ if (con->rect.y + con->rect.height == workspace->rect.y + workspace->rect.height)
+ result |= ADJ_LOWER_SCREEN_EDGE;
return result;
}
void x_draw_decoration(Con *con) {
Con *parent = con->parent;
bool leaf = con_is_leaf(con);
- adjacent_t adjacent_to = ADJ_NONE;
- if (config.hide_edge_borders)
- adjacent_to = con_adjacent_borders(con);
+
/* This code needs to run for:
* • leaf containers
* • non-leaf containers which are in a stacked/tabbed container
*
* It does not need to run for:
+ * • direct children of outputs
* • floating containers (they don’t have a decoration)
*/
if ((!leaf &&
parent->layout != L_STACKED &&
parent->layout != L_TABBED) ||
+ parent->type == CT_OUTPUT ||
con->type == CT_FLOATING_CON)
return;
/* 3: draw a rectangle in border color around the client */
if (p->border_style != BS_NONE && p->con_is_leaf) {
+ /* We might hide some borders adjacent to the screen-edge */
+ adjacent_t borders_to_hide = ADJ_NONE;
+ borders_to_hide = con_adjacent_borders(con) & config.hide_edge_borders;
+
Rect br = con_border_style_rect(con);
#if 0
DLOG("con->rect spans %d x %d\n", con->rect.width, con->rect.height);
* rectangle because some childs are not freely resizable and we want
* their background color to "shine through". */
xcb_change_gc(conn, con->pm_gc, XCB_GC_FOREGROUND, (uint32_t[]){ p->color->background });
- if (!(adjacent_to & ADJ_LEFT_SCREEN_EDGE)) {
+ if (!(borders_to_hide & ADJ_LEFT_SCREEN_EDGE)) {
xcb_rectangle_t leftline = { 0, 0, br.x, r->height };
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &leftline);
}
- if (!(adjacent_to & ADJ_RIGHT_SCREEN_EDGE)) {
+ if (!(borders_to_hide & ADJ_RIGHT_SCREEN_EDGE)) {
xcb_rectangle_t rightline = { r->width + br.width + br.x, 0, r->width, r->height };
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &rightline);
}
- xcb_rectangle_t bottomline = { 0, r->height + br.height + br.y, r->width, r->height };
- xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &bottomline);
+ if (!(borders_to_hide & ADJ_LOWER_SCREEN_EDGE)) {
+ xcb_rectangle_t bottomline = { 0, r->height + br.height + br.y, r->width, r->height };
+ xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &bottomline);
+ }
/* 1pixel border needs an additional line at the top */
- if (p->border_style == BS_1PIXEL) {
+ if (p->border_style == BS_1PIXEL && !(borders_to_hide & ADJ_UPPER_SCREEN_EDGE)) {
xcb_rectangle_t topline = { br.x, 0, con->rect.width + br.width + br.x, br.y };
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &topline);
}