draw leaf window decorations on ->frame instead of ->parent->frame

related to https://github.com/i3/i3/issues/3724
fixes https://github.com/i3/i3/issues/1966
This commit is contained in:
Michael Stapelberg 2022-11-03 23:11:32 +01:00 committed by Michael Stapelberg
parent 6e6af01b7a
commit d26ddcbfe5
14 changed files with 186 additions and 131 deletions

View File

@ -564,9 +564,7 @@ split container.
==== Default layout
In default layout, containers are placed horizontally or vertically next to
each other (depending on the +con->orientation+). If a child is a leaf node (as
opposed to a split container) and has border style "normal", appropriate space
will be reserved for its window decoration.
each other (depending on the +con->orientation+).
==== Stacked layout

View File

@ -410,6 +410,14 @@ deco_rect (map)::
The coordinates of the *window decoration* inside its container. These
coordinates are relative to the container and do not include the actual
client window.
actual_deco_rect (map)::
See +deco_rect+. i3 v4.22 changed the way title bars are rendered. Before
i3 v4.22, the deco_rect was always relative to the parent coordinates.
Starting with i3 v4.22, this remains true for tabbed/stacked containers
(actual_deco_rect is identical to deco_rect), but for normal-border leaf
containers within vertical/horizontal split containers, actual_deco_rect
is relative to the container itself. For more background, see
https://github.com/i3/i3/issues/1966
geometry (map)::
The original geometry the window specified when i3 mapped it. Used when
switching a window to floating mode, for example.

View File

@ -1501,23 +1501,6 @@ Tip: You can find an
https://github.com/Airblader/i3/wiki/Example-Configuration[example
configuration] that uses modes to illustrate various gap configurations.
[[gaps_artifacts]]
==== ⚠ Known issue with gaps: graphical artifacts (black rectangles)
The way i3 renders window title bars results in graphical artifacts (black
rectangles behind windows) when enabling gaps. In some circumstances, running a
compositor such as `picom` works around the artifacts.
Another workaround is to disable window title bars entirely:
------------------------
# You can also use any non-zero value if you'd like to have a border
default_border pixel 0
------------------------
See https://github.com/i3/i3/issues/3724[Issue #3724] for more details and
updates on this issue.
== Configuring i3bar
The bar at the bottom of your monitor is drawn by a separate process called

View File

@ -420,6 +420,14 @@ Con *con_descend_tiling_focused(Con *con);
*/
Con *con_descend_direction(Con *con, direction_t direction);
/**
* Returns whether the window decoration (title bar) should be drawn into the
* X11 frame window of this container (default) or into the X11 frame window of
* the parent container (for stacked/tabbed containers).
*
*/
bool con_draw_decoration_into_frame(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

View File

@ -404,6 +404,12 @@ void handle_button_press(xcb_button_press_event_t *event) {
}
/* Check if the click was on the decoration of a child */
if (con->window != NULL) {
if (rect_contains(con->deco_rect, event->event_x, event->event_y)) {
route_click(con, event, mod_pressed, CLICK_DECORATION);
return;
}
} else {
Con *child;
TAILQ_FOREACH_REVERSE (child, &(con->nodes_head), nodes_head, nodes) {
if (!rect_contains(child->deco_rect, event->event_x, event->event_y))
@ -412,6 +418,7 @@ void handle_button_press(xcb_button_press_event_t *event) {
route_click(child, event, mod_pressed, CLICK_DECORATION);
return;
}
}
if (event->child != XCB_NONE) {
DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");

View File

@ -1692,6 +1692,20 @@ static bool has_outer_gaps(gaps_t gaps) {
gaps.left > 0;
}
/*
* Returns whether the window decoration (title bar) should be drawn into the
* X11 frame window of this container (default) or into the X11 frame window of
* the parent container (for stacked/tabbed containers).
*
*/
bool con_draw_decoration_into_frame(Con *con) {
return con_is_leaf(con) &&
con->border_style == BS_NORMAL &&
(con->parent == NULL ||
(con->parent->layout != L_TABBED &&
con->parent->layout != L_STACKED));
}
/*
* 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
@ -1724,7 +1738,16 @@ Rect con_border_style_rect(Con *con) {
if (border_style == BS_NONE)
return (Rect){0, 0, 0, 0};
if (border_style == BS_NORMAL) {
const int deco_height = render_deco_height();
result = (Rect){border_width, 0, -(2 * border_width), -(border_width)};
if (con_draw_decoration_into_frame(con)) {
result = (Rect){
.x = border_width /* left */,
.y = deco_height,
.width = -(border_width /* left */ + border_width /* right */),
.height = -(border_width /* bottom */ + deco_height),
};
}
} else {
result = (Rect){border_width, border_width, -(2 * border_width), -(2 * border_width)};
}
@ -1828,23 +1851,17 @@ void con_set_border_style(Con *con, border_style_t border_style, int border_widt
* pixels. For the parent, we do the same also for the decoration. */
Con *parent = con->parent;
Rect bsr = con_border_style_rect(con);
int deco_height = (con->border_style == BS_NORMAL ? render_deco_height() : 0);
con->rect = rect_add(con->rect, bsr);
parent->rect = rect_add(parent->rect, bsr);
parent->rect.y += deco_height;
parent->rect.height -= deco_height;
/* Change the border style, get new border/decoration values. */
con->border_style = border_style;
con->current_border_width = border_width;
bsr = con_border_style_rect(con);
deco_height = (con->border_style == BS_NORMAL ? render_deco_height() : 0);
con->rect = rect_sub(con->rect, bsr);
parent->rect = rect_sub(parent->rect, bsr);
parent->rect.y -= deco_height;
parent->rect.height += deco_height;
}
/*

View File

@ -79,16 +79,22 @@ void floating_check_size(Con *floating_con, bool prefer_height) {
Rect floating_sane_max_dimensions;
Con *focused_con = con_descend_focused(floating_con);
DLOG("deco_rect.height = %d\n", focused_con->deco_rect.height);
Rect border_rect = con_border_style_rect(focused_con);
/* We have to do the opposite calculations that render_con() do
* to get the exact size we want. */
border_rect.width = -border_rect.width;
border_rect.width += 2 * focused_con->border_width;
border_rect.height = -border_rect.height;
/* undo x11 border */
border_rect.width += 2 * focused_con->border_width;
border_rect.height += 2 * focused_con->border_width;
if (con_border_style(focused_con) == BS_NORMAL) {
border_rect.height += render_deco_height();
}
DLOG("floating_check_size, want min width %d, min height %d, border extra: w=%d, h=%d\n",
floating_sane_min_width,
floating_sane_min_height,
border_rect.width,
border_rect.height);
i3Window *window = focused_con->window;
if (window != NULL) {
@ -319,9 +325,6 @@ bool floating_enable(Con *con, bool automatic) {
x_set_name(nc, name);
free(name);
/* find the height for the decorations */
int deco_height = render_deco_height();
DLOG("Original rect: (%d, %d) with %d x %d\n", con->rect.x, con->rect.y, con->rect.width, con->rect.height);
DLOG("Geometry = (%d, %d) with %d x %d\n", con->geometry.x, con->geometry.y, con->geometry.width, con->geometry.height);
nc->rect = con->geometry;
@ -352,15 +355,10 @@ bool floating_enable(Con *con, bool automatic) {
}
/* Add pixels for the decoration. */
Rect border_style_rect = con_border_style_rect(con);
Rect bsr = con_border_style_rect(con);
nc->rect.height -= border_style_rect.height;
nc->rect.width -= border_style_rect.width;
/* Add some more pixels for the title bar */
if (con_border_style(con) == BS_NORMAL) {
nc->rect.height += deco_height;
}
nc->rect.height -= bsr.height;
nc->rect.width -= bsr.width;
/* Honor the X11 border */
nc->rect.height += con->border_width * 2;
@ -406,14 +404,6 @@ bool floating_enable(Con *con, bool automatic) {
DLOG("Floating rect: (%d, %d) with %d x %d\n", nc->rect.x, nc->rect.y, nc->rect.width, nc->rect.height);
/* 5: Subtract the deco_height in order to make the floating window appear
* at precisely the position it specified in its original geometry (which
* is what applications might remember). */
deco_height = (con->border_style == BS_NORMAL ? render_deco_height() : 0);
nc->rect.y -= deco_height;
DLOG("Corrected y = %d (deco_height = %d)\n", nc->rect.y, deco_height);
/* render the cons to get initial window_rect correct */
render_con(nc);

View File

@ -214,6 +214,17 @@ static void handle_motion_notify(xcb_motion_notify_event_t *event) {
return;
/* see over which rect the user is */
if (con->window != NULL) {
if (rect_contains(con->deco_rect, event->event_x, event->event_y)) {
/* We found the rect, lets see if this window is focused */
if (TAILQ_FIRST(&(con->parent->focus_head)) == con)
return;
con_focus(con);
x_push_changes(croot);
return;
}
} else {
Con *current;
TAILQ_FOREACH_REVERSE (current, &(con->nodes_head), nodes_head, nodes) {
if (!rect_contains(current->deco_rect, event->event_x, event->event_y))
@ -228,6 +239,7 @@ static void handle_motion_notify(xcb_motion_notify_event_t *event) {
return;
}
}
}
/*
* Called when the keyboard mapping changes (for example by using Xmodmap),
@ -318,15 +330,9 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
Con *fullscreen = con_get_fullscreen_covering_ws(workspace);
if (fullscreen != con && con_is_floating(con) && con_is_leaf(con)) {
/* find the height for the decorations */
int deco_height = con->deco_rect.height;
/* we actually need to apply the size/position changes to the *parent*
* container */
Rect bsr = con_border_style_rect(con);
if (con->border_style == BS_NORMAL) {
bsr.y += deco_height;
bsr.height -= deco_height;
}
Con *floatingcon = con->parent;
Rect newrect = floatingcon->rect;

View File

@ -503,7 +503,15 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
y(integer, con->current_border_width);
dump_rect(gen, "rect", con->rect);
if (con_draw_decoration_into_frame(con)) {
Rect simulated_deco_rect = con->deco_rect;
simulated_deco_rect.x = con->rect.x - con->parent->rect.x;
simulated_deco_rect.y = con->rect.y - con->parent->rect.y;
dump_rect(gen, "deco_rect", simulated_deco_rect);
dump_rect(gen, "actual_deco_rect", con->deco_rect);
} else {
dump_rect(gen, "deco_rect", con->deco_rect);
}
dump_rect(gen, "window_rect", con->window_rect);
dump_rect(gen, "geometry", con->geometry);

View File

@ -23,6 +23,7 @@ static Con *to_focus;
static bool parsing_gaps;
static bool parsing_swallows;
static bool parsing_rect;
static bool parsing_actual_deco_rect;
static bool parsing_deco_rect;
static bool parsing_window_rect;
static bool parsing_geometry;
@ -61,7 +62,12 @@ static int json_start_map(void *ctx) {
TAILQ_INSERT_TAIL(&(json_node->swallow_head), current_swallow, matches);
swallow_is_empty = true;
} else {
if (!parsing_rect && !parsing_deco_rect && !parsing_window_rect && !parsing_geometry && !parsing_gaps) {
if (!parsing_rect &&
!parsing_actual_deco_rect &&
!parsing_deco_rect &&
!parsing_window_rect &&
!parsing_geometry &&
!parsing_gaps) {
if (last_key && strcasecmp(last_key, "floating_nodes") == 0) {
DLOG("New floating_node\n");
Con *ws = con_get_workspace(json_node);
@ -85,7 +91,13 @@ static int json_start_map(void *ctx) {
static int json_end_map(void *ctx) {
LOG("end of map\n");
if (!parsing_swallows && !parsing_rect && !parsing_deco_rect && !parsing_window_rect && !parsing_geometry && !parsing_gaps) {
if (!parsing_swallows &&
!parsing_rect &&
!parsing_actual_deco_rect &&
!parsing_deco_rect &&
!parsing_window_rect &&
!parsing_geometry &&
!parsing_gaps) {
/* Set a few default values to simplify manually crafted layout files. */
if (json_node->layout == L_DEFAULT) {
DLOG("Setting layout = L_SPLITH\n");
@ -195,6 +207,7 @@ static int json_end_map(void *ctx) {
parsing_gaps = false;
parsing_rect = false;
parsing_actual_deco_rect = false;
parsing_deco_rect = false;
parsing_window_rect = false;
parsing_geometry = false;
@ -253,6 +266,9 @@ static int json_key(void *ctx, const unsigned char *val, size_t len) {
if (strcasecmp(last_key, "rect") == 0)
parsing_rect = true;
if (strcasecmp(last_key, "actual_deco_rect") == 0)
parsing_actual_deco_rect = true;
if (strcasecmp(last_key, "deco_rect") == 0)
parsing_deco_rect = true;
@ -674,6 +690,7 @@ void tree_append_json(Con *con, const char *buf, const size_t len, char **errorm
incomplete = 0;
parsing_swallows = false;
parsing_rect = false;
parsing_actual_deco_rect = false;
parsing_deco_rect = false;
parsing_window_rect = false;
parsing_geometry = false;

View File

@ -69,9 +69,6 @@ void render_con(Con *con) {
con->rect = rect_add(con->rect, inset);
}
inset.height = 0;
if (con->deco_rect.width != 0 && con->deco_rect.height != 0) {
con->deco_rect = rect_add(con->deco_rect, inset);
}
params.x = con->rect.x;
params.y = con->rect.y;
@ -84,17 +81,27 @@ void render_con(Con *con) {
if (con->window) {
/* depending on the border style, the rect of the child window
* needs to be smaller */
Rect *inset = &(con->window_rect);
*inset = (Rect){0, 0, con->rect.width, con->rect.height};
Rect inset = (Rect){
.x = 0,
.y = 0,
.width = con->rect.width,
.height = con->rect.height,
};
if (con->fullscreen_mode == CF_NONE) {
*inset = rect_add(*inset, con_border_style_rect(con));
DLOG("deco_rect.height = %d\n", con->deco_rect.height);
Rect bsr = con_border_style_rect(con);
DLOG("bsr at %dx%d with size %dx%d\n",
bsr.x, bsr.y, bsr.width, bsr.height);
inset = rect_add(inset, bsr);
}
/* Obey x11 border */
inset->width -= (2 * con->border_width);
inset->height -= (2 * con->border_width);
inset.width -= (2 * con->border_width);
inset.height -= (2 * con->border_width);
*inset = rect_sanitize_dimensions(*inset);
inset = rect_sanitize_dimensions(inset);
con->window_rect = inset;
/* NB: We used to respect resize increment size hints for tiling
* windows up until commit 0db93d9 here. However, since all terminal
@ -102,7 +109,8 @@ void render_con(Con *con) {
* can (by providing their fake-transparency or background color), this
* code was removed. See also https://bugs.i3wm.org/540 */
DLOG("child will be at %dx%d with size %dx%d\n", inset->x, inset->y, inset->width, inset->height);
DLOG("child will be at %dx%d with size %dx%d\n",
inset.x, inset.y, inset.width, inset.height);
}
/* Check for fullscreen nodes */
@ -159,6 +167,18 @@ void render_con(Con *con) {
child->rect.x, child->rect.y, child->rect.width, child->rect.height);
x_raise_con(child);
render_con(child);
/* render_con_split() sets the deco_rect width based on the rect
* width, but the render_con() call updates the rect width by
* applying gaps, so we need to update deco_rect. */
if (con->layout == L_SPLITH || con->layout == L_SPLITV) {
if (con_is_leaf(child)) {
if (child->border_style == BS_NORMAL) {
child->deco_rect.width = child->rect.width;
}
}
}
i++;
}
@ -381,11 +401,8 @@ static void render_con_split(Con *con, Con *child, render_params *p, int i) {
if (con_is_leaf(child)) {
if (child->border_style == BS_NORMAL) {
/* TODO: make a function for relative coords? */
child->deco_rect.x = child->rect.x - con->rect.x;
child->deco_rect.y = child->rect.y - con->rect.y;
child->rect.y += p->deco_height;
child->rect.height -= p->deco_height;
child->deco_rect.x = 0;
child->deco_rect.y = 0;
child->deco_rect.width = child->rect.width;
child->deco_rect.height = p->deco_height;

View File

@ -10,23 +10,6 @@
#include "all.h"
static xcb_window_t create_drop_indicator(Rect rect);
/*
* Includes decoration (container title) to the container's rect. This way we
* can find the correct drop target if the mouse is on a container's
* decoration.
*
*/
static Rect con_rect_plus_deco_height(Con *con) {
Rect rect = con->rect;
rect.height += con->deco_rect.height;
if (rect.y < con->deco_rect.height) {
rect.y = 0;
} else {
rect.y -= con->deco_rect.height;
}
return rect;
}
static bool is_tiling_drop_target(Con *con) {
if (!con_has_managed_window(con) ||
con_is_floating(con) ||
@ -90,7 +73,7 @@ bool has_drop_targets(void) {
static Con *find_drop_target(uint32_t x, uint32_t y) {
Con *con;
TAILQ_FOREACH (con, &all_cons, all_cons) {
Rect rect = con_rect_plus_deco_height(con);
Rect rect = con->rect;
if (!rect_contains(rect, x, y) ||
!is_tiling_drop_target(con)) {
continue;
@ -186,7 +169,7 @@ DRAGGING_CB(drag_callback) {
return;
}
Rect rect = con_rect_plus_deco_height(target);
Rect rect = target->rect;
direction_t direction = 0;
drop_type_t drop_type = DT_CENTER;

59
src/x.c
View File

@ -355,29 +355,27 @@ void x_window_kill(xcb_window_t window, kill_window_t kill_window) {
free(event);
}
static void x_draw_title_border(Con *con, struct deco_render_params *p) {
assert(con->parent != NULL);
static void x_draw_title_border(Con *con, struct deco_render_params *p, surface_t *dest_surface) {
Rect *dr = &(con->deco_rect);
/* Left */
draw_util_rectangle(&(con->parent->frame_buffer), p->color->border,
draw_util_rectangle(dest_surface, p->color->border,
dr->x, dr->y, 1, dr->height);
/* Right */
draw_util_rectangle(&(con->parent->frame_buffer), p->color->border,
draw_util_rectangle(dest_surface, p->color->border,
dr->x + dr->width - 1, dr->y, 1, dr->height);
/* Top */
draw_util_rectangle(&(con->parent->frame_buffer), p->color->border,
draw_util_rectangle(dest_surface, p->color->border,
dr->x, dr->y, dr->width, 1);
/* Bottom */
draw_util_rectangle(&(con->parent->frame_buffer), p->color->border,
draw_util_rectangle(dest_surface, p->color->border,
dr->x, dr->y + dr->height - 1, dr->width, 1);
}
static void x_draw_decoration_after_title(Con *con, struct deco_render_params *p) {
static void x_draw_decoration_after_title(Con *con, struct deco_render_params *p, surface_t *dest_surface) {
assert(con->parent != NULL);
Rect *dr = &(con->deco_rect);
@ -389,7 +387,7 @@ static void x_draw_decoration_after_title(Con *con, struct deco_render_params *p
/* We actually only redraw the far right two pixels as that is the
* distance we keep from the edge (not the entire border width).
* Redrawing the entire border would cause text to be cut off. */
draw_util_rectangle(&(con->parent->frame_buffer), p->color->background,
draw_util_rectangle(dest_surface, p->color->background,
dr->x + dr->width - 2 * logical_px(1),
dr->y,
2 * logical_px(1),
@ -397,7 +395,7 @@ static void x_draw_decoration_after_title(Con *con, struct deco_render_params *p
}
/* Redraw the border. */
x_draw_title_border(con, p);
x_draw_title_border(con, p, dest_surface);
}
/*
@ -593,16 +591,24 @@ void x_draw_decoration(Con *con) {
}
}
surface_t *dest_surface = &(parent->frame_buffer);
if (con_draw_decoration_into_frame(con)) {
DLOG("using con->frame_buffer (for con->name=%s) as dest_surface\n", con->name);
dest_surface = &(con->frame_buffer);
} else {
DLOG("sticking to parent->frame_buffer = %p\n", dest_surface);
}
DLOG("dest_surface %p is %d x %d (id=0x%08x)\n", dest_surface, dest_surface->width, dest_surface->height, dest_surface->id);
/* If the parent hasn't been set up yet, skip the decoration rendering
* for now. */
if (parent->frame_buffer.id == XCB_NONE)
if (dest_surface->id == XCB_NONE)
goto copy_pixmaps;
/* For the first child, we clear the parent pixmap to ensure there's no
* garbage left on there. This is important to avoid tearing when using
* transparency. */
if (con == TAILQ_FIRST(&(con->parent->nodes_head))) {
draw_util_clear_surface(&(con->parent->frame_buffer), COLOR_TRANSPARENT);
FREE(con->parent->deco_render_params);
}
@ -612,11 +618,13 @@ void x_draw_decoration(Con *con) {
goto copy_pixmaps;
/* 4: paint the bar */
draw_util_rectangle(&(parent->frame_buffer), p->color->background,
DLOG("con->deco_rect = (x=%d, y=%d, w=%d, h=%d)\n",
con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height);
draw_util_rectangle(dest_surface, p->color->background,
con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height);
/* 5: draw title border */
x_draw_title_border(con, p);
x_draw_title_border(con, p, dest_surface);
/* 6: draw the icon and title */
int text_offset_y = (con->deco_rect.height - config.font.height) / 2;
@ -651,7 +659,7 @@ void x_draw_decoration(Con *con) {
? title_padding
: deco_width - mark_width - title_padding;
draw_util_text(mark, &(parent->frame_buffer),
draw_util_text(mark, dest_surface,
p->color->text, p->color->background,
con->deco_rect.x + mark_offset_x,
con->deco_rect.y + text_offset_y, mark_width);
@ -725,7 +733,7 @@ void x_draw_decoration(Con *con) {
break;
}
draw_util_text(title, &(parent->frame_buffer),
draw_util_text(title, dest_surface,
p->color->text, p->color->background,
con->deco_rect.x + title_offset_x,
con->deco_rect.y + text_offset_y,
@ -733,7 +741,7 @@ void x_draw_decoration(Con *con) {
if (has_icon) {
draw_util_image(
win->icon,
&(parent->frame_buffer),
dest_surface,
con->deco_rect.x + icon_offset_x,
con->deco_rect.y + logical_px(1),
icon_size,
@ -744,7 +752,7 @@ void x_draw_decoration(Con *con) {
I3STRING_FREE(title);
}
x_draw_decoration_after_title(con, p);
x_draw_decoration_after_title(con, p, dest_surface);
copy_pixmaps:
draw_util_copy_surface(&(con->frame_buffer), &(con->frame), 0, 0, 0, 0, con->rect.width, con->rect.height);
}
@ -891,7 +899,7 @@ void x_push_node(Con *con) {
FREE(state->name);
}
if (con->window == NULL) {
if (con->window == NULL && (con->layout == L_STACKED || con->layout == L_TABBED)) {
/* Calculate the height of all window decorations which will be drawn on to
* this frame. */
uint32_t max_y = 0, max_height = 0;
@ -905,6 +913,9 @@ void x_push_node(Con *con) {
rect.height = max_y + max_height;
if (rect.height == 0)
con->mapped = false;
} else if (con->window == NULL) {
/* not a stacked or tabbed split container */
con->mapped = false;
}
bool need_reshape = false;
@ -949,10 +960,11 @@ void x_push_node(Con *con) {
/* The pixmap of a borderless leaf container will not be used except
* for the titlebar in a stack or tabs (issue #1013). */
bool is_pixmap_needed = (con->border_style != BS_NONE ||
!con_is_leaf(con) ||
con->parent->layout == L_STACKED ||
con->parent->layout == L_TABBED);
bool is_pixmap_needed = ((con_is_leaf(con) && con->border_style != BS_NONE) ||
con->layout == L_STACKED ||
con->layout == L_TABBED);
DLOG("Con %p (layout %d), is_pixmap_needed = %s, rect.height = %d\n",
con, con->layout, is_pixmap_needed ? "yes" : "no", con->rect.height);
/* The root con and output cons will never require a pixmap. In particular for the
* __i3 output, this will likely not work anyway because it might be ridiculously
@ -999,6 +1011,7 @@ void x_push_node(Con *con) {
int width = MAX((int32_t)rect.width, 1);
int height = MAX((int32_t)rect.height, 1);
DLOG("creating %d x %d pixmap for con %p (con->frame_buffer.id = (pixmap_t)0x%08x) (con->frame.id (drawable_t)0x%08x)\n", width, height, con, con->frame_buffer.id, con->frame.id);
xcb_create_pixmap(conn, win_depth, con->frame_buffer.id, con->frame.id, width, height);
draw_util_surface_init(conn, &(con->frame_buffer), con->frame_buffer.id,
get_visualtype_by_id(get_visualid_by_depth(win_depth)), width, height);

View File

@ -50,7 +50,7 @@ $target = get_focused($ws);
$A = $cons[0];
$C = $cons[1]->{nodes}[1];
$y = $C->{rect}->{y} - 0.5 * $C->{deco_rect}->{height};
$y = $C->{rect}->{y} + 0.5 * $C->{deco_rect}->{height};
# make sure that B is the focus head of its parent
cmd '[id="' . $B->{id} . '"] focus';