Re-implement rendering to pixmaps (double-buffering) and caching decorations
This commit is contained in:
parent
e835888a9e
commit
b25477b15e
|
@ -86,6 +86,33 @@ struct reservedpx {
|
||||||
uint32_t bottom;
|
uint32_t bottom;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a width/height pair, used as part of deco_render_params to check
|
||||||
|
* whether the rects width/height have changed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct width_height {
|
||||||
|
uint32_t w;
|
||||||
|
uint32_t h;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the parameters for rendering a window decoration. This structure is
|
||||||
|
* cached in every Con and no re-rendering will be done if the parameters have
|
||||||
|
* not changed (only the pixmaps will be copied).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct deco_render_params {
|
||||||
|
struct Colortriple *color;
|
||||||
|
int border_style;
|
||||||
|
struct width_height con_rect;
|
||||||
|
struct width_height con_window_rect;
|
||||||
|
struct width_height con_deco_rect;
|
||||||
|
uint32_t background;
|
||||||
|
bool con_is_leaf;
|
||||||
|
xcb_font_t font;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for the cache of colorpixels.
|
* Used for the cache of colorpixels.
|
||||||
*
|
*
|
||||||
|
@ -96,22 +123,6 @@ struct Colorpixel {
|
||||||
SLIST_ENTRY(Colorpixel) colorpixels;
|
SLIST_ENTRY(Colorpixel) colorpixels;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cached_Pixmap {
|
|
||||||
xcb_pixmap_t id;
|
|
||||||
|
|
||||||
/* We’re going to paint on it, so a graphics context will be needed */
|
|
||||||
xcb_gcontext_t gc;
|
|
||||||
|
|
||||||
/* The rect with which the pixmap was created */
|
|
||||||
Rect rect;
|
|
||||||
|
|
||||||
/* The rect of the object to which this pixmap belongs. Necessary to
|
|
||||||
* find out when we need to re-create the pixmap. */
|
|
||||||
Rect *referred_rect;
|
|
||||||
|
|
||||||
xcb_drawable_t referred_drawable;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ignore_Event {
|
struct Ignore_Event {
|
||||||
int sequence;
|
int sequence;
|
||||||
time_t added;
|
time_t added;
|
||||||
|
@ -236,6 +247,9 @@ struct Window {
|
||||||
* application supports _NET_WM_NAME, in COMPOUND_TEXT otherwise). */
|
* application supports _NET_WM_NAME, in COMPOUND_TEXT otherwise). */
|
||||||
char *name_x;
|
char *name_x;
|
||||||
|
|
||||||
|
/** Flag to force re-rendering the decoration upon changes */
|
||||||
|
bool name_x_changed;
|
||||||
|
|
||||||
/** The name of the window as used in JSON (in UTF-8 if the application
|
/** The name of the window as used in JSON (in UTF-8 if the application
|
||||||
* supports _NET_WM_NAME, in COMPOUND_TEXT otherwise) */
|
* supports _NET_WM_NAME, in COMPOUND_TEXT otherwise) */
|
||||||
char *name_json;
|
char *name_json;
|
||||||
|
@ -353,9 +367,14 @@ struct Con {
|
||||||
* inside this container (if any) sets the urgency hint, for example. */
|
* inside this container (if any) sets the urgency hint, for example. */
|
||||||
bool urgent;
|
bool urgent;
|
||||||
|
|
||||||
/* ids/gc for the frame window */
|
/* ids/pixmap/graphics context for the frame window */
|
||||||
xcb_window_t frame;
|
xcb_window_t frame;
|
||||||
xcb_gcontext_t gc;
|
xcb_pixmap_t pixmap;
|
||||||
|
xcb_gcontext_t pm_gc;
|
||||||
|
bool pixmap_recreated;
|
||||||
|
|
||||||
|
/** Cache for the decoration rendering */
|
||||||
|
struct deco_render_params *deco_render_params;
|
||||||
|
|
||||||
/* Only workspace-containers can have floating clients */
|
/* Only workspace-containers can have floating clients */
|
||||||
TAILQ_HEAD(floating_head, Con) floating_head;
|
TAILQ_HEAD(floating_head, Con) floating_head;
|
||||||
|
|
|
@ -135,15 +135,6 @@ void xcb_get_numlock_mask(xcb_connection_t *conn);
|
||||||
*/
|
*/
|
||||||
void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window);
|
void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Prepares the given Cached_Pixmap for usage (checks whether the size of the
|
|
||||||
* object this pixmap is related to (e.g. a window) has changed and re-creates
|
|
||||||
* the pixmap if so).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void cached_pixmap_prepare(xcb_connection_t *conn, struct Cached_Pixmap *pixmap);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the width of the given text (16-bit characters, UCS) with given
|
* Calculate the width of the given text (16-bit characters, UCS) with given
|
||||||
* real length (amount of glyphs) using the given font.
|
* real length (amount of glyphs) using the given font.
|
||||||
|
|
|
@ -167,6 +167,7 @@ void tree_close(Con *con, bool kill_window, bool dont_kill_parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
free(con->name);
|
free(con->name);
|
||||||
|
FREE(con->deco_render_params);
|
||||||
TAILQ_REMOVE(&all_cons, con, all_cons);
|
TAILQ_REMOVE(&all_cons, con, all_cons);
|
||||||
free(con);
|
free(con);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ void window_update_name(i3Window *win, xcb_get_property_reply_t *prop) {
|
||||||
win->name_json = new_name;
|
win->name_json = new_name;
|
||||||
win->name_x = ucs2_name;
|
win->name_x = ucs2_name;
|
||||||
win->name_len = len;
|
win->name_len = len;
|
||||||
|
win->name_x_changed = true;
|
||||||
LOG("_NET_WM_NAME changed to \"%s\"\n", win->name_json);
|
LOG("_NET_WM_NAME changed to \"%s\"\n", win->name_json);
|
||||||
|
|
||||||
win->uses_net_wm_name = true;
|
win->uses_net_wm_name = true;
|
||||||
|
@ -104,6 +105,7 @@ void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop) {
|
||||||
win->name_x = new_name;
|
win->name_x = new_name;
|
||||||
win->name_json = sstrdup(new_name);
|
win->name_json = sstrdup(new_name);
|
||||||
win->name_len = strlen(new_name);
|
win->name_len = strlen(new_name);
|
||||||
|
win->name_x_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
131
src/x.c
131
src/x.c
|
@ -84,8 +84,6 @@ void x_con_init(Con *con) {
|
||||||
|
|
||||||
Rect dims = { -15, -15, 10, 10 };
|
Rect dims = { -15, -15, 10, 10 };
|
||||||
con->frame = create_window(conn, dims, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values);
|
con->frame = create_window(conn, dims, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values);
|
||||||
con->gc = xcb_generate_id(conn);
|
|
||||||
xcb_create_gc(conn, con->gc, con->frame, 0, 0);
|
|
||||||
|
|
||||||
struct con_state *state = scalloc(sizeof(struct con_state));
|
struct con_state *state = scalloc(sizeof(struct con_state));
|
||||||
state->id = con->frame;
|
state->id = con->frame;
|
||||||
|
@ -230,6 +228,7 @@ void x_window_kill(xcb_window_t window) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void x_draw_decoration(Con *con) {
|
void x_draw_decoration(Con *con) {
|
||||||
|
const Con *parent = con->parent;
|
||||||
/* This code needs to run for:
|
/* This code needs to run for:
|
||||||
* • leaf containers
|
* • leaf containers
|
||||||
* • non-leaf containers which are in a stacked/tabbed container
|
* • non-leaf containers which are in a stacked/tabbed container
|
||||||
|
@ -238,30 +237,61 @@ void x_draw_decoration(Con *con) {
|
||||||
* • floating containers (they don’t have a decoration)
|
* • floating containers (they don’t have a decoration)
|
||||||
*/
|
*/
|
||||||
if ((!con_is_leaf(con) &&
|
if ((!con_is_leaf(con) &&
|
||||||
con->parent->layout != L_STACKED &&
|
parent->layout != L_STACKED &&
|
||||||
con->parent->layout != L_TABBED) ||
|
parent->layout != L_TABBED) ||
|
||||||
con->type == CT_FLOATING_CON)
|
con->type == CT_FLOATING_CON)
|
||||||
return;
|
return;
|
||||||
DLOG("decoration should be rendered for con %p\n", con);
|
DLOG("decoration should be rendered for con %p\n", con);
|
||||||
|
|
||||||
/* 1: find out which colors to use */
|
/* Skip containers whose height is 0 (for example empty dockareas) */
|
||||||
struct Colortriple *color;
|
if (con->rect.height == 0) {
|
||||||
|
DLOG("height == 0, not rendering\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1: build deco_params and compare with cache */
|
||||||
|
struct deco_render_params *p = scalloc(sizeof(struct deco_render_params));
|
||||||
|
|
||||||
|
/* find out which colors to use */
|
||||||
if (con->urgent)
|
if (con->urgent)
|
||||||
color = &config.client.urgent;
|
p->color = &config.client.urgent;
|
||||||
else if (con == focused)
|
else if (con == focused)
|
||||||
color = &config.client.focused;
|
p->color = &config.client.focused;
|
||||||
else if (con == TAILQ_FIRST(&(con->parent->focus_head)))
|
else if (con == TAILQ_FIRST(&(parent->focus_head)))
|
||||||
color = &config.client.focused_inactive;
|
p->color = &config.client.focused_inactive;
|
||||||
else
|
else
|
||||||
color = &config.client.unfocused;
|
p->color = &config.client.unfocused;
|
||||||
|
|
||||||
Con *parent = con->parent;
|
p->border_style = con_border_style(con);
|
||||||
int border_style = con_border_style(con);
|
|
||||||
|
|
||||||
/* 2: draw the client.background, but only for the parts around the client_rect */
|
|
||||||
Rect *r = &(con->rect);
|
Rect *r = &(con->rect);
|
||||||
Rect *w = &(con->window_rect);
|
Rect *w = &(con->window_rect);
|
||||||
|
p->con_rect = (struct width_height){ r->width, r->height };
|
||||||
|
p->con_window_rect = (struct width_height){ w->width, w->height };
|
||||||
|
p->con_deco_rect = (struct width_height){ con->deco_rect.width, con->deco_rect.height };
|
||||||
|
p->background = config.client.background;
|
||||||
|
p->con_is_leaf = con_is_leaf(con);
|
||||||
|
p->font = config.font.id;
|
||||||
|
|
||||||
|
if (con->deco_render_params != NULL &&
|
||||||
|
(con->window == NULL || !con->window->name_x_changed) &&
|
||||||
|
!con->parent->pixmap_recreated &&
|
||||||
|
memcmp(p, con->deco_render_params, sizeof(struct deco_render_params)) == 0) {
|
||||||
|
DLOG("CACHE HIT, copying existing pixmaps\n");
|
||||||
|
free(p);
|
||||||
|
goto copy_pixmaps;
|
||||||
|
}
|
||||||
|
|
||||||
|
DLOG("CACHE MISS\n");
|
||||||
|
FREE(con->deco_render_params);
|
||||||
|
con->deco_render_params = p;
|
||||||
|
|
||||||
|
if (con->window != NULL && con->window->name_x_changed)
|
||||||
|
con->window->name_x_changed = false;
|
||||||
|
|
||||||
|
con->parent->pixmap_recreated = false;
|
||||||
|
|
||||||
|
/* 2: draw the client.background, but only for the parts around the client_rect */
|
||||||
xcb_rectangle_t background[] = {
|
xcb_rectangle_t background[] = {
|
||||||
/* top area */
|
/* top area */
|
||||||
{ 0, con->deco_rect.height, r->width, w->y },
|
{ 0, con->deco_rect.height, r->width, w->y },
|
||||||
|
@ -280,11 +310,11 @@ void x_draw_decoration(Con *con) {
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xcb_change_gc_single(conn, con->gc, XCB_GC_FOREGROUND, config.client.background);
|
xcb_change_gc_single(conn, con->pm_gc, XCB_GC_FOREGROUND, config.client.background);
|
||||||
xcb_poly_fill_rectangle(conn, con->frame, con->gc, sizeof(background) / sizeof(xcb_rectangle_t), background);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, sizeof(background) / sizeof(xcb_rectangle_t), background);
|
||||||
|
|
||||||
/* 3: draw a rectangle in border color around the client */
|
/* 3: draw a rectangle in border color around the client */
|
||||||
if (border_style != BS_NONE && con_is_leaf(con)) {
|
if (p->border_style != BS_NONE && p->con_is_leaf) {
|
||||||
Rect br = con_border_style_rect(con);
|
Rect br = con_border_style_rect(con);
|
||||||
#if 0
|
#if 0
|
||||||
DLOG("con->rect spans %d x %d\n", con->rect.width, con->rect.height);
|
DLOG("con->rect spans %d x %d\n", con->rect.width, con->rect.height);
|
||||||
|
@ -296,48 +326,53 @@ void x_draw_decoration(Con *con) {
|
||||||
* (left, bottom and right part). We don’t just fill the whole
|
* (left, bottom and right part). We don’t just fill the whole
|
||||||
* rectangle because some childs are not freely resizable and we want
|
* rectangle because some childs are not freely resizable and we want
|
||||||
* their background color to "shine through". */
|
* their background color to "shine through". */
|
||||||
xcb_change_gc_single(conn, con->gc, XCB_GC_FOREGROUND, color->background);
|
xcb_change_gc_single(conn, con->pm_gc, XCB_GC_FOREGROUND, p->color->background);
|
||||||
xcb_rectangle_t borders[] = {
|
xcb_rectangle_t borders[] = {
|
||||||
{ 0, 0, br.x, r->height },
|
{ 0, 0, br.x, r->height },
|
||||||
{ 0, r->height + br.height + br.y, r->width, r->height },
|
{ 0, r->height + br.height + br.y, r->width, r->height },
|
||||||
{ r->width + br.width + br.x, 0, r->width, r->height }
|
{ r->width + br.width + br.x, 0, r->width, r->height }
|
||||||
};
|
};
|
||||||
xcb_poly_fill_rectangle(conn, con->frame, con->gc, 3, borders);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 3, borders);
|
||||||
/* 1pixel border needs an additional line at the top */
|
/* 1pixel border needs an additional line at the top */
|
||||||
if (border_style == BS_1PIXEL) {
|
if (p->border_style == BS_1PIXEL) {
|
||||||
xcb_rectangle_t topline = { br.x, 0, con->rect.width + br.width + br.x, br.y };
|
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);
|
xcb_poly_fill_rectangle(conn, con->pixmap, con->pm_gc, 1, &topline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if this is a borderless/1pixel window, we don’t * need to render the
|
/* if this is a borderless/1pixel window, we don’t * need to render the
|
||||||
* decoration. */
|
* decoration. */
|
||||||
if (border_style != BS_NORMAL) {
|
if (p->border_style != BS_NORMAL) {
|
||||||
DLOG("border style not BS_NORMAL, aborting rendering of decoration\n");
|
DLOG("border style not BS_NORMAL, aborting rendering of decoration\n");
|
||||||
return;
|
goto copy_pixmaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4: paint the bar */
|
/* 4: paint the bar */
|
||||||
xcb_change_gc_single(conn, parent->gc, XCB_GC_FOREGROUND, color->background);
|
xcb_change_gc_single(conn, parent->pm_gc, XCB_GC_FOREGROUND, p->color->background);
|
||||||
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
xcb_rectangle_t drect = { con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height };
|
xcb_rectangle_t drect = { con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height };
|
||||||
xcb_poly_fill_rectangle(conn, parent->frame, parent->gc, 1, &drect);
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
|
xcb_poly_fill_rectangle(conn, parent->pixmap, parent->pm_gc, 1, &drect);
|
||||||
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
|
|
||||||
/* 5: draw the two lines in border color */
|
/* 5: draw the two lines in border color */
|
||||||
xcb_draw_line(conn, parent->frame, parent->gc, color->border,
|
xcb_draw_line(conn, parent->pixmap, parent->pm_gc, p->color->border,
|
||||||
con->deco_rect.x, /* x */
|
con->deco_rect.x, /* x */
|
||||||
con->deco_rect.y, /* y */
|
con->deco_rect.y, /* y */
|
||||||
con->deco_rect.x + con->deco_rect.width, /* to_x */
|
con->deco_rect.x + con->deco_rect.width, /* to_x */
|
||||||
con->deco_rect.y); /* to_y */
|
con->deco_rect.y); /* to_y */
|
||||||
xcb_draw_line(conn, parent->frame, parent->gc, color->border,
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
|
xcb_draw_line(conn, parent->pixmap, parent->pm_gc, p->color->border,
|
||||||
con->deco_rect.x, /* x */
|
con->deco_rect.x, /* x */
|
||||||
con->deco_rect.y + con->deco_rect.height - 1, /* y */
|
con->deco_rect.y + con->deco_rect.height - 1, /* y */
|
||||||
con->deco_rect.x + con->deco_rect.width, /* to_x */
|
con->deco_rect.x + con->deco_rect.width, /* to_x */
|
||||||
con->deco_rect.y + con->deco_rect.height - 1); /* to_y */
|
con->deco_rect.y + con->deco_rect.height - 1); /* to_y */
|
||||||
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
|
|
||||||
/* 6: draw the title */
|
/* 6: draw the title */
|
||||||
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
|
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
|
||||||
uint32_t values[] = { color->text, color->background, config.font.id };
|
uint32_t values[] = { p->color->text, p->color->background, config.font.id };
|
||||||
xcb_change_gc(conn, parent->gc, mask, values);
|
xcb_change_gc(conn, parent->pm_gc, mask, values);
|
||||||
int text_offset_y = config.font.height + (con->deco_rect.height - config.font.height) / 2 - 1;
|
int text_offset_y = config.font.height + (con->deco_rect.height - config.font.height) / 2 - 1;
|
||||||
|
|
||||||
struct Window *win = con->window;
|
struct Window *win = con->window;
|
||||||
|
@ -347,13 +382,14 @@ void x_draw_decoration(Con *con) {
|
||||||
xcb_image_text_8(
|
xcb_image_text_8(
|
||||||
conn,
|
conn,
|
||||||
strlen("another container"),
|
strlen("another container"),
|
||||||
parent->frame,
|
parent->pixmap,
|
||||||
parent->gc,
|
parent->pm_gc,
|
||||||
con->deco_rect.x + 2,
|
con->deco_rect.x + 2,
|
||||||
con->deco_rect.y + text_offset_y,
|
con->deco_rect.y + text_offset_y,
|
||||||
"another container"
|
"another container"
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
|
goto copy_pixmaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
int indent_level = 0,
|
int indent_level = 0,
|
||||||
|
@ -377,8 +413,8 @@ void x_draw_decoration(Con *con) {
|
||||||
xcb_image_text_16(
|
xcb_image_text_16(
|
||||||
conn,
|
conn,
|
||||||
win->name_len,
|
win->name_len,
|
||||||
parent->frame,
|
parent->pixmap,
|
||||||
parent->gc,
|
parent->pm_gc,
|
||||||
con->deco_rect.x + 2 + indent_px,
|
con->deco_rect.x + 2 + indent_px,
|
||||||
con->deco_rect.y + text_offset_y,
|
con->deco_rect.y + text_offset_y,
|
||||||
(xcb_char2b_t*)win->name_x
|
(xcb_char2b_t*)win->name_x
|
||||||
|
@ -387,12 +423,16 @@ void x_draw_decoration(Con *con) {
|
||||||
xcb_image_text_8(
|
xcb_image_text_8(
|
||||||
conn,
|
conn,
|
||||||
win->name_len,
|
win->name_len,
|
||||||
parent->frame,
|
parent->pixmap,
|
||||||
parent->gc,
|
parent->pm_gc,
|
||||||
con->deco_rect.x + 2 + indent_px,
|
con->deco_rect.x + 2 + indent_px,
|
||||||
con->deco_rect.y + text_offset_y,
|
con->deco_rect.y + text_offset_y,
|
||||||
win->name_x
|
win->name_x
|
||||||
);
|
);
|
||||||
|
|
||||||
|
copy_pixmaps:
|
||||||
|
xcb_copy_area(conn, con->pixmap, con->frame, con->pm_gc, 0, 0, 0, 0, con->rect.width, con->rect.height);
|
||||||
|
xcb_copy_area(conn, parent->pixmap, parent->frame, parent->pm_gc, 0, 0, 0, 0, parent->rect.width, parent->rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -467,6 +507,25 @@ static void x_push_node(Con *con) {
|
||||||
if (memcmp(&(state->rect), &rect, sizeof(Rect)) != 0) {
|
if (memcmp(&(state->rect), &rect, sizeof(Rect)) != 0) {
|
||||||
DLOG("setting rect (%d, %d, %d, %d)\n", rect.x, rect.y, rect.width, rect.height);
|
DLOG("setting rect (%d, %d, %d, %d)\n", rect.x, rect.y, rect.width, rect.height);
|
||||||
xcb_set_window_rect(conn, con->frame, rect);
|
xcb_set_window_rect(conn, con->frame, rect);
|
||||||
|
|
||||||
|
/* As the pixmap only depends on the size and not on the position, it
|
||||||
|
* is enough to check if width/height have changed */
|
||||||
|
if (state->rect.width != rect.width ||
|
||||||
|
state->rect.height != rect.height) {
|
||||||
|
DLOG("CACHE: creating new pixmap\n");
|
||||||
|
if (con->pixmap == 0) {
|
||||||
|
con->pixmap = xcb_generate_id(conn);
|
||||||
|
con->pm_gc = xcb_generate_id(conn);
|
||||||
|
} else {
|
||||||
|
xcb_free_pixmap(conn, con->pixmap);
|
||||||
|
xcb_free_gc(conn, con->pm_gc);
|
||||||
|
}
|
||||||
|
xcb_create_pixmap(conn, root_depth, con->pixmap, con->frame, rect.width, rect.height);
|
||||||
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
|
xcb_create_gc(conn, con->pm_gc, con->pixmap, 0, 0);
|
||||||
|
free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL));
|
||||||
|
con->pixmap_recreated = true;
|
||||||
|
}
|
||||||
memcpy(&(state->rect), &rect, sizeof(Rect));
|
memcpy(&(state->rect), &rect, sizeof(Rect));
|
||||||
fake_notify = true;
|
fake_notify = true;
|
||||||
}
|
}
|
||||||
|
|
32
src/xcb.c
32
src/xcb.c
|
@ -289,38 +289,6 @@ void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window) {
|
||||||
xcb_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
xcb_configure_window(conn, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Prepares the given Cached_Pixmap for usage (checks whether the size of the
|
|
||||||
* object this pixmap is related to (e.g. a window) has changed and re-creates
|
|
||||||
* the pixmap if so).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void cached_pixmap_prepare(xcb_connection_t *conn, struct Cached_Pixmap *pixmap) {
|
|
||||||
DLOG("preparing pixmap\n");
|
|
||||||
|
|
||||||
/* If the Rect did not change, the pixmap does not need to be recreated */
|
|
||||||
if (memcmp(&(pixmap->rect), pixmap->referred_rect, sizeof(Rect)) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(&(pixmap->rect), pixmap->referred_rect, sizeof(Rect));
|
|
||||||
|
|
||||||
if (pixmap->id == 0 || pixmap->gc == 0) {
|
|
||||||
DLOG("Creating new pixmap...\n");
|
|
||||||
pixmap->id = xcb_generate_id(conn);
|
|
||||||
pixmap->gc = xcb_generate_id(conn);
|
|
||||||
} else {
|
|
||||||
DLOG("Re-creating this pixmap...\n");
|
|
||||||
xcb_free_gc(conn, pixmap->gc);
|
|
||||||
xcb_free_pixmap(conn, pixmap->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_create_pixmap(conn, root_depth, pixmap->id,
|
|
||||||
pixmap->referred_drawable, pixmap->rect.width, pixmap->rect.height);
|
|
||||||
|
|
||||||
xcb_create_gc(conn, pixmap->gc, pixmap->id, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Query the width of the given text (16-bit characters, UCS) with given real
|
* Query the width of the given text (16-bit characters, UCS) with given real
|
||||||
* length (amount of glyphs) using the given font.
|
* length (amount of glyphs) using the given font.
|
||||||
|
|
Loading…
Reference in New Issue