]> git.sur5r.net Git - i3/i3/commitdiff
Rendering fixes for stacking mode
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 13 Nov 2010 21:39:59 +0000 (22:39 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 13 Nov 2010 21:39:59 +0000 (22:39 +0100)
include/con.h
src/con.c
src/render.c
src/tree.c
src/x.c

index 65e6421256b6a9425f7cf69a45e3b54814e4db07..bdf0b2a2c675fbec7f7663e908510cac34b5c58b 100644 (file)
@@ -135,7 +135,7 @@ int con_orientation(Con *con);
  */
 Con *con_next_focused(Con *con);
 
-/*
+/**
  * 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
  * 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);
 
+/**
+ * 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
index 8121bf0e8eccbab2b296417c47d28c75f208a24b..e92322734234d1646e6620f41be0bc6a00a62f45 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -41,12 +41,10 @@ Con *con_new(Con *parent) {
     /* TODO: remove window coloring after test-phase */
     LOG("color %s\n", colors[cnt]);
     new->name = strdup(colors[cnt]);
-#if 0
-    uint32_t cp = get_colorpixel(colors[cnt]);
+    //uint32_t cp = get_colorpixel(colors[cnt]);
     cnt++;
     if ((cnt % (sizeof(colors) / sizeof(char*))) == 0)
         cnt = 0;
-#endif
 
     x_con_init(new);
 
@@ -453,14 +451,32 @@ Con *con_next_focused(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};
 
-    if (con->border_style == BS_1PIXEL)
+    case BS_1PIXEL:
         return (Rect){1, 1, -2, -2};
 
-    if (con->border_style == BS_NONE)
+    case BS_NONE:
         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;
 }
index dcd5f58e996791104d77aa48ffc30420842f4a60..ddb3751a91bacdcf50be54eea6a79cba4e337f0b 100644 (file)
@@ -167,8 +167,13 @@ void render_con(Con *con) {
     /* in a stacking container, we ensure the focused client is raised */
     if (con->layout == L_STACKED) {
         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);
+            /* 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) {
index 244b5ba9bd7b54f61c4639aec8ff4748fafa6956..3378857666bc10a1485c20c4bce5c83e8bdada52 100644 (file)
@@ -233,7 +233,7 @@ void tree_split(Con *con, orientation_t orientation) {
     /* if we are in a container whose parent contains only one
      * child and has the same orientation like we are trying to
      * 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))) {
         DLOG("Not splitting the same way again\n");
         return;
@@ -353,6 +353,7 @@ void tree_next(char way, orientation_t orientation) {
     while (!TAILQ_EMPTY(&(next->focus_head)))
         next = TAILQ_FIRST(&(next->focus_head));
 
+    DLOG("focusing %p\n", next);
     con_focus(next);
 }
 
diff --git a/src/x.c b/src/x.c
index ae24f35b408791f722189d683b4e789d18a405bf..566864ce08175c672298ef1c18fd0c1fd37b3f8b 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -222,8 +222,13 @@ void x_window_kill(xcb_window_t window) {
  *
  */
 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;
+    DLOG("decoration should be rendered for con %p\n", con);
 
     /* 1: find out which colors to use */
     struct Colortriple *color;
@@ -237,15 +242,48 @@ void x_draw_decoration(Con *con) {
         color = &config.client.unfocused;
 
     Con *parent = con->parent;
+    int border_style = con_border_style(con);
 
     /* 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_rectangle_t rect = { 0, 0, con->rect.width, con->rect.height };
-        xcb_poly_fill_rectangle(conn, con->frame, con->gc, 1, &rect);
+        xcb_point_t points[] = {
+            { 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;
+    }
 
     /* 3: paint the bar */
     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 */
 
     /* 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_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)
         xcb_image_text_16(
             conn,
             win->name_len,
             parent->frame,
             parent->gc,
-            con->deco_rect.x,
+            con->deco_rect.x + 2 + indent_px,
             con->deco_rect.y + 14, /* TODO: hardcoded */
             (xcb_char2b_t*)win->name_x
         );
@@ -286,7 +355,7 @@ void x_draw_decoration(Con *con) {
             win->name_len,
             parent->frame,
             parent->gc,
-            con->deco_rect.x,
+            con->deco_rect.x + 2 + indent_px,
             con->deco_rect.y + 14, /* TODO: hardcoded */
             win->name_x
         );