Merge branch 'less-xlib' into next

Closes #14
This commit is contained in:
Yuxuan Shui 2018-10-10 10:55:21 +01:00
commit de6e2f5792
7 changed files with 267 additions and 265 deletions

View File

@ -1463,7 +1463,13 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf,
idx, 1L, c2_get_atom_type(pleaf), pleaf->format); idx, 1L, c2_get_atom_type(pleaf), pleaf->format);
Atom atom = winprop_get_int(prop); Atom atom = winprop_get_int(prop);
if (atom) { if (atom) {
tgt_free = XGetAtomName(ps->dpy, atom); xcb_get_atom_name_reply_t *reply =
xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, atom), NULL);
if (reply) {
tgt_free = strndup(
xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
free(reply);
}
} }
if (tgt_free) { if (tgt_free) {
tgt = tgt_free; tgt = tgt_free;

View File

@ -777,6 +777,8 @@ typedef struct session {
Display *dpy; Display *dpy;
/// Default screen. /// Default screen.
int scr; int scr;
/// XCB connection.
xcb_connection_t *c;
/// Default visual. /// Default visual.
xcb_visualid_t vis; xcb_visualid_t vis;
/// Pict formats info /// Pict formats info
@ -1696,12 +1698,29 @@ cxfree(void *data) {
XFree(data); XFree(data);
} }
static inline void _Noreturn
die(const char *msg) {
puts(msg);
exit(1);
}
/** /**
* Wrapper of XInternAtom() for convenience. * Wrapper of XInternAtom() for convenience.
*/ */
static inline Atom static inline xcb_atom_t
get_atom(session_t *ps, const char *atom_name) { get_atom(session_t *ps, const char *atom_name) {
return XInternAtom(ps->dpy, atom_name, False); xcb_intern_atom_reply_t *reply =
xcb_intern_atom_reply(ps->c,
xcb_intern_atom(ps->c, False, strlen(atom_name), atom_name),
NULL);
xcb_atom_t atom = XCB_NONE;
if (reply) {
atom = reply->atom;
free(reply);
} else
die("Failed to intern atoms, bail out");
return atom;
} }
/** /**
@ -2072,7 +2091,7 @@ xr_sync_(session_t *ps, Drawable d
if (!ps->o.xrender_sync) if (!ps->o.xrender_sync)
return; return;
XSync(ps->dpy, False); x_sync(ps->c);
#ifdef CONFIG_XSYNC #ifdef CONFIG_XSYNC
if (ps->o.xrender_sync_fence && ps->xsync_exists) { if (ps->o.xrender_sync_fence && ps->xsync_exists) {
// TODO: If everybody just follows the rules stated in X Sync prototype, // TODO: If everybody just follows the rules stated in X Sync prototype,

View File

@ -551,8 +551,7 @@ make_shadow(session_t *ps, double opacity,
int x_diff; int x_diff;
int opacity_int = (int)(opacity * 25); int opacity_int = (int)(opacity * 25);
xcb_connection_t *c = XGetXCBConnection(ps->dpy); ximage = xcb_image_create_native(ps->c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
0, 0, NULL); 0, 0, NULL);
if (!ximage) { if (!ximage) {
@ -659,8 +658,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
xcb_image_t *shadow_image = NULL; xcb_image_t *shadow_image = NULL;
xcb_pixmap_t shadow_pixmap = None, shadow_pixmap_argb = None; xcb_pixmap_t shadow_pixmap = None, shadow_pixmap_argb = None;
xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None; xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None;
GC gc = None; xcb_gcontext_t gc = None;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
shadow_image = make_shadow(ps, opacity, width, height); shadow_image = make_shadow(ps, opacity, width, height);
if (!shadow_image) { if (!shadow_image) {
@ -683,14 +681,11 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
if (!shadow_picture || !shadow_picture_argb) if (!shadow_picture || !shadow_picture_argb)
goto shadow_picture_err; goto shadow_picture_err;
gc = XCreateGC(ps->dpy, shadow_pixmap, 0, 0); gc = xcb_generate_id(ps->c);
if (!gc) { xcb_create_gc(ps->c, gc, shadow_pixmap, 0, NULL);
printf_errf("(): failed to create graphic context");
goto shadow_picture_err;
}
xcb_image_put(c, shadow_pixmap, XGContextFromGC(gc), shadow_image, 0, 0, 0); xcb_image_put(ps->c, shadow_pixmap, gc, shadow_image, 0, 0, 0);
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture, shadow_picture, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture, shadow_picture,
shadow_picture_argb, 0, 0, 0, 0, 0, 0, shadow_picture_argb, 0, 0, 0, 0, 0, 0,
shadow_image->width, shadow_image->height); shadow_image->width, shadow_image->height);
@ -702,10 +697,10 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
// Sync it once and only once // Sync it once and only once
xr_sync(ps, w->shadow_paint.pixmap, NULL); xr_sync(ps, w->shadow_paint.pixmap, NULL);
XFreeGC(ps->dpy, gc); xcb_free_gc(ps->c, gc);
xcb_image_destroy(shadow_image); xcb_image_destroy(shadow_image);
xcb_free_pixmap(c, shadow_pixmap); xcb_free_pixmap(ps->c, shadow_pixmap);
xcb_render_free_picture(c, shadow_picture); xcb_render_free_picture(ps->c, shadow_picture);
return true; return true;
@ -713,15 +708,15 @@ shadow_picture_err:
if (shadow_image) if (shadow_image)
xcb_image_destroy(shadow_image); xcb_image_destroy(shadow_image);
if (shadow_pixmap) if (shadow_pixmap)
xcb_free_pixmap(c, shadow_pixmap); xcb_free_pixmap(ps->c, shadow_pixmap);
if (shadow_pixmap_argb) if (shadow_pixmap_argb)
xcb_free_pixmap(c, shadow_pixmap_argb); xcb_free_pixmap(ps->c, shadow_pixmap_argb);
if (shadow_picture) if (shadow_picture)
xcb_render_free_picture(c, shadow_picture); xcb_render_free_picture(ps->c, shadow_picture);
if (shadow_picture_argb) if (shadow_picture_argb)
xcb_render_free_picture(c, shadow_picture_argb); xcb_render_free_picture(ps->c, shadow_picture_argb);
if (gc) if (gc)
XFreeGC(ps->dpy, gc); xcb_free_gc(ps->c, gc);
return false; return false;
} }
@ -737,7 +732,6 @@ solid_picture(session_t *ps, bool argb, double a,
xcb_render_create_picture_value_list_t pa; xcb_render_create_picture_value_list_t pa;
xcb_render_color_t col; xcb_render_color_t col;
xcb_rectangle_t rect; xcb_rectangle_t rect;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
pixmap = x_create_pixmap(ps, argb ? 32 : 8, ps->root, 1, 1); pixmap = x_create_pixmap(ps, argb ? 32 : 8, ps->root, 1, 1);
if (!pixmap) return None; if (!pixmap) return None;
@ -748,7 +742,7 @@ solid_picture(session_t *ps, bool argb, double a,
XCB_RENDER_CP_REPEAT, &pa); XCB_RENDER_CP_REPEAT, &pa);
if (!picture) { if (!picture) {
xcb_free_pixmap(c, pixmap); xcb_free_pixmap(ps->c, pixmap);
return None; return None;
} }
@ -762,8 +756,8 @@ solid_picture(session_t *ps, bool argb, double a,
rect.width = 1; rect.width = 1;
rect.height = 1; rect.height = 1;
xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect); xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect);
xcb_free_pixmap(c, pixmap); xcb_free_pixmap(ps->c, pixmap);
return picture; return picture;
} }
@ -798,15 +792,15 @@ should_ignore(session_t *ps, unsigned long sequence) {
* Determine the event mask for a window. * Determine the event mask for a window.
*/ */
long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) { long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) {
long evmask = NoEventMask; long evmask = 0;
win *w = NULL; win *w = NULL;
// Check if it's a mapped frame window // Check if it's a mapped frame window
if (WIN_EVMODE_FRAME == mode if (WIN_EVMODE_FRAME == mode
|| ((w = find_win(ps, wid)) && IsViewable == w->a.map_state)) { || ((w = find_win(ps, wid)) && IsViewable == w->a.map_state)) {
evmask |= PropertyChangeMask; evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
if (ps->o.track_focus && !ps->o.use_ewmh_active_win) if (ps->o.track_focus && !ps->o.use_ewmh_active_win)
evmask |= FocusChangeMask; evmask |= XCB_EVENT_MASK_FOCUS_CHANGE;
} }
// Check if it's a mapped client window // Check if it's a mapped client window
@ -814,7 +808,7 @@ long determine_evmask(session_t *ps, Window wid, win_evmode_t mode) {
|| ((w = find_toplevel(ps, wid)) && IsViewable == w->a.map_state)) { || ((w = find_toplevel(ps, wid)) && IsViewable == w->a.map_state)) {
if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst
|| ps->o.detect_client_opacity) || ps->o.detect_client_opacity)
evmask |= PropertyChangeMask; evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
} }
return evmask; return evmask;
@ -834,23 +828,19 @@ win *find_toplevel2(session_t *ps, Window wid) {
// We traverse through its ancestors to find out the frame // We traverse through its ancestors to find out the frame
while (wid && wid != ps->root && !(w = find_win(ps, wid))) { while (wid && wid != ps->root && !(w = find_win(ps, wid))) {
Window troot; xcb_query_tree_reply_t *reply;
Window parent;
Window *tchildren;
unsigned tnchildren;
// XQueryTree probably fails if you run compton when X is somehow // xcb_query_tree probably fails if you run compton when X is somehow
// initializing (like add it in .xinitrc). In this case // initializing (like add it in .xinitrc). In this case
// just leave it alone. // just leave it alone.
if (!XQueryTree(ps->dpy, wid, &troot, &parent, &tchildren, reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL);
&tnchildren)) { if (reply == NULL) {
parent = 0;
break; break;
} }
cxfree(tchildren); wid = reply->parent;
wid = parent; free(reply);
} }
return w; return w;
@ -873,16 +863,20 @@ recheck_focus(session_t *ps) {
// Determine the currently focused window so we can apply appropriate // Determine the currently focused window so we can apply appropriate
// opacity on it // opacity on it
Window wid = 0; xcb_window_t wid = XCB_NONE;
int revert_to; xcb_get_input_focus_reply_t *reply =
xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL);
XGetInputFocus(ps->dpy, &wid, &revert_to); if (reply) {
wid = reply->focus;
free(reply);
}
win *w = find_win_all(ps, wid); win *w = find_win_all(ps, wid);
#ifdef DEBUG_EVENTS #ifdef DEBUG_EVENTS
print_timestamp(ps); print_timestamp(ps);
printf_dbgf("(): %#010lx (%#010lx \"%s\") focused.\n", wid, printf_dbgf("(): %#010" PRIx32 " (%#010lx \"%s\") focused.\n", wid,
(w ? w->id: None), (w ? w->name: NULL)); (w ? w->id: None), (w ? w->name: NULL));
#endif #endif
@ -901,7 +895,6 @@ get_root_tile(session_t *ps) {
if (ps->o.paint_on_overlay) { if (ps->o.paint_on_overlay) {
return ps->root_picture; return ps->root_picture;
} */ } */
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
assert(!ps->root_tile_paint.pixmap); assert(!ps->root_tile_paint.pixmap);
ps->root_tile_fill = false; ps->root_tile_fill = false;
@ -955,7 +948,7 @@ get_root_tile(session_t *ps) {
rect.x = rect.y = 0; rect.x = rect.y = 0;
rect.width = rect.height = 1; rect.width = rect.height = 1;
xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, ps->root_tile_paint.pict, col, 1, &rect); xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, ps->root_tile_paint.pict, col, 1, &rect);
} }
ps->root_tile_fill = fill; ps->root_tile_fill = fill;
@ -983,27 +976,28 @@ paint_root(session_t *ps, const region_t *reg_paint) {
/** /**
* Look for the client window of a particular window. * Look for the client window of a particular window.
*/ */
Window xcb_window_t
find_client_win(session_t *ps, Window w) { find_client_win(session_t *ps, xcb_window_t w) {
if (wid_has_prop(ps, w, ps->atom_client)) { if (wid_has_prop(ps, w, ps->atom_client)) {
return w; return w;
} }
Window *children; xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c,
unsigned int nchildren; xcb_query_tree(ps->c, w), NULL);
unsigned int i; if (!reply)
Window ret = 0;
if (!wid_get_children(ps, w, &children, &nchildren)) {
return 0; return 0;
}
xcb_window_t *children = xcb_query_tree_children(reply);
int nchildren = xcb_query_tree_children_length(reply);
int i;
xcb_window_t ret = 0;
for (i = 0; i < nchildren; ++i) { for (i = 0; i < nchildren; ++i) {
if ((ret = find_client_win(ps, children[i]))) if ((ret = find_client_win(ps, children[i])))
break; break;
} }
cxfree(children); free(reply);
return ret; return ret;
} }
@ -1270,7 +1264,6 @@ static bool
xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer,
int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns, int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns,
const region_t *reg_clip) { const region_t *reg_clip) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
assert(blur_kerns[0]); assert(blur_kerns[0]);
// Directly copying from tgt_buffer to it does not work, so we create a // Directly copying from tgt_buffer to it does not work, so we create a
@ -1296,9 +1289,9 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer,
// Copy from source picture to destination. The filter must // Copy from source picture to destination. The filter must
// be applied on source picture, to get the nearby pixels outside the // be applied on source picture, to get the nearby pixels outside the
// window. // window.
xcb_render_set_picture_filter(c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION, xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
kwid * khei + 2, convolution_blur); kwid * khei + 2, convolution_blur);
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, None, dst_pict, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, None, dst_pict,
(rd_from_tgt ? x: 0), (rd_from_tgt ? y: 0), 0, 0, (rd_from_tgt ? x: 0), (rd_from_tgt ? y: 0), 0, 0,
(rd_from_tgt ? 0: x), (rd_from_tgt ? 0: y), wid, hei); (rd_from_tgt ? 0: x), (rd_from_tgt ? 0: y), wid, hei);
xrfilter_reset(ps, src_pict); xrfilter_reset(ps, src_pict);
@ -1311,7 +1304,7 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer,
} }
if (src_pict != tgt_buffer) if (src_pict != tgt_buffer)
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, None, tgt_buffer, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, None, tgt_buffer,
0, 0, 0, 0, x, y, wid, hei); 0, 0, 0, 0, x, y, wid, hei);
free_picture(ps, &tmp_picture); free_picture(ps, &tmp_picture);
@ -1431,7 +1424,6 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
xcb_render_picture_t pict, glx_texture_t *ptex, xcb_render_picture_t pict, glx_texture_t *ptex,
const region_t *reg_paint, const glx_prog_main_t *pprogram) const region_t *reg_paint, const glx_prog_main_t *pprogram)
{ {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
switch (ps->o.backend) { switch (ps->o.backend) {
case BKEND_XRENDER: case BKEND_XRENDER:
case BKEND_XR_GLX_HYBRID: case BKEND_XR_GLX_HYBRID:
@ -1439,7 +1431,7 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
xcb_render_picture_t alpha_pict = get_alpha_pict_d(ps, opacity); xcb_render_picture_t alpha_pict = get_alpha_pict_d(ps, opacity);
if (alpha_pict != ps->alpha_picts[0]) { if (alpha_pict != ps->alpha_picts[0]) {
int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC: XCB_RENDER_PICT_OP_OVER); int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC: XCB_RENDER_PICT_OP_OVER);
xcb_render_composite(c, op, pict, alpha_pict, xcb_render_composite(ps->c, op, pict, alpha_pict,
ps->tgt_buffer.pict, x, y, 0, 0, dx, dy, wid, hei); ps->tgt_buffer.pict, x, y, 0, 0, dx, dy, wid, hei);
} }
break; break;
@ -1461,14 +1453,13 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
*/ */
static inline void static inline void
paint_one(session_t *ps, win *w, const region_t *reg_paint) { paint_one(session_t *ps, win *w, const region_t *reg_paint) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
glx_mark(ps, w->id, true); glx_mark(ps, w->id, true);
// Fetch Pixmap // Fetch Pixmap
if (!w->paint.pixmap && ps->has_name_pixmap) { if (!w->paint.pixmap && ps->has_name_pixmap) {
w->paint.pixmap = xcb_generate_id(c); w->paint.pixmap = xcb_generate_id(ps->c);
set_ignore_cookie(ps, set_ignore_cookie(ps,
xcb_composite_name_window_pixmap(c, w->id, w->paint.pixmap)); xcb_composite_name_window_pixmap(ps->c, w->id, w->paint.pixmap));
if (w->paint.pixmap) if (w->paint.pixmap)
free_fence(ps, &w->fence); free_fence(ps, &w->fence);
} }
@ -1526,14 +1517,14 @@ paint_one(session_t *ps, win *w, const region_t *reg_paint) {
pixman_region32_fini(&reg); pixman_region32_fini(&reg);
} }
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, pict, None, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, pict, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei); newpict, 0, 0, 0, 0, 0, 0, wid, hei);
xcb_render_composite(c, XCB_RENDER_PICT_OP_DIFFERENCE, ps->white_picture, None, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_DIFFERENCE, ps->white_picture, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei); newpict, 0, 0, 0, 0, 0, 0, wid, hei);
// We use an extra PictOpInReverse operation to get correct pixel // We use an extra PictOpInReverse operation to get correct pixel
// alpha. There could be a better solution. // alpha. There could be a better solution.
if (win_has_alpha(w)) if (win_has_alpha(w))
xcb_render_composite(c, XCB_RENDER_PICT_OP_IN_REVERSE, pict, None, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_IN_REVERSE, pict, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei); newpict, 0, 0, 0, 0, 0, 0, wid, hei);
pict = newpict; pict = newpict;
} }
@ -1633,7 +1624,7 @@ paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * dopacity, \
.height = hei, .height = hei,
}; };
xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_OVER, ps->tgt_buffer.pict, xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_OVER, ps->tgt_buffer.pict,
color, 1, &rect); color, 1, &rect);
} }
break; break;
@ -1675,7 +1666,6 @@ rebuild_shadow_exclude_reg(session_t *ps) {
/// region_real = the damage region /// region_real = the damage region
static void static void
paint_all(session_t *ps, region_t *region, const region_t *region_real, win * const t) { paint_all(session_t *ps, region_t *region, const region_t *region_real, win * const t) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
if (!region_real) if (!region_real)
region_real = region; region_real = region;
@ -1830,7 +1820,7 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co
if (ps->o.vsync) { if (ps->o.vsync) {
// Make sure all previous requests are processed to achieve best // Make sure all previous requests are processed to achieve best
// effect // effect
XSync(ps->dpy, False); x_sync(ps->c);
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (glx_has_context(ps)) { if (glx_has_context(ps)) {
if (ps->o.vsync_use_glfinish) if (ps->o.vsync_use_glfinish)
@ -1862,14 +1852,14 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co
// No-DBE painting mode // No-DBE painting mode
else if (ps->tgt_buffer.pict != ps->tgt_picture) { else if (ps->tgt_buffer.pict != ps->tgt_picture) {
xcb_render_composite( xcb_render_composite(
c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, None, ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, None,
ps->tgt_picture, 0, 0, 0, 0, ps->tgt_picture, 0, 0, 0, 0,
0, 0, ps->root_width, ps->root_height); 0, 0, ps->root_width, ps->root_height);
} }
break; break;
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
case BKEND_XR_GLX_HYBRID: case BKEND_XR_GLX_HYBRID:
XSync(ps->dpy, False); x_sync(ps->c);
if (ps->o.vsync_use_glfinish) if (ps->o.vsync_use_glfinish)
glFinish(); glFinish();
else else
@ -1941,24 +1931,23 @@ repair_win(session_t *ps, win *w) {
if (IsViewable != w->a.map_state) if (IsViewable != w->a.map_state)
return; return;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
region_t parts; region_t parts;
pixman_region32_init(&parts); pixman_region32_init(&parts);
if (!w->ever_damaged) { if (!w->ever_damaged) {
win_extents(w, &parts); win_extents(w, &parts);
set_ignore_cookie(ps, set_ignore_cookie(ps,
xcb_damage_subtract(c, w->damage, XCB_NONE, XCB_NONE)); xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE));
} else { } else {
xcb_xfixes_region_t tmp = xcb_generate_id(c); xcb_xfixes_region_t tmp = xcb_generate_id(ps->c);
xcb_xfixes_create_region(c, tmp, 0, NULL); xcb_xfixes_create_region(ps->c, tmp, 0, NULL);
set_ignore_cookie(ps, set_ignore_cookie(ps,
xcb_damage_subtract(c, w->damage, XCB_NONE, tmp)); xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp));
xcb_xfixes_translate_region(c, tmp, xcb_xfixes_translate_region(ps->c, tmp,
w->g.x + w->g.border_width, w->g.x + w->g.border_width,
w->g.y + w->g.border_width); w->g.y + w->g.border_width);
x_fetch_region(ps, tmp, &parts); x_fetch_region(ps, tmp, &parts);
xcb_xfixes_destroy_region(c, tmp); xcb_xfixes_destroy_region(ps->c, tmp);
} }
w->ever_damaged = true; w->ever_damaged = true;
@ -1990,12 +1979,10 @@ finish_map_win(session_t *ps, win **_w) {
void void
map_win(session_t *ps, Window id) { map_win(session_t *ps, Window id) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
// Unmap overlay window if it got mapped but we are currently not // Unmap overlay window if it got mapped but we are currently not
// in redirected state. // in redirected state.
if (ps->overlay && id == ps->overlay && !ps->redirected) { if (ps->overlay && id == ps->overlay && !ps->redirected) {
XUnmapWindow(ps->dpy, ps->overlay); xcb_unmap_window(ps->c, ps->overlay);
XFlush(ps->dpy); XFlush(ps->dpy);
} }
@ -2017,13 +2004,14 @@ map_win(session_t *ps, Window id) {
cxinerama_win_upd_scr(ps, w); cxinerama_win_upd_scr(ps, w);
// Call XSelectInput() before reading properties so that no property // Set window event mask before reading properties so that no property
// changes are lost // changes are lost
XSelectInput(ps->dpy, id, determine_evmask(ps, id, WIN_EVMODE_FRAME)); xcb_change_window_attributes(ps->c, id, XCB_CW_EVENT_MASK,
(const uint32_t[]) { determine_evmask(ps, id, WIN_EVMODE_FRAME) });
// Notify compton when the shape of a window changes // Notify compton when the shape of a window changes
if (ps->shape_exists) { if (ps->shape_exists) {
xcb_shape_select_input(c, id, 1); xcb_shape_select_input(ps->c, id, 1);
} }
// Make sure the XSelectInput() requests are sent // Make sure the XSelectInput() requests are sent
@ -2418,7 +2406,7 @@ destroy_win(session_t *ps, Window id) {
static inline void static inline void
root_damaged(session_t *ps) { root_damaged(session_t *ps) {
if (ps->root_tile_paint.pixmap) { if (ps->root_tile_paint.pixmap) {
XClearArea(ps->dpy, ps->root, 0, 0, 0, 0, true); xcb_clear_area(ps->c, true, ps->root, 0, 0, 0, 0);
free_root_tile(ps); free_root_tile(ps);
} }
@ -2530,8 +2518,8 @@ opts_init_track_focus(session_t *ps) {
// Start listening to FocusChange events // Start listening to FocusChange events
for (win *w = ps->list; w; w = w->next) for (win *w = ps->list; w; w = w->next)
if (IsViewable == w->a.map_state) if (IsViewable == w->a.map_state)
XSelectInput(ps->dpy, w->id, xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK,
determine_evmask(ps, w->id, WIN_EVMODE_FRAME)); (const uint32_t[]) { determine_evmask(ps, w->id, WIN_EVMODE_FRAME) });
} }
// Recheck focus // Recheck focus
@ -2750,8 +2738,8 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
destroy_win(ps, ev->window); destroy_win(ps, ev->window);
// Reset event mask in case something wrong happens // Reset event mask in case something wrong happens
XSelectInput(ps->dpy, ev->window, xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK,
determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN)); (const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) });
// Check if the window is an undetected client window // Check if the window is an undetected client window
// Firstly, check if it's a known client window // Firstly, check if it's a known client window
@ -2770,9 +2758,8 @@ ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
} }
// Otherwise, watch for WM_STATE on it // Otherwise, watch for WM_STATE on it
else { else {
XSelectInput(ps->dpy, ev->window, xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) {
determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | XCB_EVENT_MASK_PROPERTY_CHANGE });
| PropertyChangeMask);
} }
} }
} }
@ -2833,9 +2820,17 @@ ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) {
#ifdef DEBUG_EVENTS #ifdef DEBUG_EVENTS
{ {
// Print out changed atom // Print out changed atom
char *name = XGetAtomName(ps->dpy, ev->atom); xcb_get_atom_name_reply_t *reply =
printf_dbg(" { atom = %s }\n", name); xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, ev->atom), NULL);
cxfree(name); const char *name = "?";
int name_len = 1;
if (reply) {
name = xcb_get_atom_name_name(reply);
name_len = xcb_get_atom_name_name_length(reply);
}
printf_dbg(" { atom = %.*s }\n", name_len, name);
free(reply);
} }
#endif #endif
@ -2863,8 +2858,8 @@ ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) {
// Check whether it could be a client window // Check whether it could be a client window
if (!find_toplevel(ps, ev->window)) { if (!find_toplevel(ps, ev->window)) {
// Reset event mask anyway // Reset event mask anyway
XSelectInput(ps->dpy, ev->window, xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) {
determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN)); determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) });
win *w_top = find_toplevel2(ps, ev->window); win *w_top = find_toplevel2(ps, ev->window);
// Initialize client_win as early as possible // Initialize client_win as early as possible
@ -3508,7 +3503,6 @@ static bool
register_cm(session_t *ps) { register_cm(session_t *ps) {
assert(!ps->reg_win); assert(!ps->reg_win);
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0,
None, None); None, None);
@ -3519,7 +3513,7 @@ register_cm(session_t *ps) {
// Unredirect the window if it's redirected, just in case // Unredirect the window if it's redirected, just in case
if (ps->redirected) if (ps->redirected)
xcb_composite_unredirect_window(c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL); xcb_composite_unredirect_window(ps->c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL);
{ {
XClassHint *h = XAllocClassHint(); XClassHint *h = XAllocClassHint();
@ -3534,12 +3528,9 @@ register_cm(session_t *ps) {
// Set _NET_WM_PID // Set _NET_WM_PID
{ {
long pid = getpid(); uint32_t pid = getpid();
if (!XChangeProperty(ps->dpy, ps->reg_win, xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, PropModeReplace, get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, &pid);
(unsigned char *) &pid, 1)) {
printf_errf("(): Failed to set _NET_WM_PID.");
}
} }
// Set COMPTON_VERSION // Set COMPTON_VERSION
@ -3562,13 +3553,19 @@ register_cm(session_t *ps) {
snprintf(buf, len, REGISTER_PROP "%d", ps->scr); snprintf(buf, len, REGISTER_PROP "%d", ps->scr);
buf[len - 1] = '\0'; buf[len - 1] = '\0';
atom = get_atom(ps, buf); atom = get_atom(ps, buf);
free(buf);
if (XGetSelectionOwner(ps->dpy, atom) != None) { xcb_get_selection_owner_reply_t *reply =
xcb_get_selection_owner_reply(ps->c,
xcb_get_selection_owner(ps->c, atom), NULL);
if (reply && reply->owner != XCB_NONE) {
free(reply);
fprintf(stderr, "Another composite manager is already running\n"); fprintf(stderr, "Another composite manager is already running\n");
return false; return false;
} }
XSetSelectionOwner(ps->dpy, atom, ps->reg_win, 0); free(reply);
free(buf); xcb_set_selection_owner(ps->c, ps->reg_win, atom, 0);
} }
return true; return true;
@ -4163,10 +4160,9 @@ init_atoms(session_t *ps) {
*/ */
static void static void
update_refresh_rate(session_t *ps) { update_refresh_rate(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_randr_get_screen_info_reply_t *randr_info = xcb_randr_get_screen_info_reply_t *randr_info =
xcb_randr_get_screen_info_reply(c, xcb_randr_get_screen_info_reply(ps->c,
xcb_randr_get_screen_info(c, ps->root), NULL); xcb_randr_get_screen_info(ps->c, ps->root), NULL);
if (!randr_info) if (!randr_info)
return; return;
@ -4514,10 +4510,9 @@ init_dbe(session_t *ps) {
*/ */
static bool static bool
init_overlay(session_t *ps) { init_overlay(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_composite_get_overlay_window_reply_t *reply = xcb_composite_get_overlay_window_reply_t *reply =
xcb_composite_get_overlay_window_reply(c, xcb_composite_get_overlay_window_reply(ps->c,
xcb_composite_get_overlay_window(c, ps->root), NULL); xcb_composite_get_overlay_window(ps->c, ps->root), NULL);
if (reply) { if (reply) {
ps->overlay = reply->overlay_win; ps->overlay = reply->overlay_win;
free(reply); free(reply);
@ -4528,13 +4523,13 @@ init_overlay(session_t *ps) {
// Set window region of the overlay window, code stolen from // Set window region of the overlay window, code stolen from
// compiz-0.8.8 // compiz-0.8.8
xcb_generic_error_t *e; xcb_generic_error_t *e;
e = XCB_SYNCED_VOID(xcb_shape_mask, c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, e = XCB_SYNCED_VOID(xcb_shape_mask, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
ps->overlay, 0, 0, 0); ps->overlay, 0, 0, 0);
if (e) { if (e) {
printf_errf("(): failed to set the bounding shape of overlay, giving up."); printf_errf("(): failed to set the bounding shape of overlay, giving up.");
exit(1); exit(1);
} }
e = XCB_SYNCED_VOID(xcb_shape_rectangles, c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, e = XCB_SYNCED_VOID(xcb_shape_rectangles, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT,
XCB_CLIP_ORDERING_UNSORTED, ps->overlay, 0, 0, 0, NULL); XCB_CLIP_ORDERING_UNSORTED, ps->overlay, 0, 0, 0, NULL);
if (e) { if (e) {
printf_errf("(): failed to set the input shape of overlay, giving up."); printf_errf("(): failed to set the input shape of overlay, giving up.");
@ -4542,7 +4537,8 @@ init_overlay(session_t *ps) {
} }
// Listen to Expose events on the overlay // Listen to Expose events on the overlay
XSelectInput(ps->dpy, ps->overlay, ExposureMask); xcb_change_window_attributes(ps->c, ps->overlay, XCB_CW_EVENT_MASK,
(const uint32_t[]) { XCB_EVENT_MASK_EXPOSURE });
// Retrieve DamageNotify on root window if we are painting on an // Retrieve DamageNotify on root window if we are painting on an
// overlay // overlay
@ -4550,7 +4546,7 @@ init_overlay(session_t *ps) {
// Unmap overlay, firstly. But this typically does not work because // Unmap overlay, firstly. But this typically does not work because
// the window isn't created yet. // the window isn't created yet.
// XUnmapWindow(ps->dpy, ps->overlay); // xcb_unmap_window(c, ps->overlay);
// XFlush(ps->dpy); // XFlush(ps->dpy);
} }
else { else {
@ -4570,7 +4566,6 @@ init_overlay(session_t *ps) {
*/ */
static bool static bool
init_filters(session_t *ps) { init_filters(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
// Blur filter // Blur filter
if (ps->o.blur_background || ps->o.blur_background_frame) { if (ps->o.blur_background || ps->o.blur_background_frame) {
switch (ps->o.backend) { switch (ps->o.backend) {
@ -4578,8 +4573,8 @@ init_filters(session_t *ps) {
case BKEND_XR_GLX_HYBRID: case BKEND_XR_GLX_HYBRID:
{ {
// Query filters // Query filters
xcb_render_query_filters_reply_t *pf = xcb_render_query_filters_reply(c, xcb_render_query_filters_reply_t *pf = xcb_render_query_filters_reply(ps->c,
xcb_render_query_filters(c, get_tgt_window(ps)), NULL); xcb_render_query_filters(ps->c, get_tgt_window(ps)), NULL);
if (pf) { if (pf) {
xcb_str_iterator_t iter = xcb_render_query_filters_filters_iterator(pf); xcb_str_iterator_t iter = xcb_render_query_filters_filters_iterator(pf);
for (; iter.rem; xcb_str_next(&iter)) { for (; iter.rem; xcb_str_next(&iter)) {
@ -4621,14 +4616,12 @@ redir_start(session_t *ps) {
printf_dbgf("(): Screen redirected.\n"); printf_dbgf("(): Screen redirected.\n");
#endif #endif
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
// Map overlay window. Done firstly according to this: // Map overlay window. Done firstly according to this:
// https://bugzilla.gnome.org/show_bug.cgi?id=597014 // https://bugzilla.gnome.org/show_bug.cgi?id=597014
if (ps->overlay) if (ps->overlay)
XMapWindow(ps->dpy, ps->overlay); xcb_map_window(ps->c, ps->overlay);
xcb_composite_redirect_subwindows(c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); xcb_composite_redirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL);
/* /*
// Unredirect GL context window as this may have an effect on VSync: // Unredirect GL context window as this may have an effect on VSync:
@ -4640,7 +4633,7 @@ redir_start(session_t *ps) {
} */ } */
// Must call XSync() here // Must call XSync() here
XSync(ps->dpy, False); x_sync(ps->c);
ps->redirected = true; ps->redirected = true;
@ -4655,7 +4648,6 @@ redir_start(session_t *ps) {
static void static void
redir_stop(session_t *ps) { redir_stop(session_t *ps) {
if (ps->redirected) { if (ps->redirected) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
#ifdef DEBUG_REDIR #ifdef DEBUG_REDIR
print_timestamp(ps); print_timestamp(ps);
printf_dbgf("(): Screen unredirected.\n"); printf_dbgf("(): Screen unredirected.\n");
@ -4666,13 +4658,13 @@ redir_stop(session_t *ps) {
for (win *w = ps->list; w; w = w->next) for (win *w = ps->list; w; w = w->next)
free_wpaint(ps, w); free_wpaint(ps, w);
xcb_composite_unredirect_subwindows(c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); xcb_composite_unredirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL);
// Unmap overlay window // Unmap overlay window
if (ps->overlay) if (ps->overlay)
XUnmapWindow(ps->dpy, ps->overlay); xcb_unmap_window(ps->c, ps->overlay);
// Must call XSync() here // Must call XSync() here
XSync(ps->dpy, False); x_sync(ps->c);
ps->redirected = false; ps->redirected = false;
} }
@ -4684,13 +4676,17 @@ handle_queued_x_events(EV_P_ ev_prepare *w, int revents) {
ev_session_prepare *sw = (void *)w; ev_session_prepare *sw = (void *)w;
session_t *ps = sw->ps; session_t *ps = sw->ps;
xcb_generic_event_t *ev; xcb_generic_event_t *ev;
xcb_connection_t *c = XGetXCBConnection(ps->dpy); while ((ev = xcb_poll_for_queued_event(ps->c))) {
while ((ev = xcb_poll_for_queued_event(c))) {
ev_handle(ps, ev); ev_handle(ps, ev);
free(ev); free(ev);
}; };
XFlush(ps->dpy); XFlush(ps->dpy);
xcb_flush(c); xcb_flush(ps->c);
int err = xcb_connection_has_error(ps->c);
if (err) {
printf_errfq(1, "(): X11 server connection broke (error %d)", err);
}
} }
/** /**
@ -4822,8 +4818,7 @@ delayed_draw_callback(EV_P_ ev_idle *w, int revents) {
static void static void
x_event_callback(EV_P_ ev_io *w, int revents) { x_event_callback(EV_P_ ev_io *w, int revents) {
session_t *ps = (session_t *)w; session_t *ps = (session_t *)w;
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_generic_event_t *ev = xcb_poll_for_event(ps->c);
xcb_generic_event_t *ev = xcb_poll_for_event(c);
if (ev) { if (ev) {
ev_handle(ps, ev); ev_handle(ps, ev);
free(ev); free(ev);
@ -4838,18 +4833,17 @@ cxinerama_upd_scrs(session_t *ps) {
if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return; if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_xinerama_is_active_reply_t *active = xcb_xinerama_is_active_reply_t *active =
xcb_xinerama_is_active_reply(c, xcb_xinerama_is_active_reply(ps->c,
xcb_xinerama_is_active(c), NULL); xcb_xinerama_is_active(ps->c), NULL);
if (!active || !active->state) { if (!active || !active->state) {
free(active); free(active);
return; return;
} }
free(active); free(active);
ps->xinerama_scrs = xcb_xinerama_query_screens_reply(c, ps->xinerama_scrs = xcb_xinerama_query_screens_reply(ps->c,
xcb_xinerama_query_screens(c), NULL); xcb_xinerama_query_screens(ps->c), NULL);
if (!ps->xinerama_scrs) if (!ps->xinerama_scrs)
return; return;
@ -4878,6 +4872,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
static const session_t s_def = { static const session_t s_def = {
.dpy = NULL, .dpy = NULL,
.scr = 0, .scr = 0,
.c = NULL,
.vis = 0, .vis = 0,
.depth = 0, .depth = 0,
.root = None, .root = None,
@ -5082,7 +5077,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
} }
XSetEventQueueOwner(ps->dpy, XCBOwnsEventQueue); XSetEventQueueOwner(ps->dpy, XCBOwnsEventQueue);
} }
xcb_connection_t *c = XGetXCBConnection(ps->dpy); ps->c = XGetXCBConnection(ps->dpy);
const xcb_query_extension_reply_t *ext_info; const xcb_query_extension_reply_t *ext_info;
XSetErrorHandler(xerror); XSetErrorHandler(xerror);
@ -5098,25 +5093,25 @@ session_init(session_t *ps_old, int argc, char **argv) {
// Start listening to events on root earlier to catch all possible // Start listening to events on root earlier to catch all possible
// root geometry changes // root geometry changes
XSelectInput(ps->dpy, ps->root, xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK, (const uint32_t[]) {
SubstructureNotifyMask XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
| ExposureMask | XCB_EVENT_MASK_EXPOSURE
| StructureNotifyMask | XCB_EVENT_MASK_STRUCTURE_NOTIFY
| PropertyChangeMask); | XCB_EVENT_MASK_PROPERTY_CHANGE });
XFlush(ps->dpy); XFlush(ps->dpy);
ps->root_width = DisplayWidth(ps->dpy, ps->scr); ps->root_width = DisplayWidth(ps->dpy, ps->scr);
ps->root_height = DisplayHeight(ps->dpy, ps->scr); ps->root_height = DisplayHeight(ps->dpy, ps->scr);
xcb_prefetch_extension_data(c, &xcb_render_id); xcb_prefetch_extension_data(ps->c, &xcb_render_id);
xcb_prefetch_extension_data(c, &xcb_composite_id); xcb_prefetch_extension_data(ps->c, &xcb_composite_id);
xcb_prefetch_extension_data(c, &xcb_damage_id); xcb_prefetch_extension_data(ps->c, &xcb_damage_id);
xcb_prefetch_extension_data(c, &xcb_shape_id); xcb_prefetch_extension_data(ps->c, &xcb_shape_id);
xcb_prefetch_extension_data(c, &xcb_xfixes_id); xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id);
xcb_prefetch_extension_data(c, &xcb_randr_id); xcb_prefetch_extension_data(ps->c, &xcb_randr_id);
xcb_prefetch_extension_data(c, &xcb_xinerama_id); xcb_prefetch_extension_data(ps->c, &xcb_xinerama_id);
ext_info = xcb_get_extension_data(c, &xcb_render_id); ext_info = xcb_get_extension_data(ps->c, &xcb_render_id);
if (!ext_info || !ext_info->present) { if (!ext_info || !ext_info->present) {
fprintf(stderr, "No render extension\n"); fprintf(stderr, "No render extension\n");
exit(1); exit(1);
@ -5124,7 +5119,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->render_event = ext_info->first_event; ps->render_event = ext_info->first_event;
ps->render_error = ext_info->first_error; ps->render_error = ext_info->first_error;
ext_info = xcb_get_extension_data(c, &xcb_composite_id); ext_info = xcb_get_extension_data(ps->c, &xcb_composite_id);
if (!ext_info || !ext_info->present) { if (!ext_info || !ext_info->present) {
fprintf(stderr, "No composite extension\n"); fprintf(stderr, "No composite extension\n");
exit(1); exit(1);
@ -5135,8 +5130,8 @@ session_init(session_t *ps_old, int argc, char **argv) {
{ {
xcb_composite_query_version_reply_t *reply = xcb_composite_query_version_reply_t *reply =
xcb_composite_query_version_reply(c, xcb_composite_query_version_reply(ps->c,
xcb_composite_query_version(c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION), xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION),
NULL); NULL);
if (!ps->o.no_name_pixmap if (!ps->o.no_name_pixmap
@ -5146,25 +5141,25 @@ session_init(session_t *ps_old, int argc, char **argv) {
free(reply); free(reply);
} }
ext_info = xcb_get_extension_data(c, &xcb_damage_id); ext_info = xcb_get_extension_data(ps->c, &xcb_damage_id);
if (!ext_info || !ext_info->present) { if (!ext_info || !ext_info->present) {
fprintf(stderr, "No damage extension\n"); fprintf(stderr, "No damage extension\n");
exit(1); exit(1);
} }
ps->damage_event = ext_info->first_event; ps->damage_event = ext_info->first_event;
ps->damage_error = ext_info->first_error; ps->damage_error = ext_info->first_error;
xcb_discard_reply(c, xcb_discard_reply(ps->c,
xcb_damage_query_version(c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION).sequence); xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION).sequence);
ext_info = xcb_get_extension_data(c, &xcb_xfixes_id); ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id);
if (!ext_info || !ext_info->present) { if (!ext_info || !ext_info->present) {
fprintf(stderr, "No XFixes extension\n"); fprintf(stderr, "No XFixes extension\n");
exit(1); exit(1);
} }
ps->xfixes_event = ext_info->first_event; ps->xfixes_event = ext_info->first_event;
ps->xfixes_error = ext_info->first_error; ps->xfixes_error = ext_info->first_error;
xcb_discard_reply(c, xcb_discard_reply(ps->c,
xcb_xfixes_query_version(c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence); xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence);
// Build a safe representation of display name // Build a safe representation of display name
{ {
@ -5191,7 +5186,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
get_cfg(ps, argc, argv, false); get_cfg(ps, argc, argv, false);
// Query X Shape // Query X Shape
ext_info = xcb_get_extension_data(c, &xcb_shape_id); ext_info = xcb_get_extension_data(ps->c, &xcb_shape_id);
if (ext_info && ext_info->present) { if (ext_info && ext_info->present) {
ps->shape_event = ext_info->first_event; ps->shape_event = ext_info->first_event;
ps->shape_error = ext_info->first_error; ps->shape_error = ext_info->first_error;
@ -5221,7 +5216,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
// Query X RandR // Query X RandR
if ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop) { if ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop) {
ext_info = xcb_get_extension_data(c, &xcb_randr_id); ext_info = xcb_get_extension_data(ps->c, &xcb_randr_id);
if (ext_info && ext_info->present) { if (ext_info && ext_info->present) {
ps->randr_exists = true; ps->randr_exists = true;
ps->randr_event = ext_info->first_event; ps->randr_event = ext_info->first_event;
@ -5250,7 +5245,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
// Query X Xinerama extension // Query X Xinerama extension
if (ps->o.xinerama_shadow_crop) { if (ps->o.xinerama_shadow_crop) {
#ifdef CONFIG_XINERAMA #ifdef CONFIG_XINERAMA
ext_info = xcb_get_extension_data(c, &xcb_xinerama_id); ext_info = xcb_get_extension_data(ps->c, &xcb_xinerama_id);
ps->xinerama_exists = ext_info && ext_info->present; ps->xinerama_exists = ext_info && ext_info->present;
#else #else
printf_errf("(): Xinerama support not compiled in."); printf_errf("(): Xinerama support not compiled in.");
@ -5302,7 +5297,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
// an auto-detected refresh rate, or when Xinerama features are enabled // an auto-detected refresh rate, or when Xinerama features are enabled
if (ps->randr_exists && ((ps->o.sw_opti && !ps->o.refresh_rate) if (ps->randr_exists && ((ps->o.sw_opti && !ps->o.refresh_rate)
|| ps->o.xinerama_shadow_crop)) || ps->o.xinerama_shadow_crop))
xcb_randr_select_input(c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
// Initialize VSync // Initialize VSync
if (!vsync_init(ps)) if (!vsync_init(ps))
@ -5389,29 +5384,36 @@ session_init(session_t *ps_old, int argc, char **argv) {
ev_set_priority(&ps->event_check->w, EV_MINPRI); ev_set_priority(&ps->event_check->w, EV_MINPRI);
ev_prepare_start(ps->loop, &ps->event_check->w); ev_prepare_start(ps->loop, &ps->event_check->w);
XGrabServer(ps->dpy); xcb_grab_server(ps->c);
{ {
Window root_return, parent_return; xcb_window_t *children;
Window *children; int nchildren;
unsigned int nchildren;
XQueryTree(ps->dpy, ps->root, &root_return, xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c,
&parent_return, &children, &nchildren); xcb_query_tree(ps->c, ps->root), NULL);
for (unsigned i = 0; i < nchildren; i++) { if (reply) {
add_win(ps, children[i], i ? children[i-1] : None); children = xcb_query_tree_children(reply);
nchildren = xcb_query_tree_children_length(reply);
} else {
children = NULL;
nchildren = 0;
} }
cxfree(children); for (int i = 0; i < nchildren; i++) {
add_win(ps, children[i], i ? children[i-1] : XCB_NONE);
}
free(reply);
} }
if (ps->o.track_focus) { if (ps->o.track_focus) {
recheck_focus(ps); recheck_focus(ps);
} }
XUngrabServer(ps->dpy); xcb_ungrab_server(ps->c);
// ALWAYS flush after XUngrabServer()! // ALWAYS flush after xcb_ungrab_server()!
XFlush(ps->dpy); XFlush(ps->dpy);
// Initialize DBus // Initialize DBus
@ -5458,11 +5460,11 @@ session_init(session_t *ps_old, int argc, char **argv) {
*/ */
static void static void
session_destroy(session_t *ps) { session_destroy(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
redir_stop(ps); redir_stop(ps);
// Stop listening to events on root window // Stop listening to events on root window
XSelectInput(ps->dpy, ps->root, 0); xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK,
(const uint32_t[]) { 0 });
#ifdef CONFIG_DBUS #ifdef CONFIG_DBUS
// Kill DBus connection // Kill DBus connection
@ -5599,18 +5601,18 @@ session_destroy(session_t *ps) {
// Release overlay window // Release overlay window
if (ps->overlay) { if (ps->overlay) {
xcb_composite_release_overlay_window(c, ps->overlay); xcb_composite_release_overlay_window(ps->c, ps->overlay);
ps->overlay = None; ps->overlay = None;
} }
// Free reg_win // Free reg_win
if (ps->reg_win) { if (ps->reg_win) {
XDestroyWindow(ps->dpy, ps->reg_win); xcb_destroy_window(ps->c, ps->reg_win);
ps->reg_win = None; ps->reg_win = None;
} }
// Flush all events // Flush all events
XSync(ps->dpy, True); x_sync(ps->c);
ev_io_stop(ps->loop, &ps->xiow); ev_io_stop(ps->loop, &ps->xiow);
#ifdef DEBUG_XRC #ifdef DEBUG_XRC

View File

@ -43,8 +43,8 @@ void add_damage(session_t *ps, const region_t *damage);
long determine_evmask(session_t *ps, Window wid, win_evmode_t mode); long determine_evmask(session_t *ps, Window wid, win_evmode_t mode);
Window xcb_window_t
find_client_win(session_t *ps, Window w); find_client_win(session_t *ps, xcb_window_t w);
win *find_toplevel2(session_t *ps, Window wid); win *find_toplevel2(session_t *ps, Window wid);
@ -62,8 +62,7 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
static inline void static inline void
xrfilter_reset(session_t *ps, xcb_render_picture_t p) { xrfilter_reset(session_t *ps, xcb_render_picture_t p) {
#define FILTER "Nearest" #define FILTER "Nearest"
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_render_set_picture_filter(ps->c, p, strlen(FILTER), FILTER, 0, NULL);
xcb_render_set_picture_filter(c, p, strlen(FILTER), FILTER, 0, NULL);
#undef FILTER #undef FILTER
} }
@ -113,8 +112,7 @@ array_wid_exists(const Window *arr, int count, Window wid) {
inline static void inline static void
free_picture(session_t *ps, xcb_render_picture_t *p) { free_picture(session_t *ps, xcb_render_picture_t *p) {
if (*p) { if (*p) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_render_free_picture(ps->c, *p);
xcb_render_free_picture(c, *p);
*p = None; *p = None;
} }
} }
@ -127,7 +125,7 @@ free_damage(session_t *ps, xcb_damage_damage_t *p) {
if (*p) { if (*p) {
// BadDamage will be thrown if the window is destroyed // BadDamage will be thrown if the window is destroyed
set_ignore_cookie(ps, set_ignore_cookie(ps,
xcb_damage_destroy(XGetXCBConnection(ps->dpy), *p)); xcb_damage_destroy(ps->c, *p));
*p = None; *p = None;
} }
} }
@ -196,11 +194,10 @@ free_texture(session_t *ps, glx_texture_t **t) {
*/ */
static inline void static inline void
free_paint(session_t *ps, paint_t *ppaint) { free_paint(session_t *ps, paint_t *ppaint) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
free_paint_glx(ps, ppaint); free_paint_glx(ps, ppaint);
free_picture(ps, &ppaint->pict); free_picture(ps, &ppaint->pict);
if (ppaint->pixmap) if (ppaint->pixmap)
xcb_free_pixmap(c, ppaint->pixmap); xcb_free_pixmap(ps->c, ppaint->pixmap);
ppaint->pixmap = XCB_NONE; ppaint->pixmap = XCB_NONE;
} }
@ -235,11 +232,10 @@ free_win_res(session_t *ps, win *w) {
*/ */
static inline void static inline void
free_root_tile(session_t *ps) { free_root_tile(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
free_picture(ps, &ps->root_tile_paint.pict); free_picture(ps, &ps->root_tile_paint.pict);
free_texture(ps, &ps->root_tile_paint.ptex); free_texture(ps, &ps->root_tile_paint.ptex);
if (ps->root_tile_fill) { if (ps->root_tile_fill) {
xcb_free_pixmap(c, ps->root_tile_paint.pixmap); xcb_free_pixmap(ps->c, ps->root_tile_paint.pixmap);
ps->root_tile_paint.pixmap = XCB_NONE; ps->root_tile_paint.pixmap = XCB_NONE;
} }
ps->root_tile_paint.pixmap = None; ps->root_tile_paint.pixmap = None;
@ -309,45 +305,21 @@ wid_set_text_prop(session_t *ps, Window wid, Atom prop_atom, char *str) {
*/ */
static inline void static inline void
win_ev_stop(session_t *ps, win *w) { win_ev_stop(session_t *ps, win *w) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
// Will get BadWindow if the window is destroyed // Will get BadWindow if the window is destroyed
set_ignore_next(ps); set_ignore_cookie(ps,
XSelectInput(ps->dpy, w->id, 0); xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 }));
if (w->client_win) { if (w->client_win) {
set_ignore_next(ps); set_ignore_cookie(ps,
XSelectInput(ps->dpy, w->client_win, 0); xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 }));
} }
if (ps->shape_exists) { if (ps->shape_exists) {
set_ignore_cookie(ps, set_ignore_cookie(ps,
xcb_shape_select_input(c, w->id, 0)); xcb_shape_select_input(ps->c, w->id, 0));
} }
} }
/**
* Get the children of a window.
*
* @param ps current session
* @param w window to check
* @param children [out] an array of child window IDs
* @param nchildren [out] number of children
* @return 1 if successful, 0 otherwise
*/
static inline bool
wid_get_children(session_t *ps, Window w,
Window **children, unsigned *nchildren) {
Window troot, tparent;
if (!XQueryTree(ps->dpy, w, &troot, &tparent, children, nchildren)) {
*nchildren = 0;
return false;
}
return true;
}
/** /**
* Check whether a window has WM frames. * Check whether a window has WM frames.
*/ */

View File

@ -27,14 +27,14 @@ clear_cache_win_leaders(session_t *ps) {
static inline void static inline void
wid_set_opacity_prop(session_t *ps, Window wid, opacity_t val) { wid_set_opacity_prop(session_t *ps, Window wid, opacity_t val) {
const unsigned long v = val; const uint32_t v = val;
XChangeProperty(ps->dpy, wid, ps->atom_opacity, XCB_ATOM_CARDINAL, 32, xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity,
PropModeReplace, (unsigned char *) &v, 1); XCB_ATOM_CARDINAL, 32, 1, &v);
} }
static inline void static inline void
wid_rm_opacity_prop(session_t *ps, Window wid) { wid_rm_opacity_prop(session_t *ps, Window wid) {
XDeleteProperty(ps->dpy, wid, ps->atom_opacity); xcb_delete_property(ps->c, wid, ps->atom_opacity);
} }
/** /**
@ -230,10 +230,9 @@ static inline bool win_bounding_shaped(const session_t *ps, Window wid) {
if (ps->shape_exists) { if (ps->shape_exists) {
xcb_shape_query_extents_reply_t *reply; xcb_shape_query_extents_reply_t *reply;
Bool bounding_shaped; Bool bounding_shaped;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
reply = xcb_shape_query_extents_reply(c, reply = xcb_shape_query_extents_reply(ps->c,
xcb_shape_query_extents(c, wid), NULL); xcb_shape_query_extents(ps->c, wid), NULL);
bounding_shaped = reply && reply->bounding_shaped; bounding_shaped = reply && reply->bounding_shaped;
free(reply); free(reply);
@ -637,8 +636,8 @@ void win_mark_client(session_t *ps, win *w, Window client) {
if (IsViewable != w->a.map_state) if (IsViewable != w->a.map_state)
return; return;
XSelectInput(ps->dpy, client, xcb_change_window_attributes(ps->c, client, XCB_CW_EVENT_MASK,
determine_evmask(ps, client, WIN_EVMODE_CLIENT)); (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_CLIENT) });
// Make sure the XSelectInput() requests are sent // Make sure the XSelectInput() requests are sent
XFlush(ps->dpy); XFlush(ps->dpy);
@ -679,8 +678,8 @@ void win_unmark_client(session_t *ps, win *w) {
w->client_win = None; w->client_win = None;
// Recheck event mask // Recheck event mask
XSelectInput(ps->dpy, client, xcb_change_window_attributes(ps->c, client, XCB_CW_EVENT_MASK,
determine_evmask(ps, client, WIN_EVMODE_UNKNOWN)); (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_UNKNOWN) });
} }
/** /**
@ -838,11 +837,10 @@ bool add_win(session_t *ps, Window id, Window prev) {
// Fill structure // Fill structure
new->id = id; new->id = id;
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, id);
xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(c, id); xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, id);
xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(c, id); xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(ps->c, acookie, NULL);
xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(c, acookie, NULL); xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL);
xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(c, gcookie, NULL);
if (!a || IsUnviewable == a->map_state) { if (!a || IsUnviewable == a->map_state) {
// Failed to get window attributes probably means the window is gone // Failed to get window attributes probably means the window is gone
// already. IsUnviewable means the window is already reparented // already. IsUnviewable means the window is already reparented
@ -871,9 +869,9 @@ bool add_win(session_t *ps, Window id, Window prev) {
if (InputOutput == new->a._class) { if (InputOutput == new->a._class) {
// Create Damage for window // Create Damage for window
new->damage = xcb_generate_id(c); new->damage = xcb_generate_id(ps->c);
xcb_generic_error_t *e = xcb_request_check(c, xcb_generic_error_t *e = xcb_request_check(ps->c,
xcb_damage_create_checked(c, new->damage, id, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY)); xcb_damage_create_checked(ps->c, new->damage, id, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
if (e) { if (e) {
free(e); free(e);
free(new); free(new);
@ -1159,9 +1157,8 @@ void win_update_bounding_shape(session_t *ps, win *w) {
* as well as not generate a region. * as well as not generate a region.
*/ */
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(ps->c,
xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(c, xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
xcb_shape_get_rectangles(c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
if (!r) if (!r)
return; return;

28
src/x.c
View File

@ -104,12 +104,11 @@ bool wid_get_text_prop(session_t *ps, Window wid, Atom prop,
static inline void x_get_server_pictfmts(session_t *ps) { static inline void x_get_server_pictfmts(session_t *ps) {
if (ps->pictfmts) if (ps->pictfmts)
return; return;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_generic_error_t *e = NULL; xcb_generic_error_t *e = NULL;
// Get window picture format // Get window picture format
ps->pictfmts = ps->pictfmts =
xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats_reply(ps->c,
xcb_render_query_pict_formats(c), &e); xcb_render_query_pict_formats(ps->c), &e);
if (e || !ps->pictfmts) { if (e || !ps->pictfmts) {
printf_errf("(): failed to get pict formats\n"); printf_errf("(): failed to get pict formats\n");
abort(); abort();
@ -146,10 +145,9 @@ x_create_picture_with_pictfmt_and_pixmap(
} }
} }
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_render_picture_t tmp_picture = xcb_generate_id(ps->c);
xcb_render_picture_t tmp_picture = xcb_generate_id(c);
xcb_generic_error_t *e = xcb_generic_error_t *e =
xcb_request_check(c, xcb_render_create_picture_checked(c, tmp_picture, xcb_request_check(ps->c, xcb_render_create_picture_checked(ps->c, tmp_picture,
pixmap, pictfmt->id, valuemask, buf)); pixmap, pictfmt->id, valuemask, buf));
free(buf); free(buf);
if (e) { if (e) {
@ -209,17 +207,15 @@ x_create_picture(session_t *ps, int wid, int hei,
xcb_render_picture_t picture = xcb_render_picture_t picture =
x_create_picture_with_pictfmt_and_pixmap(ps, pictfmt, tmp_pixmap, valuemask, attr); x_create_picture_with_pictfmt_and_pixmap(ps, pictfmt, tmp_pixmap, valuemask, attr);
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_free_pixmap(ps->c, tmp_pixmap);
xcb_free_pixmap(c, tmp_pixmap);
return picture; return picture;
} }
bool x_fetch_region(session_t *ps, xcb_xfixes_region_t r, pixman_region32_t *res) { bool x_fetch_region(session_t *ps, xcb_xfixes_region_t r, pixman_region32_t *res) {
xcb_generic_error_t *e = NULL; xcb_generic_error_t *e = NULL;
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(ps->c,
xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c, xcb_xfixes_fetch_region(ps->c, r), &e);
xcb_xfixes_fetch_region(c, r), &e);
if (!xr) { if (!xr) {
printf_errf("(): failed to fetch rectangles"); printf_errf("(): failed to fetch rectangles");
return false; return false;
@ -255,9 +251,8 @@ void x_set_picture_clip_region(session_t *ps, xcb_render_picture_t pict,
.height = rects[i].y2 - rects[i].y1, .height = rects[i].y2 - rects[i].y1,
}; };
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_generic_error_t *e = xcb_generic_error_t *e =
xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(c, pict, xcb_request_check(ps->c, xcb_render_set_picture_clip_rectangles_checked(ps->c, pict,
clip_x_origin, clip_y_origin, nrects, xrects)); clip_x_origin, clip_y_origin, nrects, xrects));
if (e) if (e)
printf_errf("(): failed to set clip region"); printf_errf("(): failed to set clip region");
@ -371,10 +366,9 @@ x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_
*/ */
xcb_pixmap_t xcb_pixmap_t
x_create_pixmap(session_t *ps, uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height) { x_create_pixmap(session_t *ps, uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_pixmap_t pix = xcb_generate_id(ps->c);
xcb_pixmap_t pix = xcb_generate_id(c); xcb_void_cookie_t cookie = xcb_create_pixmap_checked(ps->c, depth, pix, drawable, width, height);
xcb_void_cookie_t cookie = xcb_create_pixmap_checked(c, depth, pix, drawable, width, height); xcb_generic_error_t *err = xcb_request_check(ps->c, cookie);
xcb_generic_error_t *err = xcb_request_check(c, cookie);
if (err == NULL) if (err == NULL)
return pix; return pix;

12
src/x.h
View File

@ -24,6 +24,18 @@ typedef struct winprop winprop_t;
r; \ r; \
}) })
/**
* Send a request to X server and get the reply to make sure all previous
* requests are processed, and their replies received
*
* xcb_get_input_focus is used here because it is the same request used by
* libX11
*/
static inline void
x_sync(xcb_connection_t *c) {
free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL));
}
/** /**
* Get a specific attribute of a window. * Get a specific attribute of a window.
* *