x: first create/render pixmap, then change window sizes (reduces flickering for new windows)
Especially in stacked cons.
This commit is contained in:
parent
bbddacd336
commit
b49874dcb8
55
src/x.c
55
src/x.c
|
@ -452,6 +452,26 @@ update_pixmaps:
|
||||||
xcb_clear_area(conn, false, parent->frame, 0, 0, parent->rect.width, parent->rect.height);
|
xcb_clear_area(conn, false, parent->frame, 0, 0, parent->rect.width, parent->rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recursively calls x_draw_decoration. This cannot be done in x_push_node
|
||||||
|
* because x_push_node uses focus order to recurse (see the comment above)
|
||||||
|
* while drawing the decoration needs to happen in the actual order.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void x_deco_recurse(Con *con) {
|
||||||
|
Con *current;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(current, &(con->nodes_head), nodes)
|
||||||
|
x_deco_recurse(current);
|
||||||
|
|
||||||
|
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
|
||||||
|
x_deco_recurse(current);
|
||||||
|
|
||||||
|
if ((con->type != CT_ROOT && con->type != CT_OUTPUT) &&
|
||||||
|
con->mapped)
|
||||||
|
x_draw_decoration(con);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function pushes the properties of each node of the layout tree to
|
* This function pushes the properties of each node of the layout tree to
|
||||||
* X11 if they have changed (like the map state, position of the window, …).
|
* X11 if they have changed (like the map state, position of the window, …).
|
||||||
|
@ -522,8 +542,9 @@ void x_push_node(Con *con) {
|
||||||
bool fake_notify = false;
|
bool fake_notify = false;
|
||||||
/* set new position if rect changed */
|
/* set new position if rect changed */
|
||||||
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);
|
/* We first create the new pixmap, then render to it, set it as the
|
||||||
xcb_set_window_rect(conn, con->frame, rect);
|
* background and only afterwards change the window size. This reduces
|
||||||
|
* flickering. */
|
||||||
|
|
||||||
/* As the pixmap only depends on the size and not on the position, it
|
/* As the pixmap only depends on the size and not on the position, it
|
||||||
* is enough to check if width/height have changed. Also, we don’t
|
* is enough to check if width/height have changed. Also, we don’t
|
||||||
|
@ -542,10 +563,20 @@ void x_push_node(Con *con) {
|
||||||
}
|
}
|
||||||
xcb_create_pixmap(conn, root_depth, con->pixmap, con->frame, rect.width, rect.height);
|
xcb_create_pixmap(conn, root_depth, con->pixmap, con->frame, rect.width, rect.height);
|
||||||
xcb_create_gc(conn, con->pm_gc, con->pixmap, 0, 0);
|
xcb_create_gc(conn, con->pm_gc, con->pixmap, 0, 0);
|
||||||
|
|
||||||
|
/* Render the decoration now to make the correct decoration visible
|
||||||
|
* from the very first moment. Later calls will be cached, so this
|
||||||
|
* doesn’t hurt performance. */
|
||||||
|
x_deco_recurse(con);
|
||||||
|
|
||||||
uint32_t values[] = { con->pixmap };
|
uint32_t values[] = { con->pixmap };
|
||||||
xcb_change_window_attributes(conn, con->frame, XCB_CW_BACK_PIXMAP, values);
|
xcb_change_window_attributes(conn, con->frame, XCB_CW_BACK_PIXMAP, values);
|
||||||
con->pixmap_recreated = true;
|
con->pixmap_recreated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLOG("setting rect (%d, %d, %d, %d)\n", rect.x, rect.y, rect.width, rect.height);
|
||||||
|
xcb_set_window_rect(conn, con->frame, rect);
|
||||||
|
|
||||||
memcpy(&(state->rect), &rect, sizeof(Rect));
|
memcpy(&(state->rect), &rect, sizeof(Rect));
|
||||||
fake_notify = true;
|
fake_notify = true;
|
||||||
}
|
}
|
||||||
|
@ -603,26 +634,6 @@ void x_push_node(Con *con) {
|
||||||
x_push_node(current);
|
x_push_node(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Recursively calls x_draw_decoration. This cannot be done in x_push_node
|
|
||||||
* because x_push_node uses focus order to recurse (see the comment above)
|
|
||||||
* while drawing the decoration needs to happen in the actual order.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void x_deco_recurse(Con *con) {
|
|
||||||
Con *current;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->nodes_head), nodes)
|
|
||||||
x_deco_recurse(current);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
|
|
||||||
x_deco_recurse(current);
|
|
||||||
|
|
||||||
if ((con->type != CT_ROOT && con->type != CT_OUTPUT) &&
|
|
||||||
con->mapped)
|
|
||||||
x_draw_decoration(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Same idea as in x_push_node(), but this function only unmaps windows. It is
|
* Same idea as in x_push_node(), but this function only unmaps windows. It is
|
||||||
* necessary to split this up to handle new fullscreen clients properly: The
|
* necessary to split this up to handle new fullscreen clients properly: The
|
||||||
|
|
Loading…
Reference in New Issue