Rendering fixes for stacking mode
This commit is contained in:
parent
e6d1f181fd
commit
7c6f2dbfc6
|
@ -135,7 +135,7 @@ int con_orientation(Con *con);
|
||||||
*/
|
*/
|
||||||
Con *con_next_focused(Con *con);
|
Con *con_next_focused(Con *con);
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Returns a "relative" Rect which contains the amount of pixels that need to
|
* Returns a "relative" Rect which contains the amount of pixels that need to
|
||||||
* be added to the original Rect to get the final position (obviously the
|
* be added to the original Rect to get the final position (obviously the
|
||||||
* amount of pixels for normal, 1pixel and borderless are different).
|
* amount of pixels for normal, 1pixel and borderless are different).
|
||||||
|
@ -143,4 +143,14 @@ Con *con_next_focused(Con *con);
|
||||||
*/
|
*/
|
||||||
Rect con_border_style_rect(Con *con);
|
Rect con_border_style_rect(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to get a container’s border style. This is important
|
||||||
|
* because when inside a stack, the border style is always BS_NORMAL.
|
||||||
|
* For tabbed mode, the same applies, with one exception: when the container is
|
||||||
|
* borderless and the only element in the tabbed container, the border is not
|
||||||
|
* rendered.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int con_border_style(Con *con);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
30
src/con.c
30
src/con.c
|
@ -41,12 +41,10 @@ Con *con_new(Con *parent) {
|
||||||
/* TODO: remove window coloring after test-phase */
|
/* TODO: remove window coloring after test-phase */
|
||||||
LOG("color %s\n", colors[cnt]);
|
LOG("color %s\n", colors[cnt]);
|
||||||
new->name = strdup(colors[cnt]);
|
new->name = strdup(colors[cnt]);
|
||||||
#if 0
|
//uint32_t cp = get_colorpixel(colors[cnt]);
|
||||||
uint32_t cp = get_colorpixel(colors[cnt]);
|
|
||||||
cnt++;
|
cnt++;
|
||||||
if ((cnt % (sizeof(colors) / sizeof(char*))) == 0)
|
if ((cnt % (sizeof(colors) / sizeof(char*))) == 0)
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
x_con_init(new);
|
x_con_init(new);
|
||||||
|
|
||||||
|
@ -453,14 +451,32 @@ Con *con_next_focused(Con *con) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Rect con_border_style_rect(Con *con) {
|
Rect con_border_style_rect(Con *con) {
|
||||||
if (con->border_style == BS_NORMAL)
|
switch (con_border_style(con)) {
|
||||||
|
case BS_NORMAL:
|
||||||
return (Rect){2, 0, -(2 * 2), -2};
|
return (Rect){2, 0, -(2 * 2), -2};
|
||||||
|
|
||||||
if (con->border_style == BS_1PIXEL)
|
case BS_1PIXEL:
|
||||||
return (Rect){1, 1, -2, -2};
|
return (Rect){1, 1, -2, -2};
|
||||||
|
|
||||||
if (con->border_style == BS_NONE)
|
case BS_NONE:
|
||||||
return (Rect){0, 0, 0, 0};
|
return (Rect){0, 0, 0, 0};
|
||||||
|
|
||||||
assert(false);
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use this function to get a container’s border style. This is important
|
||||||
|
* because when inside a stack, the border style is always BS_NORMAL.
|
||||||
|
* For tabbed mode, the same applies, with one exception: when the container is
|
||||||
|
* borderless and the only element in the tabbed container, the border is not
|
||||||
|
* rendered.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int con_border_style(Con *con) {
|
||||||
|
if (con->parent->layout == L_STACKED)
|
||||||
|
return BS_NORMAL;
|
||||||
|
|
||||||
|
return con->border_style;
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,8 +167,13 @@ void render_con(Con *con) {
|
||||||
/* in a stacking container, we ensure the focused client is raised */
|
/* in a stacking container, we ensure the focused client is raised */
|
||||||
if (con->layout == L_STACKED) {
|
if (con->layout == L_STACKED) {
|
||||||
Con *foc = TAILQ_FIRST(&(con->focus_head));
|
Con *foc = TAILQ_FIRST(&(con->focus_head));
|
||||||
if (foc != TAILQ_END(&(con->focus_head)))
|
if (foc != TAILQ_END(&(con->focus_head))) {
|
||||||
|
LOG("con %p is stacking, raising %p\n", con, foc);
|
||||||
x_raise_con(foc);
|
x_raise_con(foc);
|
||||||
|
/* by rendering the stacked container again, we handle the case
|
||||||
|
* that we have a non-leaf-container inside the stack. */
|
||||||
|
render_con(foc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
|
TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
|
||||||
|
|
|
@ -233,7 +233,7 @@ void tree_split(Con *con, orientation_t orientation) {
|
||||||
/* if we are in a container whose parent contains only one
|
/* if we are in a container whose parent contains only one
|
||||||
* child and has the same orientation like we are trying to
|
* child and has the same orientation like we are trying to
|
||||||
* set, this operation is a no-op to not confuse the user */
|
* set, this operation is a no-op to not confuse the user */
|
||||||
if (parent->orientation == orientation &&
|
if (con_orientation(parent) == orientation &&
|
||||||
TAILQ_NEXT(con, nodes) == TAILQ_END(&(parent->nodes_head))) {
|
TAILQ_NEXT(con, nodes) == TAILQ_END(&(parent->nodes_head))) {
|
||||||
DLOG("Not splitting the same way again\n");
|
DLOG("Not splitting the same way again\n");
|
||||||
return;
|
return;
|
||||||
|
@ -353,6 +353,7 @@ void tree_next(char way, orientation_t orientation) {
|
||||||
while (!TAILQ_EMPTY(&(next->focus_head)))
|
while (!TAILQ_EMPTY(&(next->focus_head)))
|
||||||
next = TAILQ_FIRST(&(next->focus_head));
|
next = TAILQ_FIRST(&(next->focus_head));
|
||||||
|
|
||||||
|
DLOG("focusing %p\n", next);
|
||||||
con_focus(next);
|
con_focus(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
89
src/x.c
89
src/x.c
|
@ -222,8 +222,13 @@ void x_window_kill(xcb_window_t window) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void x_draw_decoration(Con *con) {
|
void x_draw_decoration(Con *con) {
|
||||||
if (!con_is_leaf(con) || (con->type != CT_CON && con->type != CT_FLOATING_CON))
|
/* this code needs to run for:
|
||||||
|
* • leaf containers
|
||||||
|
* • non-leaf containers which are in a stacking container
|
||||||
|
*/
|
||||||
|
if (!con_is_leaf(con) && con->parent->layout != L_STACKED)
|
||||||
return;
|
return;
|
||||||
|
DLOG("decoration should be rendered for con %p\n", con);
|
||||||
|
|
||||||
/* 1: find out which colors to use */
|
/* 1: find out which colors to use */
|
||||||
struct Colortriple *color;
|
struct Colortriple *color;
|
||||||
|
@ -237,15 +242,48 @@ void x_draw_decoration(Con *con) {
|
||||||
color = &config.client.unfocused;
|
color = &config.client.unfocused;
|
||||||
|
|
||||||
Con *parent = con->parent;
|
Con *parent = con->parent;
|
||||||
|
int border_style = con_border_style(con);
|
||||||
|
|
||||||
/* 2: draw a rectangle in border color around the client */
|
/* 2: draw a rectangle in border color around the client */
|
||||||
if (con->border_style != BS_NONE) {
|
if (border_style != BS_NONE && con_is_leaf(con)) {
|
||||||
|
Rect br = con_border_style_rect(con);
|
||||||
|
Rect *r = &(con->rect);
|
||||||
|
#if 0
|
||||||
|
DLOG("con->rect spans %d x %d\n", con->rect.width, con->rect.height);
|
||||||
|
DLOG("border_rect spans (%d, %d) with %d x %d\n", border_rect.x, border_rect.y, border_rect.width, border_rect.height);
|
||||||
|
DLOG("window_rect spans (%d, %d) with %d x %d\n", con->window_rect.x, con->window_rect.y, con->window_rect.width, con->window_rect.height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This polygon represents the border around the child window (left,
|
||||||
|
* bottom and right part). We don’t just fill the whole rectangle
|
||||||
|
* because some childs are not freely resizable and we want their
|
||||||
|
* background color to "shine through". */
|
||||||
xcb_change_gc_single(conn, con->gc, XCB_GC_FOREGROUND, color->background);
|
xcb_change_gc_single(conn, con->gc, XCB_GC_FOREGROUND, color->background);
|
||||||
xcb_rectangle_t rect = { 0, 0, con->rect.width, con->rect.height };
|
xcb_point_t points[] = {
|
||||||
xcb_poly_fill_rectangle(conn, con->frame, con->gc, 1, &rect);
|
{ 0, 0 },
|
||||||
|
{ 0, r->height },
|
||||||
|
{ r->width, r->height },
|
||||||
|
{ r->width, 0 },
|
||||||
|
{ r->width + br.width + br.x, 0 },
|
||||||
|
{ r->width + br.width + br.x, r->height + br.height + br.y },
|
||||||
|
{ br.x, r->height + br.height },
|
||||||
|
{ br.x, 0 }
|
||||||
|
};
|
||||||
|
xcb_fill_poly(conn, con->frame, con->gc, XCB_POLY_SHAPE_COMPLEX, XCB_COORD_MODE_ORIGIN, 8, points);
|
||||||
|
|
||||||
|
/* 1pixel border needs an additional line at the top */
|
||||||
|
if (border_style == BS_1PIXEL) {
|
||||||
|
xcb_rectangle_t topline = { br.x, 0, con->rect.width + br.width + br.x, br.y };
|
||||||
|
xcb_poly_fill_rectangle(conn, con->frame, con->gc, 1, &topline);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (con->border_style != BS_NORMAL)
|
|
||||||
|
/* if this is a borderless/1pixel window, we don’t * need to render the
|
||||||
|
* decoration. */
|
||||||
|
if (border_style != BS_NORMAL) {
|
||||||
|
DLOG("border style not BS_NORMAL, aborting rendering of decoration\n");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* 3: paint the bar */
|
/* 3: paint the bar */
|
||||||
xcb_change_gc_single(conn, parent->gc, XCB_GC_FOREGROUND, color->background);
|
xcb_change_gc_single(conn, parent->gc, XCB_GC_FOREGROUND, color->background);
|
||||||
|
@ -265,18 +303,49 @@ void x_draw_decoration(Con *con) {
|
||||||
con->deco_rect.y + con->deco_rect.height - 1); /* to_y */
|
con->deco_rect.y + con->deco_rect.height - 1); /* to_y */
|
||||||
|
|
||||||
/* 5: draw the title */
|
/* 5: draw the title */
|
||||||
struct Window *win = con->window;
|
|
||||||
if (win == NULL || win ->name_x == NULL)
|
|
||||||
return;
|
|
||||||
xcb_change_gc_single(conn, parent->gc, XCB_GC_BACKGROUND, color->background);
|
xcb_change_gc_single(conn, parent->gc, XCB_GC_BACKGROUND, color->background);
|
||||||
xcb_change_gc_single(conn, parent->gc, XCB_GC_FOREGROUND, color->text);
|
xcb_change_gc_single(conn, parent->gc, XCB_GC_FOREGROUND, color->text);
|
||||||
|
|
||||||
|
struct Window *win = con->window;
|
||||||
|
if (win == NULL || win->name_x == NULL) {
|
||||||
|
/* this is a non-leaf container, we need to make up a good description */
|
||||||
|
// TODO: use a good description instead of just "another container"
|
||||||
|
xcb_image_text_8(
|
||||||
|
conn,
|
||||||
|
strlen("another container"),
|
||||||
|
parent->frame,
|
||||||
|
parent->gc,
|
||||||
|
con->deco_rect.x + 2,
|
||||||
|
con->deco_rect.y + 14, /* TODO: hardcoded */
|
||||||
|
"another container"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int indent_level = 0,
|
||||||
|
indent_mult = 0;
|
||||||
|
Con *il_parent = con->parent;
|
||||||
|
if (il_parent->type != L_STACKED) {
|
||||||
|
while (1) {
|
||||||
|
DLOG("il_parent = %p, layout = %d\n", il_parent, il_parent->layout);
|
||||||
|
if (il_parent->layout == L_STACKED)
|
||||||
|
indent_level++;
|
||||||
|
if (il_parent->type == CT_WORKSPACE)
|
||||||
|
break;
|
||||||
|
il_parent = il_parent->parent;
|
||||||
|
indent_mult++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DLOG("indent_level = %d, indent_mult = %d\n", indent_level, indent_mult);
|
||||||
|
int indent_px = (indent_level * 5) * indent_mult;
|
||||||
|
|
||||||
if (win->uses_net_wm_name)
|
if (win->uses_net_wm_name)
|
||||||
xcb_image_text_16(
|
xcb_image_text_16(
|
||||||
conn,
|
conn,
|
||||||
win->name_len,
|
win->name_len,
|
||||||
parent->frame,
|
parent->frame,
|
||||||
parent->gc,
|
parent->gc,
|
||||||
con->deco_rect.x,
|
con->deco_rect.x + 2 + indent_px,
|
||||||
con->deco_rect.y + 14, /* TODO: hardcoded */
|
con->deco_rect.y + 14, /* TODO: hardcoded */
|
||||||
(xcb_char2b_t*)win->name_x
|
(xcb_char2b_t*)win->name_x
|
||||||
);
|
);
|
||||||
|
@ -286,7 +355,7 @@ void x_draw_decoration(Con *con) {
|
||||||
win->name_len,
|
win->name_len,
|
||||||
parent->frame,
|
parent->frame,
|
||||||
parent->gc,
|
parent->gc,
|
||||||
con->deco_rect.x,
|
con->deco_rect.x + 2 + indent_px,
|
||||||
con->deco_rect.y + 14, /* TODO: hardcoded */
|
con->deco_rect.y + 14, /* TODO: hardcoded */
|
||||||
win->name_x
|
win->name_x
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue