diff --git a/src/backend/backend.c b/src/backend/backend.c
index da1fa42996..f094555c33 100644
--- a/src/backend/backend.c
+++ b/src/backend/backend.c
@@ -91,10 +91,10 @@ void paint_all_new(session_t *ps, struct managed_win *t) {
return handle_device_reset(ps);
}
if (ps->o.xrender_sync_fence) {
- if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) {
+ if (ps->xsync_exists && !x_fence_sync(&ps->c, ps->sync_fence)) {
log_error("x_fence_sync failed, xrender-sync-fence will be "
"disabled from now on.");
- xcb_sync_destroy_fence(ps->c, ps->sync_fence);
+ xcb_sync_destroy_fence(ps->c.c, ps->sync_fence);
ps->sync_fence = XCB_NONE;
ps->o.xrender_sync_fence = false;
ps->xsync_exists = false;
@@ -348,7 +348,7 @@ void paint_all_new(session_t *ps, struct managed_win *t) {
}
if (ps->o.crop_shadow_to_monitor && w->randr_monitor >= 0 &&
- w->randr_monitor < ps->randr_nmonitors) {
+ w->randr_monitor < ps->monitors.count) {
// There can be a window where number of monitors is
// updated, but the monitor number attached to the window
// have not.
@@ -358,7 +358,7 @@ void paint_all_new(session_t *ps, struct managed_win *t) {
// bounds.
pixman_region32_intersect(
®_shadow, ®_shadow,
- &ps->randr_monitor_regs[w->randr_monitor]);
+ &ps->monitors.regions[w->randr_monitor]);
}
if (ps->o.transparent_clipping) {
diff --git a/src/backend/backend.h b/src/backend/backend.h
index 7cd64a082b..3ed7a761a8 100644
--- a/src/backend/backend.h
+++ b/src/backend/backend.h
@@ -23,8 +23,7 @@ struct backend_operations;
typedef struct backend_base {
struct backend_operations *ops;
- xcb_connection_t *c;
- xcb_window_t root;
+ struct x_connection *c;
struct ev_loop *loop;
/// Whether the backend can accept new render request at the moment
diff --git a/src/backend/backend_common.c b/src/backend/backend_common.c
index ecdefa4cf5..5b24c67a8c 100644
--- a/src/backend/backend_common.c
+++ b/src/backend/backend_common.c
@@ -19,17 +19,18 @@
/**
* Generate a 1x1 Picture
of a particular color.
*/
-xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool argb,
- double a, double r, double g, double b) {
+xcb_render_picture_t
+solid_picture(struct x_connection *c, bool argb, double a, double r, double g, double b) {
xcb_pixmap_t pixmap;
xcb_render_picture_t picture;
xcb_render_create_picture_value_list_t pa;
xcb_render_color_t col;
xcb_rectangle_t rect;
- pixmap = x_create_pixmap(c, argb ? 32 : 8, d, 1, 1);
- if (!pixmap)
+ pixmap = x_create_pixmap(c, argb ? 32 : 8, 1, 1);
+ if (!pixmap) {
return XCB_NONE;
+ }
pa.repeat = 1;
picture = x_create_picture_with_standard_and_pixmap(
@@ -37,7 +38,7 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a
XCB_RENDER_CP_REPEAT, &pa);
if (!picture) {
- xcb_free_pixmap(c, pixmap);
+ xcb_free_pixmap(c->c, pixmap);
return XCB_NONE;
}
@@ -51,14 +52,14 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a
rect.width = 1;
rect.height = 1;
- xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect);
- xcb_free_pixmap(c, pixmap);
+ xcb_render_fill_rectangles(c->c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect);
+ xcb_free_pixmap(c->c, pixmap);
return picture;
}
-xcb_image_t *
-make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height) {
+xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity,
+ int width, int height) {
/*
* We classify shadows into 4 kinds of regions
* r = shadow radius
@@ -84,8 +85,9 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
assert(d % 2 == 1);
assert(d > 0);
- ximage = xcb_image_create_native(c, to_u16_checked(swidth), to_u16_checked(sheight),
- XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
+ ximage =
+ xcb_image_create_native(c->c, to_u16_checked(swidth), to_u16_checked(sheight),
+ XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
if (!ximage) {
log_error("failed to create an X image");
return 0;
@@ -193,7 +195,7 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
/**
* Generate shadow Picture
for a window.
*/
-bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const int width,
+bool build_shadow(struct x_connection *c, double opacity, const int width,
const int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict) {
xcb_image_t *shadow_image = NULL;
@@ -207,9 +209,9 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
return false;
}
- shadow_pixmap = x_create_pixmap(c, 8, d, shadow_image->width, shadow_image->height);
+ shadow_pixmap = x_create_pixmap(c, 8, shadow_image->width, shadow_image->height);
shadow_pixmap_argb =
- x_create_pixmap(c, 32, d, shadow_image->width, shadow_image->height);
+ x_create_pixmap(c, 32, shadow_image->width, shadow_image->height);
if (!shadow_pixmap || !shadow_pixmap_argb) {
log_error("Failed to create shadow pixmaps");
@@ -225,11 +227,11 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
}
gc = x_new_id(c);
- xcb_create_gc(c, gc, shadow_pixmap, 0, NULL);
+ xcb_create_gc(c->c, gc, shadow_pixmap, 0, NULL);
// We need to make room for protocol metadata in the request. The metadata should
// be 24 bytes plus padding, let's be generous and give it 1kb
- auto maximum_image_size = xcb_get_maximum_request_length(c) * 4 - 1024;
+ auto maximum_image_size = xcb_get_maximum_request_length(c->c) * 4 - 1024;
auto maximum_row =
to_u16_checked(clamp(maximum_image_size / shadow_image->stride, 0, UINT16_MAX));
if (maximum_row <= 0) {
@@ -248,23 +250,23 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
}
uint32_t offset = row * shadow_image->stride / sizeof(*shadow_image->data);
- xcb_put_image(c, (uint8_t)shadow_image->format, shadow_pixmap, gc,
+ xcb_put_image(c->c, (uint8_t)shadow_image->format, shadow_pixmap, gc,
shadow_image->width, batch_height, 0, to_i16_checked(row),
0, shadow_image->depth, shadow_image->stride * batch_height,
shadow_image->data + offset);
}
- xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, shadow_pixel, shadow_picture,
+ xcb_render_composite(c->c, XCB_RENDER_PICT_OP_SRC, shadow_pixel, shadow_picture,
shadow_picture_argb, 0, 0, 0, 0, 0, 0, shadow_image->width,
shadow_image->height);
*pixmap = shadow_pixmap_argb;
*pict = shadow_picture_argb;
- xcb_free_gc(c, gc);
+ xcb_free_gc(c->c, gc);
xcb_image_destroy(shadow_image);
- xcb_free_pixmap(c, shadow_pixmap);
- xcb_render_free_picture(c, shadow_picture);
+ xcb_free_pixmap(c->c, shadow_pixmap);
+ x_free_picture(c, shadow_picture);
return true;
@@ -273,19 +275,19 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
xcb_image_destroy(shadow_image);
}
if (shadow_pixmap) {
- xcb_free_pixmap(c, shadow_pixmap);
+ xcb_free_pixmap(c->c, shadow_pixmap);
}
if (shadow_pixmap_argb) {
- xcb_free_pixmap(c, shadow_pixmap_argb);
+ xcb_free_pixmap(c->c, shadow_pixmap_argb);
}
if (shadow_picture) {
- xcb_render_free_picture(c, shadow_picture);
+ x_free_picture(c, shadow_picture);
}
if (shadow_picture_argb) {
- xcb_render_free_picture(c, shadow_picture_argb);
+ x_free_picture(c, shadow_picture_argb);
}
if (gc) {
- xcb_free_gc(c, gc);
+ xcb_free_gc(c->c, gc);
}
return false;
@@ -294,22 +296,22 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
void *default_backend_render_shadow(backend_t *backend_data, int width, int height,
struct backend_shadow_context *sctx, struct color color) {
const conv *kernel = (void *)sctx;
- xcb_render_picture_t shadow_pixel = solid_picture(
- backend_data->c, backend_data->root, true, 1, color.red, color.green, color.blue);
+ xcb_render_picture_t shadow_pixel =
+ solid_picture(backend_data->c, true, 1, color.red, color.green, color.blue);
xcb_pixmap_t shadow = XCB_NONE;
xcb_render_picture_t pict = XCB_NONE;
- if (!build_shadow(backend_data->c, backend_data->root, color.alpha, width, height,
- kernel, shadow_pixel, &shadow, &pict)) {
- xcb_render_free_picture(backend_data->c, shadow_pixel);
+ if (!build_shadow(backend_data->c, color.alpha, width, height, kernel,
+ shadow_pixel, &shadow, &pict)) {
+ x_free_picture(backend_data->c, shadow_pixel);
return NULL;
}
auto visual = x_get_visual_for_standard(backend_data->c, XCB_PICT_STANDARD_ARGB_32);
void *ret = backend_data->ops->bind_pixmap(
backend_data, shadow, x_get_visual_info(backend_data->c, visual), true);
- xcb_render_free_picture(backend_data->c, pict);
- xcb_render_free_picture(backend_data->c, shadow_pixel);
+ x_free_picture(backend_data->c, pict);
+ x_free_picture(backend_data->c, shadow_pixel);
return ret;
}
@@ -506,9 +508,8 @@ struct backend_image *default_new_backend_image(int w, int h) {
}
void init_backend_base(struct backend_base *base, session_t *ps) {
- base->c = ps->c;
+ base->c = &ps->c;
base->loop = ps->loop;
- base->root = ps->root;
base->busy = false;
base->ops = NULL;
}
diff --git a/src/backend/backend_common.h b/src/backend/backend_common.h
index c72a1686b3..2e49cecf71 100644
--- a/src/backend/backend_common.h
+++ b/src/backend/backend_common.h
@@ -44,15 +44,15 @@ struct backend_image {
int border_width;
};
-bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, int width,
- int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
+bool build_shadow(struct x_connection *, double opacity, int width, int height,
+ const conv *kernel, xcb_render_picture_t shadow_pixel,
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict);
-xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb,
- double a, double r, double g, double b);
+xcb_render_picture_t
+solid_picture(struct x_connection *, bool argb, double a, double r, double g, double b);
-xcb_image_t *
-make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height);
+xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity,
+ int width, int height);
/// The default implementation of `is_win_transparent`, it simply looks at win::mode. So
/// this is not suitable for backends that alter the content of windows
diff --git a/src/backend/dummy/dummy.c b/src/backend/dummy/dummy.c
index 5f5e1229a7..4e3d713873 100644
--- a/src/backend/dummy/dummy.c
+++ b/src/backend/dummy/dummy.c
@@ -30,9 +30,8 @@ struct dummy_data {
struct backend_base *dummy_init(struct session *ps attr_unused) {
auto ret = (struct backend_base *)ccalloc(1, struct dummy_data);
- ret->c = ps->c;
+ ret->c = &ps->c;
ret->loop = ps->loop;
- ret->root = ps->root;
ret->busy = false;
return ret;
}
@@ -44,7 +43,7 @@ void dummy_deinit(struct backend_base *data) {
HASH_DEL(dummy->images, img);
free(img->refcount);
if (img->owned) {
- xcb_free_pixmap(data->c, img->pixmap);
+ xcb_free_pixmap(data->c->c, img->pixmap);
}
free(img);
}
@@ -118,7 +117,7 @@ void dummy_release_image(backend_t *base, void *image) {
HASH_DEL(dummy->images, img);
free(img->refcount);
if (img->owned) {
- xcb_free_pixmap(base->c, img->pixmap);
+ xcb_free_pixmap(base->c->c, img->pixmap);
}
free(img);
}
diff --git a/src/backend/gl/egl.c b/src/backend/gl/egl.c
index 761eb63504..a78c1903da 100644
--- a/src/backend/gl/egl.c
+++ b/src/backend/gl/egl.c
@@ -79,7 +79,7 @@ static void egl_release_image(backend_t *base, struct gl_texture *tex) {
}
if (p->owned) {
- xcb_free_pixmap(base->c, p->pixmap);
+ xcb_free_pixmap(base->c->c, p->pixmap);
p->pixmap = XCB_NONE;
}
@@ -154,10 +154,10 @@ static backend_t *egl_init(session_t *ps) {
}
gd = ccalloc(1, struct egl_data);
- gd->display = eglGetPlatformDisplayProc(EGL_PLATFORM_X11_EXT, ps->dpy,
+ gd->display = eglGetPlatformDisplayProc(EGL_PLATFORM_X11_EXT, ps->c.dpy,
(EGLAttrib[]){
EGL_PLATFORM_X11_SCREEN_EXT,
- ps->scr,
+ ps->c.screen,
EGL_NONE,
});
if (gd->display == EGL_NO_DISPLAY) {
@@ -190,7 +190,7 @@ static backend_t *egl_init(session_t *ps) {
goto end;
}
- auto visual_info = x_get_visual_info(ps->c, ps->vis);
+ auto visual_info = x_get_visual_info(&ps->c, ps->c.screen_info->root_visual);
EGLConfig config = NULL;
int nconfigs = 1;
// clang-format off
@@ -280,7 +280,8 @@ egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
struct egl_data *gd = (void *)base;
struct egl_pixmap *eglpixmap = NULL;
- auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL);
+ auto r =
+ xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), NULL);
if (!r) {
log_error("Invalid pixmap %#010x", pixmap);
return NULL;
@@ -335,7 +336,7 @@ egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
free(eglpixmap);
if (owned) {
- xcb_free_pixmap(base->c, pixmap);
+ xcb_free_pixmap(base->c->c, pixmap);
}
free(wd);
return NULL;
diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c
index 80056c6798..d30dc9f291 100644
--- a/src/backend/gl/glx.c
+++ b/src/backend/gl/glx.c
@@ -42,8 +42,6 @@ struct _glx_pixmap {
struct _glx_data {
struct gl_data gl;
- Display *display;
- int screen;
xcb_window_t target_win;
GLXContext ctx;
};
@@ -52,18 +50,18 @@ struct _glx_data {
do { \
if (glXGetFBConfigAttrib(a, b, attr, c)) { \
log_info("Cannot get FBConfig attribute " #attr); \
- continue; \
+ break; \
} \
} while (0)
-struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvisual_info m) {
+struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *c, struct xvisual_info m) {
log_debug("Looking for FBConfig for RGBA%d%d%d%d, depth %d", m.red_size,
m.blue_size, m.green_size, m.alpha_size, m.visual_depth);
int ncfg;
// clang-format off
GLXFBConfig *cfg =
- glXChooseFBConfig(dpy, screen, (int[]){
+ glXChooseFBConfig(c->dpy, c->screen, (int[]){
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
@@ -87,25 +85,26 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
GLXFBConfig ret;
for (int i = 0; i < ncfg; i++) {
int depthbuf, stencil, doublebuf, bufsize;
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BUFFER_SIZE, &bufsize);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_DEPTH_SIZE, &depthbuf);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_STENCIL_SIZE, &stencil);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_DOUBLEBUFFER, &doublebuf);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_BUFFER_SIZE, &bufsize);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_DEPTH_SIZE, &depthbuf);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_STENCIL_SIZE, &stencil);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_DOUBLEBUFFER, &doublebuf);
if (depthbuf + stencil + bufsize * (doublebuf + 1) >= min_cost) {
continue;
}
int red, green, blue;
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_RED_SIZE, &red);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BLUE_SIZE, &blue);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_GREEN_SIZE, &green);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_RED_SIZE, &red);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_BLUE_SIZE, &blue);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_GREEN_SIZE, &green);
if (red != m.red_size || green != m.green_size || blue != m.blue_size) {
// Color size doesn't match, this cannot work
continue;
}
int rgb, rgba;
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &rgb);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BIND_TO_TEXTURE_RGBA_EXT, &rgba);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &rgb);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_BIND_TO_TEXTURE_RGBA_EXT,
+ &rgba);
if (!rgb && !rgba) {
log_info("FBConfig is neither RGBA nor RGB, we cannot "
"handle this setup.");
@@ -113,10 +112,9 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
}
int visual;
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_VISUAL_ID, &visual);
if (m.visual_depth != -1 &&
- x_get_visual_depth(XGetXCBConnection(dpy), (xcb_visualid_t)visual) !=
- m.visual_depth) {
+ x_get_visual_depth(c, (xcb_visualid_t)visual) != m.visual_depth) {
// FBConfig and the correspondent X Visual might not have the same
// depth. (e.g. 32 bit FBConfig with a 24 bit Visual). This is
// quite common, seen in both open source and proprietary drivers.
@@ -129,9 +127,9 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
// All check passed, we are using this one.
found = true;
ret = cfg[i];
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT,
- &texture_tgts);
- glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_Y_INVERTED_EXT, &y_inverted);
+ glXGetFBConfigAttribChecked(
+ c->dpy, cfg[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT, &texture_tgts);
+ glXGetFBConfigAttribChecked(c->dpy, cfg[i], GLX_Y_INVERTED_EXT, &y_inverted);
// Prefer the texture format with matching alpha, with the other one as
// fallback
@@ -161,24 +159,22 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
* Free a glx_texture_t.
*/
static void glx_release_image(backend_t *base, struct gl_texture *tex) {
- struct _glx_data *gd = (void *)base;
-
struct _glx_pixmap *p = tex->user_data;
// Release binding
if (p->glpixmap && tex->texture) {
glBindTexture(GL_TEXTURE_2D, tex->texture);
- glXReleaseTexImageEXT(gd->display, p->glpixmap, GLX_FRONT_LEFT_EXT);
+ glXReleaseTexImageEXT(base->c->dpy, p->glpixmap, GLX_FRONT_LEFT_EXT);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Free GLX Pixmap
if (p->glpixmap) {
- glXDestroyPixmap(gd->display, p->glpixmap);
+ glXDestroyPixmap(base->c->dpy, p->glpixmap);
p->glpixmap = 0;
}
if (p->owned) {
- xcb_free_pixmap(base->c, p->pixmap);
+ xcb_free_pixmap(base->c->c, p->pixmap);
p->pixmap = XCB_NONE;
}
@@ -196,8 +192,8 @@ void glx_deinit(backend_t *base) {
// Destroy GLX context
if (gd->ctx) {
- glXMakeCurrent(gd->display, None, NULL);
- glXDestroyContext(gd->display, gd->ctx);
+ glXMakeCurrent(base->c->dpy, None, NULL);
+ glXDestroyContext(base->c->dpy, gd->ctx);
gd->ctx = 0;
}
@@ -233,12 +229,10 @@ static bool glx_set_swap_interval(int interval, Display *dpy, GLXDrawable drawab
*/
static backend_t *glx_init(session_t *ps) {
bool success = false;
- glxext_init(ps->dpy, ps->scr);
+ glxext_init(ps->c.dpy, ps->c.screen);
auto gd = ccalloc(1, struct _glx_data);
init_backend_base(&gd->gl.base, ps);
- gd->display = ps->dpy;
- gd->screen = ps->scr;
gd->target_win = session_get_target_window(ps);
XVisualInfo *pvis = NULL;
@@ -251,8 +245,8 @@ static backend_t *glx_init(session_t *ps) {
// Get XVisualInfo
int nitems = 0;
- XVisualInfo vreq = {.visualid = ps->vis};
- pvis = XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
+ XVisualInfo vreq = {.visualid = ps->c.screen_info->root_visual};
+ pvis = XGetVisualInfo(ps->c.dpy, VisualIDMask, &vreq, &nitems);
if (!pvis) {
log_error("Failed to acquire XVisualInfo for current visual.");
goto end;
@@ -260,22 +254,22 @@ static backend_t *glx_init(session_t *ps) {
// Ensure the visual is double-buffered
int value = 0;
- if (glXGetConfig(ps->dpy, pvis, GLX_USE_GL, &value) || !value) {
+ if (glXGetConfig(ps->c.dpy, pvis, GLX_USE_GL, &value) || !value) {
log_error("Root visual is not a GL visual.");
goto end;
}
- if (glXGetConfig(ps->dpy, pvis, GLX_STENCIL_SIZE, &value) || !value) {
+ if (glXGetConfig(ps->c.dpy, pvis, GLX_STENCIL_SIZE, &value) || !value) {
log_error("Root visual lacks stencil buffer.");
goto end;
}
- if (glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value) || !value) {
+ if (glXGetConfig(ps->c.dpy, pvis, GLX_DOUBLEBUFFER, &value) || !value) {
log_error("Root visual is not a double buffered GL visual.");
goto end;
}
- if (glXGetConfig(ps->dpy, pvis, GLX_RGBA, &value) || !value) {
+ if (glXGetConfig(ps->c.dpy, pvis, GLX_RGBA, &value) || !value) {
log_error("Root visual is a color index visual, not supported");
goto end;
}
@@ -293,11 +287,11 @@ static backend_t *glx_init(session_t *ps) {
// Find a fbconfig with visualid matching the one from the target win, so we can
// be sure that the fbconfig is compatible with our target window.
int ncfgs;
- GLXFBConfig *cfg = glXGetFBConfigs(gd->display, gd->screen, &ncfgs);
+ GLXFBConfig *cfg = glXGetFBConfigs(ps->c.dpy, ps->c.screen, &ncfgs);
bool found = false;
for (int i = 0; i < ncfgs; i++) {
int visualid;
- glXGetFBConfigAttribChecked(gd->display, cfg[i], GLX_VISUAL_ID, &visualid);
+ glXGetFBConfigAttribChecked(ps->c.dpy, cfg[i], GLX_VISUAL_ID, &visualid);
if ((VisualID)visualid != pvis->visualid) {
continue;
}
@@ -316,7 +310,7 @@ static backend_t *glx_init(session_t *ps) {
attributes[7] = GLX_LOSE_CONTEXT_ON_RESET_ARB;
}
- gd->ctx = glXCreateContextAttribsARB(ps->dpy, cfg[i], 0, true, attributes);
+ gd->ctx = glXCreateContextAttribsARB(ps->c.dpy, cfg[i], 0, true, attributes);
free(cfg);
if (!gd->ctx) {
@@ -334,7 +328,7 @@ static backend_t *glx_init(session_t *ps) {
// Attach GLX context
GLXDrawable tgt = gd->target_win;
- if (!glXMakeCurrent(ps->dpy, tgt, gd->ctx)) {
+ if (!glXMakeCurrent(ps->c.dpy, tgt, gd->ctx)) {
log_error("Failed to attach GLX context.");
goto end;
}
@@ -348,11 +342,11 @@ static backend_t *glx_init(session_t *ps) {
gd->gl.release_user_data = glx_release_image;
if (ps->o.vsync) {
- if (!glx_set_swap_interval(1, ps->dpy, tgt)) {
+ if (!glx_set_swap_interval(1, ps->c.dpy, tgt)) {
log_error("Failed to enable vsync.");
}
} else {
- glx_set_swap_interval(0, ps->dpy, tgt);
+ glx_set_swap_interval(0, ps->c.dpy, tgt);
}
success = true;
@@ -372,7 +366,6 @@ static backend_t *glx_init(session_t *ps) {
static void *
glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) {
- struct _glx_data *gd = (void *)base;
struct _glx_pixmap *glxpixmap = NULL;
// Retrieve pixmap parameters, if they aren't provided
if (fmt.visual_depth > OPENGL_MAX_DEPTH) {
@@ -386,7 +379,8 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
return false;
}
- auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL);
+ auto r =
+ xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), NULL);
if (!r) {
log_error("Invalid pixmap %#010x", pixmap);
return NULL;
@@ -400,7 +394,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
wd->inner = (struct backend_image_inner_base *)inner;
free(r);
- auto fbcfg = glx_find_fbconfig(gd->display, gd->screen, fmt);
+ auto fbcfg = glx_find_fbconfig(base->c, fmt);
if (!fbcfg) {
log_error("Couldn't find FBConfig with requested visual %x", fmt.visual);
goto err;
@@ -429,7 +423,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
glxpixmap = cmalloc(struct _glx_pixmap);
glxpixmap->pixmap = pixmap;
- glxpixmap->glpixmap = glXCreatePixmap(gd->display, fbcfg->cfg, pixmap, attrs);
+ glxpixmap->glpixmap = glXCreatePixmap(base->c->dpy, fbcfg->cfg, pixmap, attrs);
glxpixmap->owned = owned;
free(fbcfg);
@@ -446,19 +440,19 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
inner->has_alpha = fmt.alpha_size != 0;
wd->inner->refcount = 1;
glBindTexture(GL_TEXTURE_2D, inner->texture);
- glXBindTexImageEXT(gd->display, glxpixmap->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
+ glXBindTexImageEXT(base->c->dpy, glxpixmap->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
gl_check_err();
return wd;
err:
if (glxpixmap && glxpixmap->glpixmap) {
- glXDestroyPixmap(gd->display, glxpixmap->glpixmap);
+ glXDestroyPixmap(base->c->dpy, glxpixmap->glpixmap);
}
free(glxpixmap);
if (owned) {
- xcb_free_pixmap(base->c, pixmap);
+ xcb_free_pixmap(base->c->c, pixmap);
}
free(wd);
return NULL;
@@ -467,7 +461,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
static void glx_present(backend_t *base, const region_t *region attr_unused) {
struct _glx_data *gd = (void *)base;
gl_present(base, region);
- glXSwapBuffers(gd->display, gd->target_win);
+ glXSwapBuffers(base->c->dpy, gd->target_win);
}
static int glx_buffer_age(backend_t *base) {
@@ -477,15 +471,14 @@ static int glx_buffer_age(backend_t *base) {
struct _glx_data *gd = (void *)base;
unsigned int val;
- glXQueryDrawable(gd->display, gd->target_win, GLX_BACK_BUFFER_AGE_EXT, &val);
+ glXQueryDrawable(base->c->dpy, gd->target_win, GLX_BACK_BUFFER_AGE_EXT, &val);
return (int)val ?: -1;
}
static void glx_diagnostics(backend_t *base) {
- struct _glx_data *gd = (void *)base;
bool warn_software_rendering = false;
const char *software_renderer_names[] = {"llvmpipe", "SWR", "softpipe"};
- auto glx_vendor = glXGetClientString(gd->display, GLX_VENDOR);
+ auto glx_vendor = glXGetClientString(base->c->dpy, GLX_VENDOR);
printf("* Driver vendors:\n");
printf(" * GLX: %s\n", glx_vendor);
printf(" * GL: %s\n", glGetString(GL_VENDOR));
diff --git a/src/backend/gl/glx.h b/src/backend/gl/glx.h
index 44b4da0595..ce8702a974 100644
--- a/src/backend/gl/glx.h
+++ b/src/backend/gl/glx.h
@@ -41,8 +41,7 @@ struct glx_fbconfig_criteria {
int visual_depth;
};
-struct glx_fbconfig_info *glx_find_fbconfig(Display *, int screen, struct xvisual_info);
-
+struct glx_fbconfig_info *glx_find_fbconfig(struct x_connection *, struct xvisual_info);
struct glxext_info {
bool initialized;
diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c
index 0041817aca..bb2acd456a 100644
--- a/src/backend/xrender/xrender.c
+++ b/src/backend/xrender/xrender.c
@@ -28,7 +28,6 @@ typedef struct _xrender_data {
backend_t base;
/// If vsync is enabled and supported by the current system
bool vsync;
- xcb_visualid_t default_visual;
/// Target window
xcb_window_t target_win;
/// Painting target, it is either the root or the overlay
@@ -104,9 +103,9 @@ struct xrender_image {
/// Make a picture of size width x height, which has a rounded rectangle of corner_radius
/// rendered in it.
struct xrender_rounded_rectangle_cache *
-make_rounded_corner_cache(xcb_connection_t *c, xcb_render_picture_t src,
- xcb_drawable_t root, int width, int height, int corner_radius) {
- auto picture = x_create_picture_with_standard(c, root, width, height,
+make_rounded_corner_cache(struct x_connection *c, xcb_render_picture_t src, int width,
+ int height, int corner_radius) {
+ auto picture = x_create_picture_with_standard(c, width, height,
XCB_PICT_STANDARD_ARGB_32, 0, NULL);
if (picture == XCB_NONE) {
return NULL;
@@ -160,7 +159,7 @@ make_rounded_corner_cache(xcb_connection_t *c, xcb_render_picture_t src,
}
#undef ADD_POINT
- XCB_AWAIT_VOID(xcb_render_tri_strip, c, XCB_RENDER_PICT_OP_SRC, src, picture,
+ XCB_AWAIT_VOID(xcb_render_tri_strip, c->c, XCB_RENDER_PICT_OP_SRC, src, picture,
x_get_pictfmt_for_standard(c, XCB_PICT_STANDARD_A_8), 0, 0,
(uint32_t)point_count, points);
free(points);
@@ -182,30 +181,29 @@ static xcb_render_picture_t process_mask(struct _xrender_data *xd, struct xrende
*allocated = true;
x_clear_picture_clip_region(xd->base.c, inner->pict);
auto ret = x_create_picture_with_visual(
- xd->base.c, xd->base.root, inner->width, inner->height, inner->visual,
- XCB_RENDER_CP_REPEAT,
+ xd->base.c, inner->width, inner->height, inner->visual, XCB_RENDER_CP_REPEAT,
(xcb_render_create_picture_value_list_t[]){XCB_RENDER_REPEAT_PAD});
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_SRC, inner->pict, XCB_NONE,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_SRC, inner->pict, XCB_NONE,
ret, 0, 0, 0, 0, 0, 0, tmpw, tmph);
// Remember: the mask has a 1-pixel border
if (mask->base.corner_radius != 0) {
if (mask->rounded_rectangle == NULL) {
mask->rounded_rectangle = make_rounded_corner_cache(
- xd->base.c, xd->white_pixel, xd->base.root, inner->width - 2,
+ xd->base.c, xd->white_pixel, inner->width - 2,
inner->height - 2, (int)mask->base.corner_radius);
}
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_IN_REVERSE,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_IN_REVERSE,
mask->rounded_rectangle->p, XCB_NONE, ret, 0, 0, 0,
0, 1, 1, (uint16_t)(tmpw - 2), (uint16_t)(tmph - 2));
}
if (mask->base.color_inverted) {
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_XOR, xd->white_pixel,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_XOR, xd->white_pixel,
XCB_NONE, ret, 0, 0, 0, 0, 0, 0, tmpw, tmph);
}
if (alpha_pict != XCB_NONE) {
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_SRC, ret, alpha_pict,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_SRC, ret, alpha_pict,
ret, 0, 0, 0, 0, 0, 0, to_u16_checked(inner->width),
to_u16_checked(inner->height));
}
@@ -246,43 +244,43 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
pixman_region32_intersect(®, (region_t *)reg_paint, (region_t *)reg_visible);
x_set_picture_clip_region(xd->base.c, result, 0, 0, ®);
if (img->corner_radius != 0 && xrimg->rounded_rectangle == NULL) {
- xrimg->rounded_rectangle = make_rounded_corner_cache(
- xd->base.c, xd->white_pixel, xd->base.root, inner->width,
- inner->height, (int)img->corner_radius);
+ xrimg->rounded_rectangle =
+ make_rounded_corner_cache(xd->base.c, xd->white_pixel, inner->width,
+ inner->height, (int)img->corner_radius);
}
if (((img->color_inverted || img->dim != 0) && has_alpha) || img->corner_radius != 0) {
// Apply image properties using a temporary image, because the source
// image is transparent. Otherwise the properties can be applied directly
// on the target image.
- auto tmp_pict =
- x_create_picture_with_visual(xd->base.c, xd->base.root, inner->width,
- inner->height, inner->visual, 0, NULL);
+ auto tmp_pict = x_create_picture_with_visual(
+ xd->base.c, inner->width, inner->height, inner->visual, 0, NULL);
// Set clip region translated to source coordinate
x_set_picture_clip_region(xd->base.c, tmp_pict, to_i16_checked(-dst.x),
to_i16_checked(-dst.y), ®);
// Copy source -> tmp
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_SRC, inner->pict,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_SRC, inner->pict,
XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
if (img->color_inverted) {
if (inner->has_alpha) {
auto tmp_pict2 = x_create_picture_with_visual(
- xd->base.c, xd->base.root, tmpw, tmph, inner->visual,
- 0, NULL);
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_SRC,
+ xd->base.c, tmpw, tmph, inner->visual, 0, NULL);
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_SRC,
tmp_pict, XCB_NONE, tmp_pict2, 0, 0,
0, 0, 0, 0, tmpw, tmph);
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_DIFFERENCE,
+ xcb_render_composite(xd->base.c->c,
+ XCB_RENDER_PICT_OP_DIFFERENCE,
xd->white_pixel, XCB_NONE, tmp_pict,
0, 0, 0, 0, 0, 0, tmpw, tmph);
xcb_render_composite(
- xd->base.c, XCB_RENDER_PICT_OP_IN_REVERSE, tmp_pict2,
+ xd->base.c->c, XCB_RENDER_PICT_OP_IN_REVERSE, tmp_pict2,
XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
- xcb_render_free_picture(xd->base.c, tmp_pict2);
+ x_free_picture(xd->base.c, tmp_pict2);
} else {
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_DIFFERENCE,
+ xcb_render_composite(xd->base.c->c,
+ XCB_RENDER_PICT_OP_DIFFERENCE,
xd->white_pixel, XCB_NONE, tmp_pict,
0, 0, 0, 0, 0, 0, tmpw, tmph);
}
@@ -297,33 +295,34 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
.height = tmph,
};
- xcb_render_fill_rectangles(xd->base.c, XCB_RENDER_PICT_OP_OVER,
+ xcb_render_fill_rectangles(xd->base.c->c, XCB_RENDER_PICT_OP_OVER,
tmp_pict, dim_color, 1, &rect);
}
if (img->corner_radius != 0 && xrimg->rounded_rectangle != NULL) {
// Clip tmp_pict with a rounded rectangle
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_IN_REVERSE,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_IN_REVERSE,
xrimg->rounded_rectangle->p, XCB_NONE,
tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
}
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_OVER, tmp_pict,
+ xcb_render_composite(xd->base.c->c, XCB_RENDER_PICT_OP_OVER, tmp_pict,
mask_pict, result, 0, 0, mask_dst_x, mask_dst_y,
to_i16_checked(dst.x), to_i16_checked(dst.y), tmpew,
tmpeh);
- xcb_render_free_picture(xd->base.c, tmp_pict);
+ xcb_render_free_picture(xd->base.c->c, tmp_pict);
} else {
uint8_t op = (has_alpha ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC);
- xcb_render_composite(xd->base.c, op, inner->pict, mask_pict, result, 0, 0,
- mask_dst_x, mask_dst_y, to_i16_checked(dst.x),
+ xcb_render_composite(xd->base.c->c, op, inner->pict, mask_pict, result, 0,
+ 0, mask_dst_x, mask_dst_y, to_i16_checked(dst.x),
to_i16_checked(dst.y), tmpew, tmpeh);
if (img->dim != 0 || img->color_inverted) {
// Apply properties, if we reach here, then has_alpha == false
assert(!has_alpha);
if (img->color_inverted) {
- xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_DIFFERENCE,
+ xcb_render_composite(xd->base.c->c,
+ XCB_RENDER_PICT_OP_DIFFERENCE,
xd->white_pixel, XCB_NONE, result, 0,
0, 0, 0, to_i16_checked(dst.x),
to_i16_checked(dst.y), tmpew, tmpeh);
@@ -338,13 +337,14 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
.height = tmpeh,
};
- xcb_render_fill_rectangles(xd->base.c, XCB_RENDER_PICT_OP_OVER,
+ xcb_render_fill_rectangles(xd->base.c->c,
+ XCB_RENDER_PICT_OP_OVER,
result, dim_color, 1, &rect);
}
}
}
if (mask_allocated) {
- xcb_render_free_picture(xd->base.c, mask_pict);
+ x_free_picture(xd->base.c, mask_pict);
}
pixman_region32_fini(®);
}
@@ -362,7 +362,7 @@ static void fill(backend_t *base, struct color c, const region_t *clip) {
x_set_picture_clip_region(base->c, xd->back[2], 0, 0, clip);
// color is in X fixed point representation
xcb_render_fill_rectangles(
- base->c, XCB_RENDER_PICT_OP_OVER, xd->back[2],
+ base->c->c, XCB_RENDER_PICT_OP_OVER, xd->back[2],
(xcb_render_color_t){.red = (uint16_t)(c.red * 0xffff),
.green = (uint16_t)(c.green * 0xffff),
.blue = (uint16_t)(c.blue * 0xffff),
@@ -382,7 +382,7 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
}
struct _xrender_data *xd = (void *)backend_data;
- xcb_connection_t *c = xd->base.c;
+ auto c = xd->base.c;
region_t reg_op;
pixman_region32_init(®_op);
pixman_region32_intersect(®_op, (region_t *)reg_blur, (region_t *)reg_visible);
@@ -405,10 +405,12 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
const uint32_t pic_attrs_mask = XCB_RENDER_CP_REPEAT;
const xcb_render_create_picture_value_list_t pic_attrs = {.repeat = XCB_RENDER_REPEAT_PAD};
xcb_render_picture_t tmp_picture[2] = {
- x_create_picture_with_visual(xd->base.c, xd->base.root, width_resized, height_resized,
- xd->default_visual, pic_attrs_mask, &pic_attrs),
- x_create_picture_with_visual(xd->base.c, xd->base.root, width_resized, height_resized,
- xd->default_visual, pic_attrs_mask, &pic_attrs)};
+ x_create_picture_with_visual(xd->base.c, width_resized, height_resized,
+ xd->base.c->screen_info->root_visual,
+ pic_attrs_mask, &pic_attrs),
+ x_create_picture_with_visual(xd->base.c, width_resized, height_resized,
+ xd->base.c->screen_info->root_visual,
+ pic_attrs_mask, &pic_attrs)};
if (!tmp_picture[0] || !tmp_picture[1]) {
log_error("Failed to build intermediate Picture.");
@@ -445,8 +447,8 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
// Copy from source picture to destination. The filter must
// be applied on source picture, to get the nearby pixels outside the
// window.
- xcb_render_set_picture_filter(c, src_pict, to_u16_checked(strlen(filter)),
- filter,
+ xcb_render_set_picture_filter(c->c, src_pict,
+ to_u16_checked(strlen(filter)), filter,
to_u32_checked(bctx->x_blur_kernel[i]->size),
bctx->x_blur_kernel[i]->kernel);
@@ -454,21 +456,21 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
// First pass, back buffer -> tmp picture
// (we do this even if this is also the last pass, because we
// cannot do back buffer -> back buffer)
- xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
+ xcb_render_composite(c->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
dst_pict, to_i16_checked(extent_resized->x1),
to_i16_checked(extent_resized->y1), 0, 0, 0,
0, width_resized, height_resized);
} else if (i < bctx->x_blur_kernel_count - 1) {
// This is not the last pass or the first pass,
// tmp picture 1 -> tmp picture 2
- xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict,
+ xcb_render_composite(c->c, XCB_RENDER_PICT_OP_SRC, src_pict,
XCB_NONE, dst_pict, 0, 0, 0, 0, 0, 0,
width_resized, height_resized);
} else {
x_set_picture_clip_region(c, xd->back[2], 0, 0, ®_op);
// This is the last pass, and we are doing more than 1 pass
xcb_render_composite(
- c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, xd->back[2],
+ c->c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, xd->back[2],
0, 0, to_i16_checked(extent_resized->x1 - mask_dst.x + 1),
to_i16_checked(extent_resized->y1 - mask_dst.y + 1),
to_i16_checked(extent_resized->x1),
@@ -477,7 +479,7 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
// reset filter
xcb_render_set_picture_filter(
- c, src_pict, to_u16_checked(strlen(filter0)), filter0, 0, NULL);
+ c->c, src_pict, to_u16_checked(strlen(filter0)), filter0, 0, NULL);
src_pict = tmp_picture[current];
dst_pict = tmp_picture[!current];
@@ -488,15 +490,15 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
if (i == 1) {
x_set_picture_clip_region(c, xd->back[2], 0, 0, ®_op);
xcb_render_composite(
- c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, xd->back[2], 0, 0,
+ c->c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, xd->back[2], 0, 0,
to_i16_checked(extent_resized->x1 - mask_dst.x + 1),
to_i16_checked(extent_resized->y1 - mask_dst.y + 1),
to_i16_checked(extent_resized->x1),
to_i16_checked(extent_resized->y1), width_resized, height_resized);
}
- xcb_render_free_picture(c, tmp_picture[0]);
- xcb_render_free_picture(c, tmp_picture[1]);
+ x_free_picture(c, tmp_picture[0]);
+ x_free_picture(c, tmp_picture[1]);
pixman_region32_fini(®_op);
pixman_region32_fini(®_op_resized);
return true;
@@ -505,7 +507,7 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
static void *
bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) {
xcb_generic_error_t *e;
- auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), &e);
+ auto r = xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), &e);
if (!r) {
log_error("Invalid pixmap: %#010x", pixmap);
x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code);
@@ -540,9 +542,9 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool
return img;
}
static void release_image_inner(backend_t *base, struct _xrender_image_data_inner *inner) {
- xcb_render_free_picture(base->c, inner->pict);
+ x_free_picture(base->c, inner->pict);
if (inner->owned) {
- xcb_free_pixmap(base->c, inner->pixmap);
+ xcb_free_pixmap(base->c->c, inner->pixmap);
}
free(inner);
}
@@ -556,7 +558,7 @@ release_rounded_corner_cache(backend_t *base, struct xrender_rounded_rectangle_c
assert(cache->refcount > 0);
cache->refcount--;
if (cache->refcount == 0) {
- xcb_render_free_picture(base->c, cache->p);
+ x_free_picture(base->c, cache->p);
free(cache);
}
}
@@ -575,22 +577,22 @@ static void release_image(backend_t *base, void *image) {
static void deinit(backend_t *backend_data) {
struct _xrender_data *xd = (void *)backend_data;
for (int i = 0; i < 256; i++) {
- xcb_render_free_picture(xd->base.c, xd->alpha_pict[i]);
+ x_free_picture(xd->base.c, xd->alpha_pict[i]);
}
- xcb_render_free_picture(xd->base.c, xd->target);
+ x_free_picture(xd->base.c, xd->target);
for (int i = 0; i < 3; i++) {
if (xd->back[i] != XCB_NONE) {
- xcb_render_free_picture(xd->base.c, xd->back[i]);
+ x_free_picture(xd->base.c, xd->back[i]);
}
if (xd->back_pixmap[i] != XCB_NONE) {
- xcb_free_pixmap(xd->base.c, xd->back_pixmap[i]);
+ xcb_free_pixmap(xd->base.c->c, xd->back_pixmap[i]);
}
}
if (xd->present_event) {
- xcb_unregister_for_special_event(xd->base.c, xd->present_event);
+ xcb_unregister_for_special_event(xd->base.c->c, xd->present_event);
}
- xcb_render_free_picture(xd->base.c, xd->white_pixel);
- xcb_render_free_picture(xd->base.c, xd->black_pixel);
+ x_free_picture(xd->base.c, xd->white_pixel);
+ x_free_picture(xd->base.c, xd->black_pixel);
free(xd);
}
@@ -609,7 +611,7 @@ static void present(backend_t *base, const region_t *region) {
x_clear_picture_clip_region(base->c, xd->back[xd->curr_back]);
// Update the back buffer first, then present
- xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, xd->back[2],
+ xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_SRC, xd->back[2],
XCB_NONE, xd->back[xd->curr_back], orig_x, orig_y, 0,
0, orig_x, orig_y, region_width, region_height);
@@ -618,10 +620,10 @@ static void present(backend_t *base, const region_t *region) {
// Make sure we got reply from PresentPixmap before waiting for events,
// to avoid deadlock
auto e = xcb_request_check(
- base->c, xcb_present_pixmap_checked(
- xd->base.c, xd->target_win,
- xd->back_pixmap[xd->curr_back], 0, XCB_NONE, xregion, 0,
- 0, XCB_NONE, XCB_NONE, XCB_NONE, 0, 0, 0, 0, 0, NULL));
+ base->c->c, xcb_present_pixmap_checked(
+ xd->base.c->c, xd->target_win,
+ xd->back_pixmap[xd->curr_back], 0, XCB_NONE, xregion, 0,
+ 0, XCB_NONE, XCB_NONE, XCB_NONE, 0, 0, 0, 0, 0, NULL));
x_destroy_region(base->c, xregion);
if (e) {
log_error("Failed to present pixmap");
@@ -630,7 +632,7 @@ static void present(backend_t *base, const region_t *region) {
}
// TODO(yshui) don't block wait for present completion
xcb_present_generic_event_t *pev =
- (void *)xcb_wait_for_special_event(base->c, xd->present_event);
+ (void *)xcb_wait_for_special_event(base->c->c, xd->present_event);
if (!pev) {
// We don't know what happened, maybe X died
// But reset buffer age, so in case we do recover, we will
@@ -654,7 +656,7 @@ static void present(backend_t *base, const region_t *region) {
free(pev);
} else {
// No vsync needed, draw into the target picture directly
- xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, xd->back[2],
+ xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_SRC, xd->back[2],
XCB_NONE, xd->target, orig_x, orig_y, 0, 0, orig_x,
orig_y, region_width, region_height);
}
@@ -673,7 +675,7 @@ static int buffer_age(backend_t *backend_data) {
static struct _xrender_image_data_inner *
new_inner(backend_t *base, int w, int h, xcb_visualid_t visual, uint8_t depth) {
auto new_inner = ccalloc(1, struct _xrender_image_data_inner);
- new_inner->pixmap = x_create_pixmap(base->c, depth, base->root, w, h);
+ new_inner->pixmap = x_create_pixmap(base->c, depth, w, h);
if (new_inner->pixmap == XCB_NONE) {
log_error("Failed to create pixmap for copy");
free(new_inner);
@@ -683,7 +685,7 @@ new_inner(backend_t *base, int w, int h, xcb_visualid_t visual, uint8_t depth) {
base->c, visual, new_inner->pixmap, 0, NULL);
if (new_inner->pict == XCB_NONE) {
log_error("Failed to create picture for copy");
- xcb_free_pixmap(base->c, new_inner->pixmap);
+ xcb_free_pixmap(base->c->c, new_inner->pixmap);
free(new_inner);
return NULL;
}
@@ -705,12 +707,12 @@ static void *make_mask(backend_t *base, geometry_t size, const region_t *reg) {
auto inner =
new_inner(base, size.width + 2, size.height + 2,
x_get_visual_for_standard(base->c, XCB_PICT_STANDARD_ARGB_32), 32);
- xcb_render_change_picture(base->c, inner->pict, XCB_RENDER_CP_REPEAT,
+ xcb_render_change_picture(base->c->c, inner->pict, XCB_RENDER_CP_REPEAT,
(uint32_t[]){XCB_RENDER_REPEAT_PAD});
const rect_t *extent = pixman_region32_extents((region_t *)reg);
x_set_picture_clip_region(base->c, xd->back[2], 1, 1, reg);
xcb_render_fill_rectangles(
- base->c, XCB_RENDER_PICT_OP_SRC, inner->pict,
+ base->c->c, XCB_RENDER_PICT_OP_SRC, inner->pict,
(xcb_render_color_t){.red = 0, .green = 0, .blue = 0, .alpha = 0xffff}, 1,
(xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1 + 1),
.y = to_i16_checked(extent->y1 + 1),
@@ -720,7 +722,7 @@ static void *make_mask(backend_t *base, geometry_t size, const region_t *reg) {
// Paint the border transparent
xcb_render_fill_rectangles(
- base->c, XCB_RENDER_PICT_OP_SRC, inner->pict,
+ base->c->c, XCB_RENDER_PICT_OP_SRC, inner->pict,
(xcb_render_color_t){.red = 0, .green = 0, .blue = 0, .alpha = 0}, 4,
(xcb_rectangle_t[]){{.x = 0, .y = 0, .width = w16, .height = 1},
{.x = 0, .y = 0, .width = 1, .height = h16},
@@ -758,7 +760,7 @@ static bool decouple_image(backend_t *base, struct backend_image *img, const reg
}
x_set_picture_clip_region(base->c, inner->pict, 0, 0, reg);
- xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, inner->pict, XCB_NONE,
+ xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_SRC, inner->pict, XCB_NONE,
inner2->pict, 0, 0, 0, 0, 0, 0, to_u16_checked(inner->width),
to_u16_checked(inner->height));
@@ -797,8 +799,8 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
auto inner = (struct _xrender_image_data_inner *)img->inner;
auto alpha_pict = xd->alpha_pict[(int)((1 - dargs[0]) * MAX_ALPHA)];
x_set_picture_clip_region(base->c, inner->pict, 0, 0, ®);
- xcb_render_composite(base->c, XCB_RENDER_PICT_OP_OUT_REVERSE, alpha_pict,
- XCB_NONE, inner->pict, 0, 0, 0, 0, 0, 0,
+ xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_OUT_REVERSE,
+ alpha_pict, XCB_NONE, inner->pict, 0, 0, 0, 0, 0, 0,
to_u16_checked(inner->width),
to_u16_checked(inner->height));
inner->has_alpha = true;
@@ -877,24 +879,24 @@ static backend_t *backend_xrender_init(session_t *ps) {
for (int i = 0; i <= MAX_ALPHA; ++i) {
double o = (double)i / (double)MAX_ALPHA;
- xd->alpha_pict[i] = solid_picture(ps->c, ps->root, false, o, 0, 0, 0);
+ xd->alpha_pict[i] = solid_picture(&ps->c, false, o, 0, 0, 0);
assert(xd->alpha_pict[i] != XCB_NONE);
}
xd->target_width = ps->root_width;
xd->target_height = ps->root_height;
- xd->default_visual = ps->vis;
- xd->black_pixel = solid_picture(ps->c, ps->root, true, 1, 0, 0, 0);
- xd->white_pixel = solid_picture(ps->c, ps->root, true, 1, 1, 1, 1);
+ xd->black_pixel = solid_picture(&ps->c, true, 1, 0, 0, 0);
+ xd->white_pixel = solid_picture(&ps->c, true, 1, 1, 1, 1);
xd->target_win = session_get_target_window(ps);
xcb_render_create_picture_value_list_t pa = {
.subwindowmode = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS,
};
xd->target = x_create_picture_with_visual_and_pixmap(
- ps->c, ps->vis, xd->target_win, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
+ &ps->c, ps->c.screen_info->root_visual, xd->target_win,
+ XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
- auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis);
+ auto pictfmt = x_get_pictform_for_visual(&ps->c, ps->c.screen_info->root_visual);
if (!pictfmt) {
log_fatal("Default visual is invalid");
abort();
@@ -902,11 +904,11 @@ static backend_t *backend_xrender_init(session_t *ps) {
xd->vsync = ps->o.vsync;
if (ps->present_exists) {
- auto eid = x_new_id(ps->c);
+ auto eid = x_new_id(&ps->c);
auto e =
- xcb_request_check(ps->c, xcb_present_select_input_checked(
- ps->c, eid, xd->target_win,
- XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY));
+ xcb_request_check(ps->c.c, xcb_present_select_input_checked(
+ ps->c.c, eid, xd->target_win,
+ XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY));
if (e) {
log_error("Cannot select present input, vsync will be disabled");
xd->vsync = false;
@@ -914,7 +916,7 @@ static backend_t *backend_xrender_init(session_t *ps) {
}
xd->present_event =
- xcb_register_for_special_xge(ps->c, &xcb_present_id, eid, NULL);
+ xcb_register_for_special_xge(ps->c.c, &xcb_present_id, eid, NULL);
if (!xd->present_event) {
log_error("Cannot register for special XGE, vsync will be "
"disabled");
@@ -928,14 +930,14 @@ static backend_t *backend_xrender_init(session_t *ps) {
// double buffering.
int first_buffer_index = xd->vsync ? 0 : 2;
for (int i = first_buffer_index; i < 3; i++) {
- xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root,
- to_u16_checked(ps->root_width),
- to_u16_checked(ps->root_height));
+ xd->back_pixmap[i] =
+ x_create_pixmap(&ps->c, pictfmt->depth, to_u16_checked(ps->root_width),
+ to_u16_checked(ps->root_height));
const uint32_t pic_attrs_mask = XCB_RENDER_CP_REPEAT;
const xcb_render_create_picture_value_list_t pic_attrs = {
.repeat = XCB_RENDER_REPEAT_PAD};
xd->back[i] = x_create_picture_with_pictfmt_and_pixmap(
- ps->c, pictfmt, xd->back_pixmap[i], pic_attrs_mask, &pic_attrs);
+ &ps->c, pictfmt, xd->back_pixmap[i], pic_attrs_mask, &pic_attrs);
xd->buffer_age[i] = -1;
if (xd->back_pixmap[i] == XCB_NONE || xd->back[i] == XCB_NONE) {
log_error("Cannot create pixmap for rendering");
diff --git a/src/c2.c b/src/c2.c
index f8af6992ed..823d30ea7c 100644
--- a/src/c2.c
+++ b/src/c2.c
@@ -336,17 +336,19 @@ static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_p
* Parse a condition string.
*/
c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data) {
- if (!pattern)
+ if (!pattern) {
return NULL;
+ }
// Parse the pattern
c2_ptr_t result = C2_PTR_INIT;
int offset = -1;
- if (strlen(pattern) >= 2 && ':' == pattern[1])
+ if (strlen(pattern) >= 2 && ':' == pattern[1]) {
offset = c2_parse_legacy(pattern, 0, &result);
- else
+ } else {
offset = c2_parse_grp(pattern, 0, &result, 0);
+ }
if (offset < 0) {
c2_freep(&result);
@@ -395,11 +397,13 @@ c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data) {
*/
static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
// Check for recursion levels
- if (level > C2_MAX_LEVELS)
+ if (level > C2_MAX_LEVELS) {
c2_error("Exceeded maximum recursion levels.");
+ }
- if (!pattern)
+ if (!pattern) {
return -1;
+ }
// Expected end character
const char endchar = (offset ? ')' : '\0');
@@ -428,17 +432,20 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
assert(elei <= 2);
// Jump over spaces
- if (isspace((unsigned char)pattern[offset]))
+ if (isspace((unsigned char)pattern[offset])) {
continue;
+ }
// Handle end of group
- if (')' == pattern[offset])
+ if (')' == pattern[offset]) {
break;
+ }
// Handle "!"
if ('!' == pattern[offset]) {
- if (!next_expected)
+ if (!next_expected) {
c2_error("Unexpected \"!\".");
+ }
neg = !neg;
continue;
@@ -446,8 +453,9 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
// Handle AND and OR
if ('&' == pattern[offset] || '|' == pattern[offset]) {
- if (next_expected)
+ if (next_expected) {
c2_error("Unexpected logical operator.");
+ }
next_expected = true;
if (!mstrncmp("&&", pattern + offset)) {
@@ -456,15 +464,17 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
} else if (!mstrncmp("||", pattern + offset)) {
ops[elei] = C2_B_OOR;
++offset;
- } else
+ } else {
c2_error("Illegal logical operator.");
+ }
continue;
}
// Parsing an element
- if (!next_expected)
+ if (!next_expected) {
c2_error("Unexpected expression.");
+ }
assert(!elei || ops[elei]);
@@ -491,21 +501,25 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
// It's a subgroup if it starts with '('
if ('(' == pattern[offset]) {
- if ((offset = c2_parse_grp(pattern, offset + 1, pele, level + 1)) < 0)
+ if ((offset = c2_parse_grp(pattern, offset + 1, pele, level + 1)) < 0) {
goto fail;
+ }
}
// Otherwise it's a leaf
else {
- if ((offset = c2_parse_target(pattern, offset, pele)) < 0)
+ if ((offset = c2_parse_target(pattern, offset, pele)) < 0) {
goto fail;
+ }
assert(!pele->isbranch && !c2_ptr_isempty(*pele));
- if ((offset = c2_parse_op(pattern, offset, pele)) < 0)
+ if ((offset = c2_parse_op(pattern, offset, pele)) < 0) {
goto fail;
+ }
- if ((offset = c2_parse_pattern(pattern, offset, pele)) < 0)
+ if ((offset = c2_parse_pattern(pattern, offset, pele)) < 0) {
goto fail;
+ }
}
// Decrement offset -- we will increment it in loop update
--offset;
@@ -513,10 +527,11 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
// Apply negation
if (neg) {
neg = false;
- if (pele->isbranch)
+ if (pele->isbranch) {
pele->b->neg = !pele->b->neg;
- else
+ } else {
pele->l->neg = !pele->l->neg;
+ }
}
next_expected = false;
@@ -525,10 +540,12 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
}
// Wrong end character?
- if (pattern[offset] && !endchar)
+ if (pattern[offset] && !endchar) {
c2_error("Expected end of string but found '%c'.", pattern[offset]);
- if (!pattern[offset] && endchar)
+ }
+ if (!pattern[offset] && endchar) {
c2_error("Expected '%c' but found end of string.", endchar);
+ }
// Handle end of group
if (!elei) {
@@ -544,8 +561,9 @@ static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int
*presult = eles[0];
- if (')' == pattern[offset])
+ if (')' == pattern[offset]) {
++offset;
+ }
return offset;
@@ -778,11 +796,11 @@ static int c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
// Parse operator
while ('=' == pattern[offset] || '>' == pattern[offset] || '<' == pattern[offset]) {
- if ('=' == pattern[offset] && C2_L_OGT == pleaf->op)
+ if ('=' == pattern[offset] && C2_L_OGT == pleaf->op) {
pleaf->op = C2_L_OGTEQ;
- else if ('=' == pattern[offset] && C2_L_OLT == pleaf->op)
+ } else if ('=' == pattern[offset] && C2_L_OLT == pleaf->op) {
pleaf->op = C2_L_OLTEQ;
- else if (pleaf->op) {
+ } else if (pleaf->op) {
c2_error("Duplicate operator.");
} else {
switch (pattern[offset]) {
@@ -797,9 +815,10 @@ static int c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
}
// Check for problems
- if (C2_L_OEQ != pleaf->op && (pleaf->match || pleaf->match_ignorecase))
+ if (C2_L_OEQ != pleaf->op && (pleaf->match || pleaf->match_ignorecase)) {
c2_error("Exists/greater-than/less-than operators cannot have a "
"qualifier.");
+ }
return offset;
@@ -891,9 +910,10 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
char *pstr = NULL;
long val = strtol(
tstr, &pstr, ('o' == pattern[offset] ? 8 : 16));
- if (pstr != &tstr[2] || val <= 0)
+ if (pstr != &tstr[2] || val <= 0) {
c2_error("Invalid octal/hex escape "
"sequence.");
+ }
*(ptptnstr++) = to_char_checked(val);
offset += 2;
break;
@@ -904,8 +924,9 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
*(ptptnstr++) = pattern[offset];
}
}
- if (!pattern[offset])
+ if (!pattern[offset]) {
c2_error("Premature end of pattern string.");
+ }
++offset;
*ptptnstr = '\0';
pleaf->ptnstr = strdup(tptnstr);
@@ -914,27 +935,32 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
C2H_SKIP_SPACES();
- if (!pleaf->ptntype)
+ if (!pleaf->ptntype) {
c2_error("Invalid pattern type.");
+ }
// Check if the type is correct
if (!(((C2_L_TSTRING == pleaf->type || C2_L_TATOM == pleaf->type) &&
C2_L_PTSTRING == pleaf->ptntype) ||
((C2_L_TCARDINAL == pleaf->type || C2_L_TWINDOW == pleaf->type ||
C2_L_TDRAWABLE == pleaf->type) &&
- C2_L_PTINT == pleaf->ptntype)))
+ C2_L_PTINT == pleaf->ptntype))) {
c2_error("Pattern type incompatible with target type.");
+ }
- if (C2_L_PTINT == pleaf->ptntype && pleaf->match)
+ if (C2_L_PTINT == pleaf->ptntype && pleaf->match) {
c2_error("Integer/boolean pattern cannot have operator qualifiers.");
+ }
- if (C2_L_PTINT == pleaf->ptntype && pleaf->match_ignorecase)
+ if (C2_L_PTINT == pleaf->ptntype && pleaf->match_ignorecase) {
c2_error("Integer/boolean pattern cannot have flags.");
+ }
if (C2_L_PTSTRING == pleaf->ptntype &&
(C2_L_OGT == pleaf->op || C2_L_OGTEQ == pleaf->op || C2_L_OLT == pleaf->op ||
- C2_L_OLTEQ == pleaf->op))
+ C2_L_OLTEQ == pleaf->op)) {
c2_error("String pattern cannot have an arithmetic operator.");
+ }
return offset;
@@ -1173,9 +1199,8 @@ c2_lptr_t *c2_free_lptr(c2_lptr_t *lp, c2_userdata_free f) {
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) {
if (pleaf->predef != C2_L_PUNDEFINED) {
return C2_PREDEFS[pleaf->predef].name;
- } else {
- return pleaf->tgt;
}
+ return pleaf->tgt;
}
/**
@@ -1378,11 +1403,11 @@ static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w
int word_count = 1;
if (pleaf->index < 0) {
// Get length of property in 32-bit multiples
- auto prop_info = x_get_prop_info(ps->c, wid, pleaf->tgtatom);
+ auto prop_info = x_get_prop_info(&ps->c, wid, pleaf->tgtatom);
word_count = to_int_checked((prop_info.length + 4 - 1) / 4);
}
winprop_t prop = x_get_prop_with_offset(
- ps->c, wid, pleaf->tgtatom, idx, word_count,
+ &ps->c, wid, pleaf->tgtatom, idx, word_count,
c2_get_atom_type(pleaf), pleaf->format);
ntargets = (pleaf->index < 0 ? prop.nitems : min2(prop.nitems, 1));
@@ -1455,11 +1480,11 @@ static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w
int word_count = 1;
if (pleaf->index < 0) {
// Get length of property in 32-bit multiples
- auto prop_info = x_get_prop_info(ps->c, wid, pleaf->tgtatom);
+ auto prop_info = x_get_prop_info(&ps->c, wid, pleaf->tgtatom);
word_count = to_int_checked((prop_info.length + 4 - 1) / 4);
}
winprop_t prop = x_get_prop_with_offset(
- ps->c, wid, pleaf->tgtatom, idx, word_count,
+ &ps->c, wid, pleaf->tgtatom, idx, word_count,
c2_get_atom_type(pleaf), pleaf->format);
ntargets = (pleaf->index < 0 ? prop.nitems : min2(prop.nitems, 1));
@@ -1470,7 +1495,7 @@ static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w
xcb_atom_t atom = (xcb_atom_t)winprop_get_int(prop, i);
if (atom) {
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
- ps->c, xcb_get_atom_name(ps->c, atom), NULL);
+ ps->c.c, xcb_get_atom_name(ps->c.c, atom), NULL);
if (reply) {
targets[i] = targets_free_inner[i] = strndup(
xcb_get_atom_name_name(reply),
@@ -1599,8 +1624,9 @@ static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_p
if (cond.isbranch) {
const c2_b_t *pb = cond.b;
- if (!pb)
+ if (!pb) {
return false;
+ }
error = false;
@@ -1630,8 +1656,9 @@ static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_p
else {
const c2_l_t *pleaf = cond.l;
- if (!pleaf)
+ if (!pleaf) {
return false;
+ }
c2_match_once_leaf(ps, w, pleaf, &result, &error);
@@ -1651,11 +1678,13 @@ static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_p
}
// Postprocess the result
- if (error)
+ if (error) {
result = false;
+ }
- if (cond.isbranch ? cond.b->neg : cond.l->neg)
+ if (cond.isbranch ? cond.b->neg : cond.l->neg) {
result = !result;
+ }
return result;
}
@@ -1673,8 +1702,9 @@ bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condl
// Then go through the whole linked list
for (; condlst; condlst = condlst->next) {
if (c2_match_once(ps, w, condlst->ptr)) {
- if (pdata)
+ if (pdata) {
*pdata = condlst->data;
+ }
return true;
}
}
diff --git a/src/common.h b/src/common.h
index e183a1e6b0..707d00e714 100644
--- a/src/common.h
+++ b/src/common.h
@@ -84,18 +84,6 @@ struct glx_session;
struct atom;
struct conv;
-enum pending_reply_action {
- PENDING_REPLY_ACTION_IGNORE,
- PENDING_REPLY_ACTION_ABORT,
- PENDING_REPLY_ACTION_DEBUG_ABORT,
-};
-
-typedef struct pending_reply {
- struct pending_reply *next;
- unsigned long sequence;
- enum pending_reply_action action;
-} pending_reply_t;
-
#ifdef CONFIG_OPENGL
#ifdef DEBUG_GLX_DEBUG_CONTEXT
typedef GLXContext (*f_glXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config,
@@ -183,28 +171,14 @@ typedef struct session {
struct shader_info *shaders;
// === Display related ===
+ /// X connection
+ struct x_connection c;
/// Whether the X server is grabbed by us
bool server_grabbed;
- /// Display in use.
- Display *dpy;
- /// Previous handler of X errors
- XErrorHandler previous_xerror_handler;
- /// Default screen.
- int scr;
- /// XCB connection.
- xcb_connection_t *c;
- /// Default visual.
- xcb_visualid_t vis;
- /// Default depth.
- int depth;
- /// Root window.
- xcb_window_t root;
- /// Height of root window.
- int root_height;
/// Width of root window.
int root_width;
- // Damage of root window.
- // Damage root_damage;
+ /// Height of root window.
+ int root_height;
/// X Composite overlay window.
xcb_window_t overlay;
/// The target window for debug mode
@@ -289,11 +263,6 @@ typedef struct session {
xcb_render_picture_t *alpha_picts;
/// Time of last fading. In milliseconds.
long long fade_time;
- /// Head pointer of the error ignore linked list.
- pending_reply_t *pending_reply_head;
- /// Pointer to the next
member of tail element of the error
- /// ignore linked list.
- pending_reply_t **pending_reply_tail;
// Cached blur convolution kernels.
struct x_convolution_kernel **blur_kerns_cache;
/// If we should quit
@@ -391,10 +360,8 @@ typedef struct session {
int glx_event;
/// Error base number for X GLX extension.
int glx_error;
- /// Number of X RandR monitors.
- int randr_nmonitors;
- /// X RandR monitor regions.
- region_t *randr_monitor_regs;
+ /// Information about monitors.
+ struct x_monitors monitors;
/// Whether X Sync extension exists.
bool xsync_exists;
/// Event base number for X Sync extension.
@@ -492,7 +459,7 @@ static inline struct timespec get_time_timespec(void) {
* Return the painting target window.
*/
static inline xcb_window_t get_tgt_window(session_t *ps) {
- return ps->overlay != XCB_NONE ? ps->overlay : ps->root;
+ return ps->overlay != XCB_NONE ? ps->overlay : ps->c.screen_info->root;
}
/**
@@ -502,35 +469,6 @@ static inline bool bkend_use_glx(session_t *ps) {
return BKEND_GLX == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend;
}
-static void
-set_reply_action(session_t *ps, uint32_t sequence, enum pending_reply_action action) {
- auto i = cmalloc(pending_reply_t);
- if (!i) {
- abort();
- }
-
- i->sequence = sequence;
- i->next = 0;
- i->action = action;
- *ps->pending_reply_tail = i;
- ps->pending_reply_tail = &i->next;
-}
-
-/**
- * Ignore X errors caused by given X request.
- */
-static inline void set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) {
- if (ps->o.show_all_xerrors) {
- return;
- }
-
- set_reply_action(ps, cookie.sequence, PENDING_REPLY_ACTION_IGNORE);
-}
-
-static inline void set_cant_fail_cookie(session_t *ps, xcb_void_cookie_t cookie) {
- set_reply_action(ps, cookie.sequence, PENDING_REPLY_ACTION_ABORT);
-}
-
/**
* Determine if a window has a specific property.
*
@@ -541,7 +479,8 @@ static inline void set_cant_fail_cookie(session_t *ps, xcb_void_cookie_t cookie)
*/
static inline bool wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) {
auto r = xcb_get_property_reply(
- ps->c, xcb_get_property(ps->c, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0), NULL);
+ ps->c.c,
+ xcb_get_property(ps->c.c, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0), NULL);
if (!r) {
return false;
}
diff --git a/src/dbus.c b/src/dbus.c
index baff2bcc1a..ad98a0f2ae 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -1165,7 +1165,7 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
// display
if (!strcmp("display", target)) {
- cdbus_reply_string(ps, msg, DisplayString(ps->dpy));
+ cdbus_reply_string(ps, msg, DisplayString(ps->c.dpy));
return true;
}
diff --git a/src/event.c b/src/event.c
index b140082874..807cf4ed96 100644
--- a/src/event.c
+++ b/src/event.c
@@ -57,7 +57,7 @@ static inline const char *ev_window_name(session_t *ps, xcb_window_t wid) {
char *name = "";
if (wid) {
name = "(Failed to get title)";
- if (ps->root == wid) {
+ if (ps->c.screen_info->root == wid) {
name = "(Root window)";
} else if (ps->overlay == wid) {
name = "(Overlay)";
@@ -184,7 +184,7 @@ static inline void ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) {
}
static inline void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) {
- if (ev->parent == ps->root) {
+ if (ev->parent == ps->c.screen_info->root) {
add_win_top(ps, ev->window);
}
}
@@ -239,7 +239,7 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
}
// Recalculate which monitor this window is on
- win_update_monitor(ps->randr_nmonitors, ps->randr_monitor_regs, mw);
+ win_update_monitor(&ps->monitors, mw);
}
// override_redirect flag cannot be changed after window creation, as far
@@ -250,7 +250,7 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) {
log_debug("{ send_event: %d, id: %#010x, above: %#010x, override_redirect: %d }",
ev->event, ev->window, ev->above_sibling, ev->override_redirect);
- if (ev->window == ps->root) {
+ if (ev->window == ps->c.screen_info->root) {
set_root_flags(ps, ROOT_FLAGS_CONFIGURED);
} else {
configure_win(ps, ev);
@@ -284,8 +284,8 @@ static inline void ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) {
// in redirected state.
if (ps->overlay && ev->window == ps->overlay && !ps->redirected) {
log_debug("Overlay is mapped while we are not redirected");
- auto e =
- xcb_request_check(ps->c, xcb_unmap_window_checked(ps->c, ps->overlay));
+ auto e = xcb_request_check(
+ ps->c.c, xcb_unmap_window_checked(ps->c.c, ps->overlay));
if (e) {
log_error("Failed to unmap the overlay window");
free(e);
@@ -323,7 +323,7 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
ps->pending_updates = true;
}
- if (ev->parent == ps->root) {
+ if (ev->parent == ps->c.screen_info->root) {
// X will generate reparent notifiy even if the parent didn't actually
// change (i.e. reparent again to current parent). So we check if that's
// the case
@@ -351,7 +351,7 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
// Reset event mask in case something wrong happens
xcb_change_window_attributes(
- ps->c, ev->window, XCB_CW_EVENT_MASK,
+ ps->c.c, ev->window, XCB_CW_EVENT_MASK,
(const uint32_t[]){determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN)});
if (!wid_has_prop(ps, ev->window, ps->atoms->aWM_STATE)) {
@@ -360,7 +360,7 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
"property change in case it gains one.",
ev->window);
xcb_change_window_attributes(
- ps->c, ev->window, XCB_CW_EVENT_MASK,
+ ps->c.c, ev->window, XCB_CW_EVENT_MASK,
(const uint32_t[]){determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) |
XCB_EVENT_MASK_PROPERTY_CHANGE});
} else {
@@ -373,9 +373,9 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
win_set_flags(w_real_top, WIN_FLAGS_CLIENT_STALE);
ps->pending_updates = true;
} else {
- if (!w_real_top)
+ if (!w_real_top) {
log_debug("parent %#010x not found", ev->parent);
- else {
+ } else {
// Window is not currently mapped, unmark its
// client to trigger a client recheck when it is
// mapped later.
@@ -392,8 +392,9 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
static inline void ev_circulate_notify(session_t *ps, xcb_circulate_notify_event_t *ev) {
auto w = find_win(ps, ev->window);
- if (!w)
+ if (!w) {
return;
+ }
if (ev->place == PlaceOnTop) {
restack_top(ps, w);
@@ -410,7 +411,8 @@ static inline void expose_root(session_t *ps, const rect_t *rects, int nrects) {
}
static inline void ev_expose(session_t *ps, xcb_expose_event_t *ev) {
- if (ev->window == ps->root || (ps->overlay && ev->window == ps->overlay)) {
+ if (ev->window == ps->c.screen_info->root ||
+ (ps->overlay && ev->window == ps->overlay)) {
int more = ev->count + 1;
if (ps->n_expose == ps->size_expose) {
if (ps->expose_rects) {
@@ -439,8 +441,8 @@ static inline void ev_expose(session_t *ps, xcb_expose_event_t *ev) {
static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) {
if (unlikely(log_get_level_tls() <= LOG_LEVEL_TRACE)) {
// Print out changed atom
- xcb_get_atom_name_reply_t *reply =
- xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, ev->atom), NULL);
+ xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
+ ps->c.c, xcb_get_atom_name(ps->c.c, ev->atom), NULL);
const char *name = "?";
int name_len = 1;
if (reply) {
@@ -452,7 +454,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
free(reply);
}
- if (ps->root == ev->window) {
+ if (ps->c.screen_info->root == ev->window) {
if (ps->o.use_ewmh_active_win && ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
// to update focus
ps->pending_updates = true;
@@ -473,7 +475,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// Check whether it could be a client window
if (!find_toplevel(ps, ev->window)) {
// Reset event mask anyway
- xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK,
+ xcb_change_window_attributes(ps->c.c, ev->window, XCB_CW_EVENT_MASK,
(const uint32_t[]){determine_evmask(
ps, ev->window, WIN_EVMODE_UNKNOWN)});
@@ -586,12 +588,16 @@ static inline void repair_win(session_t *ps, struct managed_win *w) {
if (!w->ever_damaged) {
win_extents(w, &parts);
- set_ignore_cookie(
- ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE));
+ if (!ps->o.show_all_xerrors) {
+ set_ignore_cookie(&ps->c, xcb_damage_subtract(ps->c.c, w->damage,
+ XCB_NONE, XCB_NONE));
+ }
} else {
- set_ignore_cookie(
- ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, ps->damaged_region));
- x_fetch_region(ps->c, ps->damaged_region, &parts);
+ if (!ps->o.show_all_xerrors) {
+ set_ignore_cookie(&ps->c, xcb_damage_subtract(ps->c.c, w->damage, XCB_NONE,
+ ps->damaged_region));
+ }
+ x_fetch_region(&ps->c, ps->damaged_region, &parts);
pixman_region32_translate(&parts, w->g.x + w->g.border_width,
w->g.y + w->g.border_width);
}
@@ -667,7 +673,7 @@ ev_selection_clear(session_t *ps, xcb_selection_clear_event_t attr_unused *ev) {
void ev_handle(session_t *ps, xcb_generic_event_t *ev) {
if (XCB_EVENT_RESPONSE_TYPE(ev) != KeymapNotify) {
- discard_pending(ps, ev->full_sequence);
+ x_discard_pending(&ps->c, ev->full_sequence);
}
xcb_window_t wid = ev_window(ps, ev);
@@ -689,9 +695,9 @@ void ev_handle(session_t *ps, xcb_generic_event_t *ev) {
// https://bugs.freedesktop.org/show_bug.cgi?id=35945
// https://lists.freedesktop.org/archives/xcb/2011-November/007337.html
auto response_type = XCB_EVENT_RESPONSE_TYPE(ev);
- auto proc = XESetWireToEvent(ps->dpy, response_type, 0);
+ auto proc = XESetWireToEvent(ps->c.dpy, response_type, 0);
if (proc) {
- XESetWireToEvent(ps->dpy, response_type, proc);
+ XESetWireToEvent(ps->c.dpy, response_type, proc);
XEvent dummy;
// Stop Xlib from complaining about lost sequence numbers.
@@ -701,8 +707,8 @@ void ev_handle(session_t *ps, xcb_generic_event_t *ev) {
//
// We only need the low 16 bits
uint16_t seq = ev->sequence;
- ev->sequence = (uint16_t)(LastKnownRequestProcessed(ps->dpy) & 0xffff);
- proc(ps->dpy, &dummy, (xEvent *)ev);
+ ev->sequence = (uint16_t)(LastKnownRequestProcessed(ps->c.dpy) & 0xffff);
+ proc(ps->c.dpy, &dummy, (xEvent *)ev);
// Restore the sequence number
ev->sequence = seq;
}
@@ -736,7 +742,7 @@ void ev_handle(session_t *ps, xcb_generic_event_t *ev) {
case SelectionClear:
ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev);
break;
- case 0: ev_xcb_error(ps, (xcb_generic_error_t *)ev); break;
+ case 0: x_handle_error(&ps->c, (xcb_generic_error_t *)ev); break;
default:
if (ps->shape_exists && ev->response_type == ps->shape_event) {
ev_shape_notify(ps, (xcb_shape_notify_event_t *)ev);
diff --git a/src/opengl.c b/src/opengl.c
index 5d2d66cb8c..6f4d0471fb 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -39,7 +39,7 @@ static inline XVisualInfo *get_visualinfo_from_visual(session_t *ps, xcb_visuali
XVisualInfo vreq = {.visualid = visual};
int nitems = 0;
- return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
+ return XGetVisualInfo(ps->c.dpy, VisualIDMask, &vreq, &nitems);
}
/**
@@ -56,7 +56,7 @@ bool glx_init(session_t *ps, bool need_render) {
}
// Get XVisualInfo
- pvis = get_visualinfo_from_visual(ps, ps->vis);
+ pvis = get_visualinfo_from_visual(ps, ps->c.screen_info->root_visual);
if (!pvis) {
log_error("Failed to acquire XVisualInfo for current visual.");
goto glx_init_end;
@@ -65,12 +65,13 @@ bool glx_init(session_t *ps, bool need_render) {
// Ensure the visual is double-buffered
if (need_render) {
int value = 0;
- if (Success != glXGetConfig(ps->dpy, pvis, GLX_USE_GL, &value) || !value) {
+ if (Success != glXGetConfig(ps->c.dpy, pvis, GLX_USE_GL, &value) || !value) {
log_error("Root visual is not a GL visual.");
goto glx_init_end;
}
- if (Success != glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value) || !value) {
+ if (Success != glXGetConfig(ps->c.dpy, pvis, GLX_DOUBLEBUFFER, &value) ||
+ !value) {
log_error("Root visual is not a double buffered GL visual.");
goto glx_init_end;
}
@@ -112,7 +113,7 @@ bool glx_init(session_t *ps, bool need_render) {
if (!psglx->context) {
// Get GLX context
#ifndef DEBUG_GLX_DEBUG_CONTEXT
- psglx->context = glXCreateContext(ps->dpy, pvis, None, GL_TRUE);
+ psglx->context = glXCreateContext(ps->c.dpy, pvis, None, GL_TRUE);
#else
{
GLXFBConfig fbconfig = get_fbconfig_from_visualinfo(ps, pvis);
@@ -134,7 +135,7 @@ bool glx_init(session_t *ps, bool need_render) {
static const int attrib_list[] = {
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, None};
psglx->context = p_glXCreateContextAttribsARB(
- ps->dpy, fbconfig, NULL, GL_TRUE, attrib_list);
+ ps->c.dpy, fbconfig, NULL, GL_TRUE, attrib_list);
}
#endif
@@ -144,7 +145,7 @@ bool glx_init(session_t *ps, bool need_render) {
}
// Attach GLX context
- if (!glXMakeCurrent(ps->dpy, get_tgt_window(ps), psglx->context)) {
+ if (!glXMakeCurrent(ps->c.dpy, get_tgt_window(ps), psglx->context)) {
log_error("Failed to attach GLX context.");
goto glx_init_end;
}
@@ -201,7 +202,7 @@ bool glx_init(session_t *ps, bool need_render) {
// Clear screen
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // glXSwapBuffers(ps->dpy, get_tgt_window(ps));
+ // glXSwapBuffers(ps->c.dpy, get_tgt_window(ps));
}
success = true;
@@ -266,8 +267,8 @@ void glx_destroy(session_t *ps) {
// Destroy GLX context
if (ps->psglx->context) {
- glXMakeCurrent(ps->dpy, None, NULL);
- glXDestroyContext(ps->dpy, ps->psglx->context);
+ glXMakeCurrent(ps->c.dpy, None, NULL);
+ glXDestroyContext(ps->c.dpy, ps->psglx->context);
ps->psglx->context = NULL;
}
@@ -732,7 +733,7 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
// Retrieve pixmap parameters, if they aren't provided
if (!width || !height) {
auto r = xcb_get_geometry_reply(
- ps->c, xcb_get_geometry(ps->c, pixmap), NULL);
+ ps->c.c, xcb_get_geometry(ps->c.c, pixmap), NULL);
if (!r) {
log_error("Failed to query info of pixmap %#010x.", pixmap);
return false;
@@ -773,7 +774,7 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
0,
};
- ptex->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->cfg, pixmap, attrs);
+ ptex->glpixmap = glXCreatePixmap(ps->c.dpy, fbcfg->cfg, pixmap, attrs);
ptex->pixmap = pixmap;
ptex->target =
(GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE);
@@ -820,9 +821,9 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
// The specification requires rebinding whenever the content changes...
// We can't follow this, too slow.
if (need_release)
- glXReleaseTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT);
+ glXReleaseTexImageEXT(ps->c.dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT);
- glXBindTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
+ glXBindTexImageEXT(ps->c.dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
// Cleanup
glBindTexture(ptex->target, 0);
@@ -840,13 +841,13 @@ void glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
// Release binding
if (ptex->glpixmap && ptex->texture) {
glBindTexture(ptex->target, ptex->texture);
- glXReleaseTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT);
+ glXReleaseTexImageEXT(ps->c.dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT);
glBindTexture(ptex->target, 0);
}
// Free GLX Pixmap
if (ptex->glpixmap) {
- glXDestroyPixmap(ps->dpy, ptex->glpixmap);
+ glXDestroyPixmap(ps->c.dpy, ptex->glpixmap);
ptex->glpixmap = 0;
}
diff --git a/src/picom.c b/src/picom.c
index 126922e732..1567ab8962 100644
--- a/src/picom.c
+++ b/src/picom.c
@@ -129,7 +129,7 @@ static inline bool dpms_screen_is_off(xcb_dpms_info_reply_t *info) {
void check_dpms_status(EV_P attr_unused, ev_timer *w, int revents attr_unused) {
auto ps = session_ptr(w, dpms_check_timer);
- auto r = xcb_dpms_info_reply(ps->c, xcb_dpms_info(ps->c), NULL);
+ auto r = xcb_dpms_info_reply(ps->c.c, xcb_dpms_info(ps->c.c), NULL);
if (!r) {
log_fatal("Failed to query DPMS status.");
abort();
@@ -149,7 +149,7 @@ void check_dpms_status(EV_P attr_unused, ev_timer *w, int revents attr_unused) {
* XXX move to win.c
*/
static inline struct managed_win *find_win_all(session_t *ps, const xcb_window_t wid) {
- if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay) {
+ if (!wid || PointerRoot == wid || wid == ps->c.screen_info->root || wid == ps->overlay) {
return NULL;
}
@@ -352,8 +352,9 @@ void add_damage(session_t *ps, const region_t *damage) {
*/
static double fade_timeout(session_t *ps) {
auto now = get_time_ms();
- if (ps->o.fade_delta + ps->fade_time < now)
+ if (ps->o.fade_delta + ps->fade_time < now) {
return 0;
+ }
auto diff = ps->o.fade_delta + ps->fade_time - now;
@@ -406,47 +407,6 @@ static bool run_fade(session_t *ps, struct managed_win **_w, long long steps) {
return true;
}
-// === Error handling ===
-
-void discard_pending(session_t *ps, uint32_t sequence) {
- while (ps->pending_reply_head) {
- if (sequence > ps->pending_reply_head->sequence) {
- auto next = ps->pending_reply_head->next;
- free(ps->pending_reply_head);
- ps->pending_reply_head = next;
- if (!ps->pending_reply_head) {
- ps->pending_reply_tail = &ps->pending_reply_head;
- }
- } else {
- break;
- }
- }
-}
-
-static void handle_error(session_t *ps, xcb_generic_error_t *ev) {
- if (ps == NULL) {
- // Do not ignore errors until the session has been initialized
- return;
- }
- discard_pending(ps, ev->full_sequence);
- if (ps->pending_reply_head && ps->pending_reply_head->sequence == ev->full_sequence) {
- if (ps->pending_reply_head->action != PENDING_REPLY_ACTION_IGNORE) {
- x_log_error(LOG_LEVEL_ERROR, ev->full_sequence, ev->major_code,
- ev->minor_code, ev->error_code);
- }
- switch (ps->pending_reply_head->action) {
- case PENDING_REPLY_ACTION_ABORT:
- log_fatal("An unrecoverable X error occurred, aborting...");
- abort();
- case PENDING_REPLY_ACTION_DEBUG_ABORT: assert(false); break;
- case PENDING_REPLY_ACTION_IGNORE: break;
- }
- return;
- }
- x_log_error(LOG_LEVEL_WARN, ev->full_sequence, ev->major_code, ev->minor_code,
- ev->error_code);
-}
-
// === Windows ===
/**
@@ -482,8 +442,8 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
*/
void update_ewmh_active_win(session_t *ps) {
// Search for the window
- xcb_window_t wid =
- wid_get_prop_window(ps->c, ps->root, ps->atoms->a_NET_ACTIVE_WINDOW);
+ xcb_window_t wid = wid_get_prop_window(&ps->c, ps->c.screen_info->root,
+ ps->atoms->a_NET_ACTIVE_WINDOW);
auto w = find_win_all(ps, wid);
// Mark the window focused. No need to unfocus the previous one.
@@ -510,7 +470,7 @@ static void recheck_focus(session_t *ps) {
// opacity on it
xcb_window_t wid = XCB_NONE;
xcb_get_input_focus_reply_t *reply =
- xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL);
+ xcb_get_input_focus_reply(ps->c.c, xcb_get_input_focus(ps->c.c), NULL);
if (reply) {
wid = reply->focus;
@@ -719,7 +679,7 @@ static bool initialize_backend(session_t *ps) {
/// Handle configure event of the root window
static void configure_root(session_t *ps) {
- auto r = XCB_AWAIT(xcb_get_geometry, ps->c, ps->root);
+ auto r = XCB_AWAIT(xcb_get_geometry, ps->c.c, ps->c.screen_info->root);
if (!r) {
log_fatal("Failed to fetch root geometry");
abort();
@@ -795,8 +755,8 @@ static void configure_root(session_t *ps) {
static void handle_root_flags(session_t *ps) {
if ((ps->root_flags & ROOT_FLAGS_SCREEN_CHANGE) != 0) {
- if (ps->o.crop_shadow_to_monitor) {
- x_update_randr_monitors(ps);
+ if (ps->o.crop_shadow_to_monitor && ps->randr_exists) {
+ x_update_monitors(&ps->c, &ps->monitors);
}
ps->root_flags &= ~(uint64_t)ROOT_FLAGS_SCREEN_CHANGE;
}
@@ -1096,10 +1056,11 @@ void root_damaged(session_t *ps) {
ps->backend_data->ops->release_image(ps->backend_data, ps->root_image);
ps->root_image = NULL;
}
- auto pixmap = x_get_root_back_pixmap(ps->c, ps->root, ps->atoms);
+ auto pixmap = x_get_root_back_pixmap(&ps->c, ps->atoms);
if (pixmap != XCB_NONE) {
ps->root_image = ps->backend_data->ops->bind_pixmap(
- ps->backend_data, pixmap, x_get_visual_info(ps->c, ps->vis), false);
+ ps->backend_data, pixmap,
+ x_get_visual_info(&ps->c, ps->c.screen_info->root_visual), false);
if (ps->root_image) {
ps->backend_data->ops->set_image_property(
ps->backend_data, IMAGE_PROPERTY_EFFECTIVE_SIZE,
@@ -1114,27 +1075,6 @@ void root_damaged(session_t *ps) {
force_repaint(ps);
}
-/**
- * Xlib error handler function.
- */
-static int xerror(Display attr_unused *dpy, XErrorEvent *ev) {
- // Fake a xcb error, fill in just enough information
- xcb_generic_error_t xcb_err;
- xcb_err.full_sequence = (uint32_t)ev->serial;
- xcb_err.major_code = ev->request_code;
- xcb_err.minor_code = ev->minor_code;
- xcb_err.error_code = ev->error_code;
- handle_error(ps_g, &xcb_err);
- return 0;
-}
-
-/**
- * XCB error handler function.
- */
-void ev_xcb_error(session_t *ps, xcb_generic_error_t *err) {
- handle_error(ps, err);
-}
-
/**
* Force a full-screen repaint.
*/
@@ -1169,10 +1109,11 @@ void opts_set_no_fading_openclose(session_t *ps, bool newval) {
static int register_cm(session_t *ps) {
assert(!ps->reg_win);
- ps->reg_win = x_new_id(ps->c);
+ ps->reg_win = x_new_id(&ps->c);
auto e = xcb_request_check(
- ps->c, xcb_create_window_checked(ps->c, XCB_COPY_FROM_PARENT, ps->reg_win, ps->root,
- 0, 0, 1, 1, 0, XCB_NONE, ps->vis, 0, NULL));
+ ps->c.c, xcb_create_window_checked(ps->c.c, XCB_COPY_FROM_PARENT, ps->reg_win,
+ ps->c.screen_info->root, 0, 0, 1, 1, 0, XCB_NONE,
+ ps->c.screen_info->root_visual, 0, NULL));
if (e) {
log_fatal("Failed to create window.");
@@ -1191,10 +1132,10 @@ static int register_cm(session_t *ps) {
// Set names and classes
for (size_t i = 0; i < ARR_SIZE(prop_atoms); i++) {
e = xcb_request_check(
- ps->c, xcb_change_property_checked(
- ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, prop_atoms[i],
- prop_is_utf8[i] ? ps->atoms->aUTF8_STRING : XCB_ATOM_STRING,
- 8, strlen("picom"), "picom"));
+ ps->c.c, xcb_change_property_checked(
+ ps->c.c, XCB_PROP_MODE_REPLACE, ps->reg_win, prop_atoms[i],
+ prop_is_utf8[i] ? ps->atoms->aUTF8_STRING : XCB_ATOM_STRING,
+ 8, strlen("picom"), "picom"));
if (e) {
log_error_x_error(e, "Failed to set window property %d",
prop_atoms[i]);
@@ -1204,9 +1145,9 @@ static int register_cm(session_t *ps) {
const char picom_class[] = "picom\0picom";
e = xcb_request_check(
- ps->c, xcb_change_property_checked(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
- ps->atoms->aWM_CLASS, XCB_ATOM_STRING, 8,
- ARR_SIZE(picom_class), picom_class));
+ ps->c.c, xcb_change_property_checked(ps->c.c, XCB_PROP_MODE_REPLACE, ps->reg_win,
+ ps->atoms->aWM_CLASS, XCB_ATOM_STRING, 8,
+ ARR_SIZE(picom_class), picom_class));
if (e) {
log_error_x_error(e, "Failed to set the WM_CLASS property");
free(e);
@@ -1220,10 +1161,10 @@ static int register_cm(session_t *ps) {
if (gethostname(hostname, hostname_max) == 0) {
e = xcb_request_check(
- ps->c, xcb_change_property_checked(
- ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
- ps->atoms->aWM_CLIENT_MACHINE, XCB_ATOM_STRING, 8,
- (uint32_t)strlen(hostname), hostname));
+ ps->c.c, xcb_change_property_checked(
+ ps->c.c, XCB_PROP_MODE_REPLACE, ps->reg_win,
+ ps->atoms->aWM_CLIENT_MACHINE, XCB_ATOM_STRING,
+ 8, (uint32_t)strlen(hostname), hostname));
if (e) {
log_error_x_error(e, "Failed to set the WM_CLIENT_MACHINE"
" property");
@@ -1239,16 +1180,16 @@ static int register_cm(session_t *ps) {
// Set _NET_WM_PID
{
auto pid = getpid();
- xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
+ xcb_change_property(ps->c.c, XCB_PROP_MODE_REPLACE, ps->reg_win,
ps->atoms->a_NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &pid);
}
// Set COMPTON_VERSION
e = xcb_request_check(
- ps->c, xcb_change_property_checked(
- ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
- get_atom(ps->atoms, "COMPTON_VERSION"), XCB_ATOM_STRING, 8,
- (uint32_t)strlen(PICOM_VERSION), PICOM_VERSION));
+ ps->c.c, xcb_change_property_checked(
+ ps->c.c, XCB_PROP_MODE_REPLACE, ps->reg_win,
+ get_atom(ps->atoms, "COMPTON_VERSION"), XCB_ATOM_STRING, 8,
+ (uint32_t)strlen(PICOM_VERSION), PICOM_VERSION));
if (e) {
log_error_x_error(e, "Failed to set COMPTON_VERSION.");
free(e);
@@ -1260,7 +1201,7 @@ static int register_cm(session_t *ps) {
xcb_atom_t atom;
char *buf = NULL;
- if (asprintf(&buf, "%s%d", register_prop, ps->scr) < 0) {
+ if (asprintf(&buf, "%s%d", register_prop, ps->c.screen) < 0) {
log_fatal("Failed to allocate memory");
return -1;
}
@@ -1268,7 +1209,7 @@ static int register_cm(session_t *ps) {
free(buf);
xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(
- ps->c, xcb_get_selection_owner(ps->c, atom), NULL);
+ ps->c.c, xcb_get_selection_owner(ps->c.c, atom), NULL);
if (reply && reply->owner != XCB_NONE) {
// Another compositor already running
@@ -1276,7 +1217,7 @@ static int register_cm(session_t *ps) {
return 1;
}
free(reply);
- xcb_set_selection_owner(ps->c, ps->reg_win, atom, 0);
+ xcb_set_selection_owner(ps->c.c, ps->reg_win, atom, 0);
}
return 0;
@@ -1306,9 +1247,8 @@ static inline bool write_pid(session_t *ps) {
* Initialize X composite overlay window.
*/
static bool init_overlay(session_t *ps) {
- xcb_composite_get_overlay_window_reply_t *reply =
- xcb_composite_get_overlay_window_reply(
- ps->c, xcb_composite_get_overlay_window(ps->c, ps->root), NULL);
+ xcb_composite_get_overlay_window_reply_t *reply = xcb_composite_get_overlay_window_reply(
+ ps->c.c, xcb_composite_get_overlay_window(ps->c.c, ps->c.screen_info->root), NULL);
if (reply) {
ps->overlay = reply->overlay_win;
free(reply);
@@ -1318,13 +1258,13 @@ static bool init_overlay(session_t *ps) {
if (ps->overlay != XCB_NONE) {
// Set window region of the overlay window, code stolen from
// compiz-0.8.8
- if (!XCB_AWAIT_VOID(xcb_shape_mask, ps->c, XCB_SHAPE_SO_SET,
+ if (!XCB_AWAIT_VOID(xcb_shape_mask, ps->c.c, XCB_SHAPE_SO_SET,
XCB_SHAPE_SK_BOUNDING, ps->overlay, 0, 0, 0)) {
log_fatal("Failed to set the bounding shape of overlay, giving "
"up.");
return false;
}
- if (!XCB_AWAIT_VOID(xcb_shape_rectangles, ps->c, XCB_SHAPE_SO_SET,
+ if (!XCB_AWAIT_VOID(xcb_shape_rectangles, ps->c.c, XCB_SHAPE_SO_SET,
XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED,
ps->overlay, 0, 0, 0, NULL)) {
log_fatal("Failed to set the input shape of overlay, giving up.");
@@ -1332,7 +1272,7 @@ static bool init_overlay(session_t *ps) {
}
// Listen to Expose events on the overlay
- xcb_change_window_attributes(ps->c, ps->overlay, XCB_CW_EVENT_MASK,
+ xcb_change_window_attributes(ps->c.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
@@ -1340,7 +1280,7 @@ static bool init_overlay(session_t *ps) {
// root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty);
// Unmap the overlay, we will map it when needed in redirect_start
- XCB_AWAIT_VOID(xcb_unmap_window, ps->c, ps->overlay);
+ XCB_AWAIT_VOID(xcb_unmap_window, ps->c.c, ps->overlay);
} else {
log_error("Cannot get X Composite overlay window. Falling "
"back to painting on root window.");
@@ -1351,27 +1291,29 @@ static bool init_overlay(session_t *ps) {
}
static bool init_debug_window(session_t *ps) {
- xcb_colormap_t colormap = x_new_id(ps->c);
- ps->debug_window = x_new_id(ps->c);
+ xcb_colormap_t colormap = x_new_id(&ps->c);
+ ps->debug_window = x_new_id(&ps->c);
auto err = xcb_request_check(
- ps->c, xcb_create_colormap_checked(ps->c, XCB_COLORMAP_ALLOC_NONE, colormap,
- ps->root, ps->vis));
+ ps->c.c, xcb_create_colormap_checked(ps->c.c, XCB_COLORMAP_ALLOC_NONE,
+ colormap, ps->c.screen_info->root,
+ ps->c.screen_info->root_visual));
if (err) {
goto err_out;
}
err = xcb_request_check(
- ps->c, xcb_create_window_checked(ps->c, (uint8_t)ps->depth, ps->debug_window,
- ps->root, 0, 0, to_u16_checked(ps->root_width),
- to_u16_checked(ps->root_height), 0,
- XCB_WINDOW_CLASS_INPUT_OUTPUT, ps->vis,
- XCB_CW_COLORMAP, (uint32_t[]){colormap, 0}));
+ ps->c.c, xcb_create_window_checked(
+ ps->c.c, (uint8_t)ps->c.screen_info->root_depth,
+ ps->debug_window, ps->c.screen_info->root, 0, 0,
+ to_u16_checked(ps->root_width), to_u16_checked(ps->root_height),
+ 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, ps->c.screen_info->root_visual,
+ XCB_CW_COLORMAP, (uint32_t[]){colormap, 0}));
if (err) {
goto err_out;
}
- err = xcb_request_check(ps->c, xcb_map_window_checked(ps->c, ps->debug_window));
+ err = xcb_request_check(ps->c.c, xcb_map_window_checked(ps->c.c, ps->debug_window));
if (err) {
goto err_out;
}
@@ -1386,7 +1328,7 @@ xcb_window_t session_get_target_window(session_t *ps) {
if (ps->o.debug_mode) {
return ps->debug_window;
}
- return ps->overlay != XCB_NONE ? ps->overlay : ps->root;
+ return ps->overlay != XCB_NONE ? ps->overlay : ps->c.screen_info->root;
}
uint8_t session_redirection_mode(session_t *ps) {
@@ -1416,18 +1358,18 @@ static bool redirect_start(session_t *ps) {
// Map overlay window. Done firstly according to this:
// https://bugzilla.gnome.org/show_bug.cgi?id=597014
if (ps->overlay != XCB_NONE) {
- xcb_map_window(ps->c, ps->overlay);
+ xcb_map_window(ps->c.c, ps->overlay);
}
- bool success = XCB_AWAIT_VOID(xcb_composite_redirect_subwindows, ps->c, ps->root,
- session_redirection_mode(ps));
+ bool success = XCB_AWAIT_VOID(xcb_composite_redirect_subwindows, ps->c.c,
+ ps->c.screen_info->root, session_redirection_mode(ps));
if (!success) {
log_fatal("Another composite manager is already running "
"(and does not handle _NET_WM_CM_Sn correctly)");
return false;
}
- x_sync(ps->c);
+ x_sync(&ps->c);
if (!initialize_backend(ps)) {
return false;
@@ -1456,16 +1398,16 @@ static bool redirect_start(session_t *ps) {
}
if (ps->present_exists && ps->frame_pacing) {
- ps->present_event_id = x_new_id(ps->c);
+ ps->present_event_id = x_new_id(&ps->c);
auto select_input = xcb_present_select_input(
- ps->c, ps->present_event_id, session_get_target_window(ps),
+ ps->c.c, ps->present_event_id, session_get_target_window(ps),
XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY);
- auto notify_msc =
- xcb_present_notify_msc(ps->c, session_get_target_window(ps), 0, 0, 1, 0);
- set_cant_fail_cookie(ps, select_input);
- set_cant_fail_cookie(ps, notify_msc);
+ auto notify_msc = xcb_present_notify_msc(
+ ps->c.c, session_get_target_window(ps), 0, 0, 1, 0);
+ set_cant_fail_cookie(&ps->c, select_input);
+ set_cant_fail_cookie(&ps->c, notify_msc);
ps->present_event = xcb_register_for_special_xge(
- ps->c, &xcb_present_id, ps->present_event_id, NULL);
+ ps->c.c, &xcb_present_id, ps->present_event_id, NULL);
// Initialize rendering and frame timing statistics, and frame pacing
// states.
@@ -1480,13 +1422,13 @@ static bool redirect_start(session_t *ps) {
}
// Must call XSync() here
- x_sync(ps->c);
+ x_sync(&ps->c);
ps->redirected = true;
ps->first_frame = true;
// Re-detect driver since we now have a backend
- ps->drivers = detect_driver(ps->c, ps->backend_data, ps->root);
+ ps->drivers = detect_driver(ps->c.c, ps->backend_data, ps->c.screen_info->root);
apply_driver_workarounds(ps, ps->drivers);
root_damaged(ps);
@@ -1506,10 +1448,11 @@ static void unredirect(session_t *ps) {
destroy_backend(ps);
- xcb_composite_unredirect_subwindows(ps->c, ps->root, session_redirection_mode(ps));
+ xcb_composite_unredirect_subwindows(ps->c.c, ps->c.screen_info->root,
+ session_redirection_mode(ps));
// Unmap overlay window
if (ps->overlay != XCB_NONE) {
- xcb_unmap_window(ps->c, ps->overlay);
+ xcb_unmap_window(ps->c.c, ps->overlay);
}
// Free the damage ring
@@ -1521,15 +1464,15 @@ static void unredirect(session_t *ps) {
ps->damage_ring = ps->damage = NULL;
if (ps->present_event_id) {
- xcb_present_select_input(ps->c, ps->present_event_id,
+ xcb_present_select_input(ps->c.c, ps->present_event_id,
session_get_target_window(ps), 0);
ps->present_event_id = XCB_NONE;
- xcb_unregister_for_special_event(ps->c, ps->present_event);
+ xcb_unregister_for_special_event(ps->c.c, ps->present_event);
ps->present_event = NULL;
}
// Must call XSync() here
- x_sync(ps->c);
+ x_sync(&ps->c);
ps->redirected = false;
log_debug("Screen unredirected.");
@@ -1553,9 +1496,9 @@ handle_present_complete_notify(session_t *ps, xcb_present_complete_notify_event_
next_msc = ps->last_msc + 1;
event_is_invalid = true;
}
- auto cookie = xcb_present_notify_msc(ps->c, session_get_target_window(ps),
- 0, next_msc, 0, 0);
- set_cant_fail_cookie(ps, cookie);
+ auto cookie = xcb_present_notify_msc(
+ ps->c.c, session_get_target_window(ps), 0, next_msc, 0, 0);
+ set_cant_fail_cookie(&ps->c, cookie);
}
if (event_is_invalid) {
return;
@@ -1602,7 +1545,7 @@ static void handle_present_events(session_t *ps) {
return;
}
xcb_present_generic_event_t *ev;
- while ((ev = (void *)xcb_poll_for_special_event(ps->c, ps->present_event))) {
+ while ((ev = (void *)xcb_poll_for_special_event(ps->c.c, ps->present_event))) {
if (ev->event != ps->present_event_id) {
// This event doesn't have the right event context, it's not meant
// for us.
@@ -1623,7 +1566,7 @@ static void handle_queued_x_events(EV_P attr_unused, ev_prepare *w, int revents
handle_present_events(ps);
xcb_generic_event_t *ev;
- while ((ev = xcb_poll_for_queued_event(ps->c))) {
+ while ((ev = xcb_poll_for_queued_event(ps->c.c))) {
ev_handle(ps, ev);
free(ev);
};
@@ -1632,9 +1575,9 @@ static void handle_queued_x_events(EV_P attr_unused, ev_prepare *w, int revents
// for an indefinite amount of time.
// Use XFlush here too, we might still use some Xlib functions
// because OpenGL.
- XFlush(ps->dpy);
- xcb_flush(ps->c);
- int err = xcb_connection_has_error(ps->c);
+ XFlush(ps->c.dpy);
+ xcb_flush(ps->c.c);
+ int err = xcb_connection_has_error(ps->c.c);
if (err) {
log_fatal("X11 server connection broke (error %d)", err);
exit(1);
@@ -1692,7 +1635,7 @@ static void fade_timer_callback(EV_P attr_unused, ev_timer *w, int revents attr_
static void handle_pending_updates(EV_P_ struct session *ps) {
if (ps->pending_updates) {
log_debug("Delayed handling of events, entering critical section");
- auto e = xcb_request_check(ps->c, xcb_grab_server_checked(ps->c));
+ auto e = xcb_request_check(ps->c.c, xcb_grab_server_checked(ps->c.c));
if (e) {
log_fatal_x_error(e, "failed to grab x server");
free(e);
@@ -1718,7 +1661,7 @@ static void handle_pending_updates(EV_P_ struct session *ps) {
{
auto r = xcb_get_input_focus_reply(
- ps->c, xcb_get_input_focus(ps->c), NULL);
+ ps->c.c, xcb_get_input_focus(ps->c.c), NULL);
if (!ps->active_win || (r && r->focus != ps->active_win->base.id)) {
recheck_focus(ps);
}
@@ -1728,7 +1671,7 @@ static void handle_pending_updates(EV_P_ struct session *ps) {
// Process window flags (stale images)
refresh_images(ps);
- e = xcb_request_check(ps->c, xcb_ungrab_server_checked(ps->c));
+ e = xcb_request_check(ps->c.c, xcb_ungrab_server_checked(ps->c.c));
if (e) {
log_fatal_x_error(e, "failed to ungrab x server");
free(e);
@@ -1868,7 +1811,7 @@ static void draw_callback(EV_P_ ev_timer *w, int revents) {
static void x_event_callback(EV_P attr_unused, ev_io *w, int revents attr_unused) {
session_t *ps = (session_t *)w;
- xcb_generic_event_t *ev = xcb_poll_for_event(ps->c);
+ xcb_generic_event_t *ev = xcb_poll_for_event(ps->c.c);
if (ev) {
ev_handle(ps, ev);
free(ev);
@@ -1966,12 +1909,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
const char *config_file, bool all_xerrors, bool fork) {
static const session_t s_def = {
.backend_data = NULL,
- .dpy = NULL,
- .scr = 0,
- .c = NULL,
- .vis = 0,
- .depth = 0,
- .root = XCB_NONE,
.root_height = 0,
.root_width = 0,
// .root_damage = XCB_NONE,
@@ -1987,8 +1924,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
.redirected = false,
.alpha_picts = NULL,
.fade_time = 0L,
- .pending_reply_head = NULL,
- .pending_reply_tail = NULL,
.quit = false,
.expose_rects = NULL,
@@ -2056,52 +1991,42 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
// TODO(yshui) investigate what's the best window size
render_statistics_init(&ps->render_stats, 128);
- ps->pending_reply_tail = &ps->pending_reply_head;
-
ps->o.show_all_xerrors = all_xerrors;
// Use the same Display across reset, primarily for resource leak checking
- ps->dpy = dpy;
- ps->c = XGetXCBConnection(ps->dpy);
+ x_connection_init(&ps->c, dpy);
+ // We store width/height from screen_info instead using them directly because they
+ // can change, see configure_root().
+ ps->root_width = ps->c.screen_info->width_in_pixels;
+ ps->root_height = ps->c.screen_info->height_in_pixels;
const xcb_query_extension_reply_t *ext_info;
- ps->previous_xerror_handler = XSetErrorHandler(xerror);
-
- ps->scr = DefaultScreen(ps->dpy);
-
- auto screen = x_screen_of_display(ps->c, ps->scr);
- ps->vis = screen->root_visual;
- ps->depth = screen->root_depth;
- ps->root = screen->root;
- ps->root_width = screen->width_in_pixels;
- ps->root_height = screen->height_in_pixels;
-
// Start listening to events on root earlier to catch all possible
// root geometry changes
auto e = xcb_request_check(
- ps->c, xcb_change_window_attributes_checked(
- ps->c, ps->root, XCB_CW_EVENT_MASK,
- (const uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
- XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
- XCB_EVENT_MASK_PROPERTY_CHANGE}));
+ ps->c.c, xcb_change_window_attributes_checked(
+ ps->c.c, ps->c.screen_info->root, XCB_CW_EVENT_MASK,
+ (const uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
+ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+ XCB_EVENT_MASK_PROPERTY_CHANGE}));
if (e) {
log_error_x_error(e, "Failed to setup root window event mask");
free(e);
}
- xcb_prefetch_extension_data(ps->c, &xcb_render_id);
- xcb_prefetch_extension_data(ps->c, &xcb_composite_id);
- xcb_prefetch_extension_data(ps->c, &xcb_damage_id);
- xcb_prefetch_extension_data(ps->c, &xcb_shape_id);
- xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id);
- xcb_prefetch_extension_data(ps->c, &xcb_randr_id);
- xcb_prefetch_extension_data(ps->c, &xcb_present_id);
- xcb_prefetch_extension_data(ps->c, &xcb_sync_id);
- xcb_prefetch_extension_data(ps->c, &xcb_glx_id);
- xcb_prefetch_extension_data(ps->c, &xcb_dpms_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_render_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_composite_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_damage_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_shape_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_xfixes_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_randr_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_present_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_sync_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_glx_id);
+ xcb_prefetch_extension_data(ps->c.c, &xcb_dpms_id);
- ext_info = xcb_get_extension_data(ps->c, &xcb_render_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_render_id);
if (!ext_info || !ext_info->present) {
log_fatal("No render extension");
exit(1);
@@ -2109,7 +2034,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
ps->render_event = ext_info->first_event;
ps->render_error = ext_info->first_error;
- ext_info = xcb_get_extension_data(ps->c, &xcb_composite_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_composite_id);
if (!ext_info || !ext_info->present) {
log_fatal("No composite extension");
exit(1);
@@ -2120,8 +2045,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
{
xcb_composite_query_version_reply_t *reply = xcb_composite_query_version_reply(
- ps->c,
- xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION,
+ ps->c.c,
+ xcb_composite_query_version(ps->c.c, XCB_COMPOSITE_MAJOR_VERSION,
XCB_COMPOSITE_MINOR_VERSION),
NULL);
@@ -2133,45 +2058,45 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
free(reply);
}
- ext_info = xcb_get_extension_data(ps->c, &xcb_damage_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_damage_id);
if (!ext_info || !ext_info->present) {
log_fatal("No damage extension");
exit(1);
}
ps->damage_event = ext_info->first_event;
ps->damage_error = ext_info->first_error;
- xcb_discard_reply(ps->c, xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION,
- XCB_DAMAGE_MINOR_VERSION)
- .sequence);
+ xcb_discard_reply(ps->c.c, xcb_damage_query_version(ps->c.c, XCB_DAMAGE_MAJOR_VERSION,
+ XCB_DAMAGE_MINOR_VERSION)
+ .sequence);
- ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_xfixes_id);
if (!ext_info || !ext_info->present) {
log_fatal("No XFixes extension");
exit(1);
}
ps->xfixes_event = ext_info->first_event;
ps->xfixes_error = ext_info->first_error;
- xcb_discard_reply(ps->c, xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION,
- XCB_XFIXES_MINOR_VERSION)
- .sequence);
+ xcb_discard_reply(ps->c.c, xcb_xfixes_query_version(ps->c.c, XCB_XFIXES_MAJOR_VERSION,
+ XCB_XFIXES_MINOR_VERSION)
+ .sequence);
- ps->damaged_region = x_new_id(ps->c);
- if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c, ps->damaged_region, 0, NULL)) {
+ ps->damaged_region = x_new_id(&ps->c);
+ if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c.c, ps->damaged_region, 0, NULL)) {
log_fatal("Failed to create a XFixes region");
goto err;
}
- ext_info = xcb_get_extension_data(ps->c, &xcb_glx_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_glx_id);
if (ext_info && ext_info->present) {
ps->glx_exists = true;
ps->glx_error = ext_info->first_error;
ps->glx_event = ext_info->first_event;
}
- ext_info = xcb_get_extension_data(ps->c, &xcb_dpms_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_dpms_id);
ps->dpms_exists = ext_info && ext_info->present;
if (ps->dpms_exists) {
- auto r = xcb_dpms_info_reply(ps->c, xcb_dpms_info(ps->c), NULL);
+ auto r = xcb_dpms_info_reply(ps->c.c, xcb_dpms_info(ps->c.c), NULL);
if (!r) {
log_fatal("Failed to query DPMS info");
goto err;
@@ -2226,7 +2151,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
"binary will not be installed in the future.");
}
- ps->atoms = init_atoms(ps->c);
+ ps->atoms = init_atoms(ps->c.c);
ps->atoms_wintypes[WINTYPE_UNKNOWN] = 0;
#define SET_WM_TYPE_ATOM(x) \
ps->atoms_wintypes[WINTYPE_##x] = ps->atoms->a_NET_WM_WINDOW_TYPE_##x
@@ -2287,25 +2212,25 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
rebuild_shadow_exclude_reg(ps);
// Query X Shape
- ext_info = xcb_get_extension_data(ps->c, &xcb_shape_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_shape_id);
if (ext_info && ext_info->present) {
ps->shape_event = ext_info->first_event;
ps->shape_error = ext_info->first_error;
ps->shape_exists = true;
}
- ext_info = xcb_get_extension_data(ps->c, &xcb_randr_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_randr_id);
if (ext_info && ext_info->present) {
ps->randr_exists = true;
ps->randr_event = ext_info->first_event;
ps->randr_error = ext_info->first_error;
}
- ext_info = xcb_get_extension_data(ps->c, &xcb_present_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_present_id);
if (ext_info && ext_info->present) {
auto r = xcb_present_query_version_reply(
- ps->c,
- xcb_present_query_version(ps->c, XCB_PRESENT_MAJOR_VERSION,
+ ps->c.c,
+ xcb_present_query_version(ps->c.c, XCB_PRESENT_MAJOR_VERSION,
XCB_PRESENT_MINOR_VERSION),
NULL);
if (r) {
@@ -2315,14 +2240,14 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
}
// Query X Sync
- ext_info = xcb_get_extension_data(ps->c, &xcb_sync_id);
+ ext_info = xcb_get_extension_data(ps->c.c, &xcb_sync_id);
if (ext_info && ext_info->present) {
ps->xsync_error = ext_info->first_error;
ps->xsync_event = ext_info->first_event;
// Need X Sync 3.1 for fences
auto r = xcb_sync_initialize_reply(
- ps->c,
- xcb_sync_initialize(ps->c, XCB_SYNC_MAJOR_VERSION, XCB_SYNC_MINOR_VERSION),
+ ps->c.c,
+ xcb_sync_initialize(ps->c.c, XCB_SYNC_MAJOR_VERSION, XCB_SYNC_MINOR_VERSION),
NULL);
if (r && (r->major_version > 3 ||
(r->major_version == 3 && r->minor_version >= 1))) {
@@ -2333,9 +2258,10 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
ps->sync_fence = XCB_NONE;
if (ps->xsync_exists) {
- ps->sync_fence = x_new_id(ps->c);
- e = xcb_request_check(ps->c, xcb_sync_create_fence_checked(
- ps->c, ps->root, ps->sync_fence, 0));
+ ps->sync_fence = x_new_id(&ps->c);
+ e = xcb_request_check(
+ ps->c.c, xcb_sync_create_fence_checked(
+ ps->c.c, ps->c.screen_info->root, ps->sync_fence, 0));
if (e) {
if (ps->o.xrender_sync_fence) {
log_error_x_error(e, "Failed to create a XSync fence. "
@@ -2412,7 +2338,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
}
}
- ps->drivers = detect_driver(ps->c, ps->backend_data, ps->root);
+ ps->drivers = detect_driver(ps->c.c, ps->backend_data, ps->c.screen_info->root);
apply_driver_workarounds(ps, ps->drivers);
// Initialize filters, must be preceded by OpenGL context creation
@@ -2453,26 +2379,29 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
// Monitor screen changes if vsync_sw is enabled and we are using
// an auto-detected refresh rate, or when X RandR features are enabled
if (ps->randr_exists && ps->o.crop_shadow_to_monitor) {
- xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
+ xcb_randr_select_input(ps->c.c, ps->c.screen_info->root,
+ XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
+ x_update_monitors(&ps->c, &ps->monitors);
}
- x_update_randr_monitors(ps);
-
{
xcb_render_create_picture_value_list_t pa = {
.subwindowmode = IncludeInferiors,
};
ps->root_picture = x_create_picture_with_visual_and_pixmap(
- ps->c, ps->vis, ps->root, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
+ &ps->c, ps->c.screen_info->root_visual, ps->c.screen_info->root,
+ XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
if (ps->overlay != XCB_NONE) {
ps->tgt_picture = x_create_picture_with_visual_and_pixmap(
- ps->c, ps->vis, ps->overlay, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
- } else
+ &ps->c, ps->c.screen_info->root_visual, ps->overlay,
+ XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
+ } else {
ps->tgt_picture = ps->root_picture;
+ }
}
- ev_io_init(&ps->xiow, x_event_callback, ConnectionNumber(ps->dpy), EV_READ);
+ ev_io_init(&ps->xiow, x_event_callback, ConnectionNumber(ps->c.dpy), EV_READ);
ev_io_start(ps->loop, &ps->xiow);
ev_init(&ps->unredir_timer, tmout_unredir_callback);
ev_init(&ps->draw_timer, draw_callback);
@@ -2509,7 +2438,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
// functions
if (ps->o.dbus) {
#ifdef CONFIG_DBUS
- cdbus_init(ps, DisplayString(ps->dpy));
+ cdbus_init(ps, DisplayString(ps->c.dpy));
if (!ps->dbus_data) {
ps->o.dbus = false;
}
@@ -2519,7 +2448,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
#endif
}
- e = xcb_request_check(ps->c, xcb_grab_server_checked(ps->c));
+ e = xcb_request_check(ps->c.c, xcb_grab_server_checked(ps->c.c));
if (e) {
log_fatal_x_error(e, "Failed to grab X server");
free(e);
@@ -2532,12 +2461,12 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
// earlier is irrelavant at this point.
// A better solution is probably grabbing the server from the very start. But I
// think there still could be race condition that mandates discarding the events.
- x_discard_events(ps->c);
+ x_discard_events(&ps->c);
- xcb_query_tree_reply_t *query_tree_reply =
- xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, ps->root), NULL);
+ xcb_query_tree_reply_t *query_tree_reply = xcb_query_tree_reply(
+ ps->c.c, xcb_query_tree(ps->c.c, ps->c.screen_info->root), NULL);
- e = xcb_request_check(ps->c, xcb_ungrab_server_checked(ps->c));
+ e = xcb_request_check(ps->c.c, xcb_ungrab_server_checked(ps->c.c));
if (e) {
log_fatal_x_error(e, "Failed to ungrab server");
free(e);
@@ -2630,7 +2559,7 @@ static void session_destroy(session_t *ps) {
ps->file_watch_handle = NULL;
// Stop listening to events on root window
- xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK,
+ xcb_change_window_attributes(ps->c.c, ps->c.screen_info->root, XCB_CW_EVENT_MASK,
(const uint32_t[]){0});
#ifdef CONFIG_DBUS
@@ -2681,32 +2610,17 @@ static void session_destroy(session_t *ps) {
ps->track_atom_lst = NULL;
}
- // Free ignore linked list
- {
- pending_reply_t *next = NULL;
- for (auto ign = ps->pending_reply_head; ign; ign = next) {
- next = ign->next;
-
- free(ign);
- }
-
- // Reset head and tail
- ps->pending_reply_head = NULL;
- ps->pending_reply_tail = &ps->pending_reply_head;
- }
-
// Free tgt_{buffer,picture} and root_picture
if (ps->tgt_buffer.pict == ps->tgt_picture) {
ps->tgt_buffer.pict = XCB_NONE;
}
- if (ps->tgt_picture == ps->root_picture) {
- ps->tgt_picture = XCB_NONE;
- } else {
- free_picture(ps->c, &ps->tgt_picture);
+ if (ps->tgt_picture != ps->root_picture) {
+ x_free_picture(&ps->c, ps->tgt_picture);
}
+ x_free_picture(&ps->c, ps->root_picture);
+ ps->tgt_picture = ps->root_picture = XCB_NONE;
- free_picture(ps->c, &ps->root_picture);
free_paint(ps, &ps->tgt_buffer);
pixman_region32_fini(&ps->screen_reg);
@@ -2719,7 +2633,7 @@ static void session_destroy(session_t *ps) {
}
free(ps->o.blur_kerns);
free(ps->o.glx_fshader_win_str);
- x_free_randr_info(ps);
+ x_free_monitor_info(&ps->monitors);
render_statistics_destroy(&ps->render_stats);
@@ -2744,28 +2658,28 @@ static void session_destroy(session_t *ps) {
// Release overlay window
if (ps->overlay) {
- xcb_composite_release_overlay_window(ps->c, ps->overlay);
+ xcb_composite_release_overlay_window(ps->c.c, ps->overlay);
ps->overlay = XCB_NONE;
}
if (ps->sync_fence != XCB_NONE) {
- xcb_sync_destroy_fence(ps->c, ps->sync_fence);
+ xcb_sync_destroy_fence(ps->c.c, ps->sync_fence);
ps->sync_fence = XCB_NONE;
}
// Free reg_win
if (ps->reg_win != XCB_NONE) {
- xcb_destroy_window(ps->c, ps->reg_win);
+ xcb_destroy_window(ps->c.c, ps->reg_win);
ps->reg_win = XCB_NONE;
}
if (ps->debug_window != XCB_NONE) {
- xcb_destroy_window(ps->c, ps->debug_window);
+ xcb_destroy_window(ps->c.c, ps->debug_window);
ps->debug_window = XCB_NONE;
}
if (ps->damaged_region != XCB_NONE) {
- xcb_xfixes_destroy_region(ps->c, ps->damaged_region);
+ xcb_xfixes_destroy_region(ps->c.c, ps->damaged_region);
ps->damaged_region = XCB_NONE;
}
@@ -2784,7 +2698,7 @@ static void session_destroy(session_t *ps) {
#endif
// Flush all events
- x_sync(ps->c);
+ x_sync(&ps->c);
ev_io_stop(ps->loop, &ps->xiow);
if (ps->o.legacy_backends) {
free_conv((conv *)ps->shadow_context);
@@ -2796,8 +2710,6 @@ static void session_destroy(session_t *ps) {
xrc_report_xid();
#endif
- XSetErrorHandler(ps->previous_xerror_handler);
-
// Stop libev event handlers
ev_timer_stop(ps->loop, &ps->unredir_timer);
ev_timer_stop(ps->loop, &ps->fade_timer);
@@ -2806,6 +2718,8 @@ static void session_destroy(session_t *ps) {
ev_prepare_stop(ps->loop, &ps->event_check);
ev_signal_stop(ps->loop, &ps->usr1_signal);
ev_signal_stop(ps->loop, &ps->int_signal);
+
+ free_x_connection(&ps->c);
}
/**
@@ -2872,10 +2786,9 @@ int main(int argc, char **argv) {
// Failed to read, the child has most likely died
// We can probably waitpid() here.
return 1;
- } else {
- // We are done
- return 0;
}
+ // We are done
+ return 0;
}
// We are the child
close(pfds[0]);
diff --git a/src/picom.h b/src/picom.h
index 6f14cd08ca..e68b1e042f 100644
--- a/src/picom.h
+++ b/src/picom.h
@@ -94,7 +94,7 @@ free_win_res_glx(session_t *ps attr_unused, struct managed_win *w attr_unused) {
* Dump an drawable's info.
*/
static inline void dump_drawable(session_t *ps, xcb_drawable_t drawable) {
- auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL);
+ auto r = xcb_get_geometry_reply(ps->c.c, xcb_get_geometry(ps->c.c, drawable), NULL);
if (!r) {
log_trace("Drawable %#010x: Failed", drawable);
return;
diff --git a/src/render.c b/src/render.c
index f4b3a97989..65d02cf335 100644
--- a/src/render.c
+++ b/src/render.c
@@ -48,20 +48,20 @@ static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int h
bool repeat, int depth, xcb_visualid_t visual, bool force) {
#ifdef CONFIG_OPENGL
// XXX This is a mess. But this will go away after the backend refactor.
- if (!ppaint->pixmap)
+ if (!ppaint->pixmap) {
return false;
+ }
struct glx_fbconfig_info *fbcfg;
if (!visual) {
assert(depth == 32);
if (!ps->argb_fbconfig) {
- ps->argb_fbconfig =
- glx_find_fbconfig(ps->dpy, ps->scr,
- (struct xvisual_info){.red_size = 8,
- .green_size = 8,
- .blue_size = 8,
- .alpha_size = 8,
- .visual_depth = 32});
+ ps->argb_fbconfig = glx_find_fbconfig(
+ &ps->c, (struct xvisual_info){.red_size = 8,
+ .green_size = 8,
+ .blue_size = 8,
+ .alpha_size = 8,
+ .visual_depth = 32});
}
if (!ps->argb_fbconfig) {
log_error("Failed to find appropriate FBConfig for 32 bit depth");
@@ -69,7 +69,7 @@ static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int h
}
fbcfg = ps->argb_fbconfig;
} else {
- auto m = x_get_visual_info(ps->c, visual);
+ auto m = x_get_visual_info(&ps->c, visual);
if (m.visual_depth < 0) {
return false;
}
@@ -80,7 +80,7 @@ static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int h
}
if (!ppaint->fbcfg) {
- ppaint->fbcfg = glx_find_fbconfig(ps->dpy, ps->scr, m);
+ ppaint->fbcfg = glx_find_fbconfig(&ps->c, m);
}
if (!ppaint->fbcfg) {
log_error("Failed to find appropriate FBConfig for X pixmap");
@@ -89,9 +89,10 @@ static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int h
fbcfg = ppaint->fbcfg;
}
- if (force || !glx_tex_binded(ppaint->ptex, ppaint->pixmap))
+ if (force || !glx_tex_binded(ppaint->ptex, ppaint->pixmap)) {
return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap, wid, hei,
repeat, fbcfg);
+ }
#else
(void)ps;
(void)ppaint;
@@ -129,7 +130,7 @@ static int get_buffer_age(session_t *ps) {
}
if (ps->o.use_damage) {
unsigned int val;
- glXQueryDrawable(ps->dpy, get_tgt_window(ps),
+ glXQueryDrawable(ps->c.dpy, get_tgt_window(ps),
GLX_BACK_BUFFER_AGE_EXT, &val);
return (int)val ?: -1;
}
@@ -144,7 +145,7 @@ static int get_buffer_age(session_t *ps) {
*/
static inline void xrfilter_reset(session_t *ps, xcb_render_picture_t p) {
#define FILTER "Nearest"
- xcb_render_set_picture_filter(ps->c, p, strlen(FILTER), FILTER, 0, NULL);
+ xcb_render_set_picture_filter(ps->c.c, p, strlen(FILTER), FILTER, 0, NULL);
#undef FILTER
}
@@ -153,7 +154,7 @@ static inline void attr_nonnull(1, 2) set_tgt_clip(session_t *ps, region_t *reg)
switch (ps->o.backend) {
case BKEND_XRENDER:
case BKEND_XR_GLX_HYBRID:
- x_set_picture_clip_region(ps->c, ps->tgt_buffer.pict, 0, 0, reg);
+ x_set_picture_clip_region(&ps->c, ps->tgt_buffer.pict, 0, 0, reg);
break;
#ifdef CONFIG_OPENGL
case BKEND_GLX: glx_set_clip(ps, reg); break;
@@ -162,16 +163,6 @@ static inline void attr_nonnull(1, 2) set_tgt_clip(session_t *ps, region_t *reg)
}
}
-/**
- * Destroy a Picture
.
- */
-void free_picture(xcb_connection_t *c, xcb_render_picture_t *p) {
- if (*p) {
- xcb_render_free_picture(c, *p);
- *p = XCB_NONE;
- }
-}
-
/**
* Free paint_t.
*/
@@ -179,10 +170,14 @@ void free_paint(session_t *ps, paint_t *ppaint) {
#ifdef CONFIG_OPENGL
free_paint_glx(ps, ppaint);
#endif
- free_picture(ps->c, &ppaint->pict);
- if (ppaint->pixmap)
- xcb_free_pixmap(ps->c, ppaint->pixmap);
- ppaint->pixmap = XCB_NONE;
+ if (ppaint->pict != XCB_NONE) {
+ x_free_picture(&ps->c, ppaint->pict);
+ ppaint->pict = XCB_NONE;
+ }
+ if (ppaint->pixmap) {
+ xcb_free_pixmap(ps->c.c, ppaint->pixmap);
+ ppaint->pixmap = XCB_NONE;
+ }
}
uint32_t
@@ -253,8 +248,7 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, int f
if (alpha_step != 0) {
if (cr) {
xcb_render_picture_t p_tmp = x_create_picture_with_standard(
- ps->c, ps->root, fullwid, fullhei,
- XCB_PICT_STANDARD_ARGB_32, 0, 0);
+ &ps->c, fullwid, fullhei, XCB_PICT_STANDARD_ARGB_32, 0, 0);
xcb_render_color_t trans = {
.red = 0, .blue = 0, .green = 0, .alpha = 0};
const xcb_rectangle_t rect = {
@@ -262,7 +256,7 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, int f
.y = 0,
.width = to_u16_checked(fullwid),
.height = to_u16_checked(fullhei)};
- xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC,
+ xcb_render_fill_rectangles(ps->c.c, XCB_RENDER_PICT_OP_SRC,
p_tmp, trans, 1, &rect);
uint32_t max_ntraps = to_u32_checked(cr);
@@ -272,25 +266,24 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, int f
traps, max_ntraps, cr, fullwid, fullhei);
xcb_render_trapezoids(
- ps->c, XCB_RENDER_PICT_OP_OVER, alpha_pict, p_tmp,
- x_get_pictfmt_for_standard(ps->c, XCB_PICT_STANDARD_A_8),
+ ps->c.c, XCB_RENDER_PICT_OP_OVER, alpha_pict, p_tmp,
+ x_get_pictfmt_for_standard(&ps->c, XCB_PICT_STANDARD_A_8),
0, 0, n, traps);
xcb_render_composite(
- ps->c, XCB_RENDER_PICT_OP_OVER, pict, p_tmp,
+ ps->c.c, XCB_RENDER_PICT_OP_OVER, pict, p_tmp,
ps->tgt_buffer.pict, to_i16_checked(x),
to_i16_checked(y), to_i16_checked(x), to_i16_checked(y),
to_i16_checked(dx), to_i16_checked(dy),
to_u16_checked(wid), to_u16_checked(hei));
- xcb_render_free_picture(ps->c, p_tmp);
+ x_free_picture(&ps->c, p_tmp);
} else {
xcb_render_picture_t p_tmp = alpha_pict;
if (clip) {
p_tmp = x_create_picture_with_standard(
- ps->c, ps->root, wid, hei,
- XCB_PICT_STANDARD_ARGB_32, 0, 0);
+ &ps->c, wid, hei, XCB_PICT_STANDARD_ARGB_32, 0, 0);
xcb_render_color_t black = {
.red = 255, .blue = 255, .green = 255, .alpha = 255};
@@ -299,17 +292,18 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, int f
.y = 0,
.width = to_u16_checked(wid),
.height = to_u16_checked(hei)};
- xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC,
+ xcb_render_fill_rectangles(ps->c.c,
+ XCB_RENDER_PICT_OP_SRC,
p_tmp, black, 1, &rect);
if (alpha_pict) {
xcb_render_composite(
- ps->c, XCB_RENDER_PICT_OP_SRC,
+ ps->c.c, XCB_RENDER_PICT_OP_SRC,
alpha_pict, XCB_NONE, p_tmp, 0, 0, 0,
0, 0, 0, to_u16_checked(wid),
to_u16_checked(hei));
}
xcb_render_composite(
- ps->c, XCB_RENDER_PICT_OP_OUT_REVERSE,
+ ps->c.c, XCB_RENDER_PICT_OP_OUT_REVERSE,
clip->pict, XCB_NONE, p_tmp, 0, 0, 0, 0,
to_i16_checked(clip->x), to_i16_checked(clip->y),
to_u16_checked(wid), to_u16_checked(hei));
@@ -319,12 +313,12 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, int f
: XCB_RENDER_PICT_OP_OVER);
xcb_render_composite(
- ps->c, op, pict, p_tmp, ps->tgt_buffer.pict,
+ ps->c.c, op, pict, p_tmp, ps->tgt_buffer.pict,
to_i16_checked(x), to_i16_checked(y), 0, 0,
to_i16_checked(dx), to_i16_checked(dy),
to_u16_checked(wid), to_u16_checked(hei));
if (clip) {
- xcb_render_free_picture(ps->c, p_tmp);
+ x_free_picture(&ps->c, p_tmp);
}
}
}
@@ -375,15 +369,18 @@ paint_region(session_t *ps, const struct managed_win *w, int x, int y, int wid,
static inline bool paint_isvalid(session_t *ps, const paint_t *ppaint) {
// Don't check for presence of Pixmap here, because older X Composite doesn't
// provide it
- if (!ppaint)
+ if (!ppaint) {
return false;
+ }
- if (bkend_use_xrender(ps) && !ppaint->pict)
+ if (bkend_use_xrender(ps) && !ppaint->pict) {
return false;
+ }
#ifdef CONFIG_OPENGL
- if (BKEND_GLX == ps->o.backend && !glx_tex_binded(ppaint->ptex, XCB_NONE))
+ if (BKEND_GLX == ps->o.backend && !glx_tex_binded(ppaint->ptex, XCB_NONE)) {
return false;
+ }
#endif
return true;
@@ -395,9 +392,9 @@ static inline bool paint_isvalid(session_t *ps, const paint_t *ppaint) {
void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) {
// Fetch Pixmap
if (!w->paint.pixmap) {
- w->paint.pixmap = x_new_id(ps->c);
- set_ignore_cookie(ps, xcb_composite_name_window_pixmap(ps->c, w->base.id,
- w->paint.pixmap));
+ w->paint.pixmap = x_new_id(&ps->c);
+ set_ignore_cookie(&ps->c, xcb_composite_name_window_pixmap(
+ ps->c.c, w->base.id, w->paint.pixmap));
}
xcb_drawable_t draw = w->paint.pixmap;
@@ -415,7 +412,7 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint)
};
w->paint.pict = x_create_picture_with_pictfmt_and_pixmap(
- ps->c, w->pictfmt, draw, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
+ &ps->c, w->pictfmt, draw, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
}
// GLX: Build texture
@@ -442,8 +439,8 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint)
// Invert window color, if required
if (bkend_use_xrender(ps) && w->invert_color) {
- xcb_render_picture_t newpict = x_create_picture_with_pictfmt(
- ps->c, ps->root, wid, hei, w->pictfmt, 0, NULL);
+ xcb_render_picture_t newpict =
+ x_create_picture_with_pictfmt(&ps->c, wid, hei, w->pictfmt, 0, NULL);
if (newpict) {
// Apply clipping region to save some CPU
if (reg_paint) {
@@ -456,17 +453,18 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint)
pixman_region32_fini(®);
}
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, pict, XCB_NONE,
- newpict, 0, 0, 0, 0, 0, 0, wid, hei);
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_DIFFERENCE,
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_SRC, pict,
+ XCB_NONE, newpict, 0, 0, 0, 0, 0, 0, wid, hei);
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_DIFFERENCE,
ps->white_picture, XCB_NONE, newpict, 0, 0,
0, 0, 0, 0, wid, hei);
// We use an extra PictOpInReverse operation to get correct
// pixel alpha. There could be a better solution.
- if (win_has_alpha(w))
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_IN_REVERSE,
+ if (win_has_alpha(w)) {
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_IN_REVERSE,
pict, XCB_NONE, newpict, 0, 0, 0, 0,
0, 0, wid, hei);
+ }
pict = newpict;
}
}
@@ -494,43 +492,51 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint)
// ctop = checked top
// Make sure top margin is smaller than height
int ctop = min2(body_height, t);
- if (ctop > 0)
+ if (ctop > 0) {
COMP_BDR(0, 0, wid, ctop);
+ }
body_height -= ctop;
- if (body_height <= 0)
+ if (body_height <= 0) {
break;
+ }
// bottom
// cbot = checked bottom
// Make sure bottom margin is not too large
int cbot = min2(body_height, b);
- if (cbot > 0)
+ if (cbot > 0) {
COMP_BDR(0, hei - cbot, wid, cbot);
+ }
// Height of window exclude the margin
body_height -= cbot;
- if (body_height <= 0)
+ if (body_height <= 0) {
break;
+ }
// left
int body_width = wid;
int cleft = min2(body_width, l);
- if (cleft > 0)
+ if (cleft > 0) {
COMP_BDR(0, ctop, cleft, body_height);
+ }
body_width -= cleft;
- if (body_width <= 0)
+ if (body_width <= 0) {
break;
+ }
// right
int cright = min2(body_width, r);
- if (cright > 0)
+ if (cright > 0) {
COMP_BDR(wid - cright, ctop, cright, body_height);
+ }
body_width -= cright;
- if (body_width <= 0)
+ if (body_width <= 0) {
break;
+ }
// body
paint_region(ps, w, cleft, ctop, body_width, body_height,
@@ -540,14 +546,17 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint)
#undef COMP_BDR
- if (pict != w->paint.pict)
- free_picture(ps->c, &pict);
+ if (pict != w->paint.pict) {
+ x_free_picture(&ps->c, pict);
+ pict = XCB_NONE;
+ }
// Dimming the window if needed
if (w->dim) {
double dim_opacity = ps->o.inactive_dim;
- if (!ps->o.inactive_dim_fixed)
+ if (!ps->o.inactive_dim_fixed) {
dim_opacity *= w->opacity;
+ }
switch (ps->o.backend) {
case BKEND_XRENDER:
@@ -569,7 +578,7 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint)
.height = hei,
};
- xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_OVER,
+ xcb_render_fill_rectangles(ps->c.c, XCB_RENDER_PICT_OP_OVER,
ps->tgt_buffer.pict, color, 1, &rect);
} break;
#ifdef CONFIG_OPENGL
@@ -593,15 +602,17 @@ static bool get_root_tile(session_t *ps) {
ps->root_tile_fill = false;
bool fill = false;
- xcb_pixmap_t pixmap = x_get_root_back_pixmap(ps->c, ps->root, ps->atoms);
+ xcb_pixmap_t pixmap = x_get_root_back_pixmap(&ps->c, ps->atoms);
// Make sure the pixmap we got is valid
- if (pixmap && !x_validate_pixmap(ps->c, pixmap))
+ if (pixmap && !x_validate_pixmap(&ps->c, pixmap)) {
pixmap = XCB_NONE;
+ }
// Create a pixmap if there isn't any
if (!pixmap) {
- pixmap = x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root, 1, 1);
+ pixmap =
+ x_create_pixmap(&ps->c, (uint8_t)ps->c.screen_info->root_depth, 1, 1);
if (pixmap == XCB_NONE) {
log_error("Failed to create pixmaps for root tile.");
return false;
@@ -614,7 +625,7 @@ static bool get_root_tile(session_t *ps) {
.repeat = true,
};
ps->root_tile_paint.pict = x_create_picture_with_visual_and_pixmap(
- ps->c, ps->vis, pixmap, XCB_RENDER_CP_REPEAT, &pa);
+ &ps->c, ps->c.screen_info->root_visual, pixmap, XCB_RENDER_CP_REPEAT, &pa);
// Fill pixmap if needed
if (fill) {
@@ -627,15 +638,17 @@ static bool get_root_tile(session_t *ps) {
rect.x = rect.y = 0;
rect.width = rect.height = 1;
- xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC,
+ xcb_render_fill_rectangles(ps->c.c, XCB_RENDER_PICT_OP_SRC,
ps->root_tile_paint.pict, col, 1, &rect);
}
ps->root_tile_fill = fill;
ps->root_tile_paint.pixmap = pixmap;
#ifdef CONFIG_OPENGL
- if (BKEND_GLX == ps->o.backend)
- return paint_bind_tex(ps, &ps->root_tile_paint, 0, 0, true, 0, ps->vis, false);
+ if (BKEND_GLX == ps->o.backend) {
+ return paint_bind_tex(ps, &ps->root_tile_paint, 0, 0, true, 0,
+ ps->c.screen_info->root_visual, false);
+ }
#endif
return true;
@@ -668,16 +681,16 @@ static bool win_build_shadow(session_t *ps, struct managed_win *w, double opacit
xcb_render_picture_t shadow_picture = XCB_NONE, shadow_picture_argb = XCB_NONE;
xcb_gcontext_t gc = XCB_NONE;
- shadow_image = make_shadow(ps->c, (conv *)ps->shadow_context, opacity, width, height);
+ shadow_image =
+ make_shadow(&ps->c, (conv *)ps->shadow_context, opacity, width, height);
if (!shadow_image) {
log_error("failed to make shadow");
return XCB_NONE;
}
- shadow_pixmap =
- x_create_pixmap(ps->c, 8, ps->root, shadow_image->width, shadow_image->height);
+ shadow_pixmap = x_create_pixmap(&ps->c, 8, shadow_image->width, shadow_image->height);
shadow_pixmap_argb =
- x_create_pixmap(ps->c, 32, ps->root, shadow_image->width, shadow_image->height);
+ x_create_pixmap(&ps->c, 32, shadow_image->width, shadow_image->height);
if (!shadow_pixmap || !shadow_pixmap_argb) {
log_error("failed to create shadow pixmaps");
@@ -685,18 +698,18 @@ static bool win_build_shadow(session_t *ps, struct managed_win *w, double opacit
}
shadow_picture = x_create_picture_with_standard_and_pixmap(
- ps->c, XCB_PICT_STANDARD_A_8, shadow_pixmap, 0, NULL);
+ &ps->c, XCB_PICT_STANDARD_A_8, shadow_pixmap, 0, NULL);
shadow_picture_argb = x_create_picture_with_standard_and_pixmap(
- ps->c, XCB_PICT_STANDARD_ARGB_32, shadow_pixmap_argb, 0, NULL);
+ &ps->c, XCB_PICT_STANDARD_ARGB_32, shadow_pixmap_argb, 0, NULL);
if (!shadow_picture || !shadow_picture_argb) {
goto shadow_picture_err;
}
- gc = x_new_id(ps->c);
- xcb_create_gc(ps->c, gc, shadow_pixmap, 0, NULL);
+ gc = x_new_id(&ps->c);
+ xcb_create_gc(ps->c.c, gc, shadow_pixmap, 0, NULL);
- xcb_image_put(ps->c, shadow_pixmap, gc, shadow_image, 0, 0, 0);
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture,
+ xcb_image_put(ps->c.c, shadow_pixmap, gc, shadow_image, 0, 0, 0);
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture,
shadow_picture, shadow_picture_argb, 0, 0, 0, 0, 0, 0,
shadow_image->width, shadow_image->height);
@@ -705,26 +718,32 @@ static bool win_build_shadow(session_t *ps, struct managed_win *w, double opacit
assert(!w->shadow_paint.pict);
w->shadow_paint.pict = shadow_picture_argb;
- xcb_free_gc(ps->c, gc);
+ xcb_free_gc(ps->c.c, gc);
xcb_image_destroy(shadow_image);
- xcb_free_pixmap(ps->c, shadow_pixmap);
- xcb_render_free_picture(ps->c, shadow_picture);
+ xcb_free_pixmap(ps->c.c, shadow_pixmap);
+ x_free_picture(&ps->c, shadow_picture);
return true;
shadow_picture_err:
- if (shadow_image)
+ if (shadow_image) {
xcb_image_destroy(shadow_image);
- if (shadow_pixmap)
- xcb_free_pixmap(ps->c, shadow_pixmap);
- if (shadow_pixmap_argb)
- xcb_free_pixmap(ps->c, shadow_pixmap_argb);
- if (shadow_picture)
- xcb_render_free_picture(ps->c, shadow_picture);
- if (shadow_picture_argb)
- xcb_render_free_picture(ps->c, shadow_picture_argb);
- if (gc)
- xcb_free_gc(ps->c, gc);
+ }
+ if (shadow_pixmap) {
+ xcb_free_pixmap(ps->c.c, shadow_pixmap);
+ }
+ if (shadow_pixmap_argb) {
+ xcb_free_pixmap(ps->c.c, shadow_pixmap_argb);
+ }
+ if (shadow_picture) {
+ x_free_picture(&ps->c, shadow_picture);
+ }
+ if (shadow_picture_argb) {
+ x_free_picture(&ps->c, shadow_picture_argb);
+ }
+ if (gc) {
+ xcb_free_gc(ps->c.c, gc);
+ }
return false;
}
@@ -753,23 +772,22 @@ win_paint_shadow(session_t *ps, struct managed_win *w, region_t *reg_paint) {
traps, max_ntraps, w->corner_radius, w->widthb, w->heightb);
td = x_create_picture_with_standard(
- ps->c, ps->root, w->widthb, w->heightb,
- XCB_PICT_STANDARD_ARGB_32, 0, 0);
+ &ps->c, w->widthb, w->heightb, XCB_PICT_STANDARD_ARGB_32, 0, 0);
xcb_render_color_t trans = {
.red = 0, .blue = 0, .green = 0, .alpha = 0};
const xcb_rectangle_t rect = {.x = 0,
.y = 0,
.width = to_u16_checked(w->widthb),
.height = to_u16_checked(w->heightb)};
- xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, td,
+ xcb_render_fill_rectangles(ps->c.c, XCB_RENDER_PICT_OP_SRC, td,
trans, 1, &rect);
- auto solid = solid_picture(ps->c, ps->root, false, 1, 0, 0, 0);
+ auto solid = solid_picture(&ps->c, false, 1, 0, 0, 0);
xcb_render_trapezoids(
- ps->c, XCB_RENDER_PICT_OP_OVER, solid, td,
- x_get_pictfmt_for_standard(ps->c, XCB_PICT_STANDARD_A_8), 0,
+ ps->c.c, XCB_RENDER_PICT_OP_OVER, solid, td,
+ x_get_pictfmt_for_standard(&ps->c, XCB_PICT_STANDARD_A_8), 0,
0, n, traps);
- xcb_render_free_picture(ps->c, solid);
+ x_free_picture(&ps->c, solid);
} else {
// Not implemented
}
@@ -785,7 +803,7 @@ win_paint_shadow(session_t *ps, struct managed_win *w, region_t *reg_paint) {
w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, NULL,
should_clip ? &clip : NULL);
if (td) {
- xcb_render_free_picture(ps->c, td);
+ x_free_picture(&ps->c, td);
}
}
@@ -813,16 +831,17 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y
// Directly copying from tgt_buffer to it does not work, so we create a
// Picture in the middle.
- xcb_render_picture_t tmp_picture =
- x_create_picture_with_visual(ps->c, ps->root, wid, hei, ps->vis, 0, NULL);
+ xcb_render_picture_t tmp_picture = x_create_picture_with_visual(
+ &ps->c, wid, hei, ps->c.screen_info->root_visual, 0, NULL);
if (!tmp_picture) {
log_error("Failed to build intermediate Picture.");
return false;
}
- if (reg_clip && tmp_picture)
- x_set_picture_clip_region(ps->c, tmp_picture, 0, 0, reg_clip);
+ if (reg_clip && tmp_picture) {
+ x_set_picture_clip_region(&ps->c, tmp_picture, 0, 0, reg_clip);
+ }
xcb_render_picture_t src_pict = tgt_buffer, dst_pict = tmp_picture;
for (int i = 0; i < nkernels; ++i) {
@@ -836,9 +855,9 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y
// be applied on source picture, to get the nearby pixels outside the
// window.
xcb_render_set_picture_filter(
- ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
+ ps->c.c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
(uint32_t)(kwid * khei + 2), convolution_blur);
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
dst_pict, (rd_from_tgt ? x : 0),
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
(rd_from_tgt ? 0 : y), wid, hei);
@@ -851,11 +870,12 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y
}
}
- if (src_pict != tgt_buffer)
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, src_pict, rounded,
+ if (src_pict != tgt_buffer) {
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_OVER, src_pict, rounded,
tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
+ }
- free_picture(ps->c, &tmp_picture);
+ x_free_picture(&ps->c, tmp_picture);
return true;
}
@@ -910,23 +930,23 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
make_rounded_window_shape(traps, max_ntraps, cr, wid, hei);
td = x_create_picture_with_standard(
- ps->c, ps->root, wid, hei, XCB_PICT_STANDARD_ARGB_32, 0, 0);
+ &ps->c, wid, hei, XCB_PICT_STANDARD_ARGB_32, 0, 0);
xcb_render_color_t trans = {
.red = 0, .blue = 0, .green = 0, .alpha = 0};
const xcb_rectangle_t rect = {.x = 0,
.y = 0,
.width = to_u16_checked(wid),
.height = to_u16_checked(hei)};
- xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, td,
+ xcb_render_fill_rectangles(ps->c.c, XCB_RENDER_PICT_OP_SRC, td,
trans, 1, &rect);
- auto solid = solid_picture(ps->c, ps->root, false, 1, 0, 0, 0);
+ auto solid = solid_picture(&ps->c, false, 1, 0, 0, 0);
xcb_render_trapezoids(
- ps->c, XCB_RENDER_PICT_OP_OVER, solid, td,
- x_get_pictfmt_for_standard(ps->c, XCB_PICT_STANDARD_A_8), 0,
+ ps->c.c, XCB_RENDER_PICT_OP_OVER, solid, td,
+ x_get_pictfmt_for_standard(&ps->c, XCB_PICT_STANDARD_A_8), 0,
0, n, traps);
- xcb_render_free_picture(ps->c, solid);
+ x_free_picture(&ps->c, solid);
}
// Minimize the region we try to blur, if the window itself is not
@@ -946,7 +966,7 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
xr_blur_dst(ps, tgt_buffer, x, y, wid, hei, ps->blur_kerns_cache,
ps->o.blur_kernel_count, ®_blur, td);
if (td) {
- xcb_render_free_picture(ps->c, td);
+ x_free_picture(&ps->c, td);
}
pixman_region32_clear(®_blur);
} break;
@@ -969,10 +989,10 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
/// region_real = the damage region
void paint_all(session_t *ps, struct managed_win *t) {
if (ps->o.xrender_sync_fence || (ps->drivers & DRIVER_NVIDIA)) {
- if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) {
+ if (ps->xsync_exists && !x_fence_sync(&ps->c, ps->sync_fence)) {
log_error("x_fence_sync failed, xrender-sync-fence will be "
"disabled from now on.");
- xcb_sync_destroy_fence(ps->c, ps->sync_fence);
+ xcb_sync_destroy_fence(ps->c.c, ps->sync_fence);
ps->sync_fence = XCB_NONE;
ps->o.xrender_sync_fence = false;
ps->xsync_exists = false;
@@ -1010,7 +1030,7 @@ void paint_all(session_t *ps, struct managed_win *t) {
if (!ps->tgt_buffer.pixmap) {
free_paint(ps, &ps->tgt_buffer);
ps->tgt_buffer.pixmap =
- x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root,
+ x_create_pixmap(&ps->c, ps->c.screen_info->root_depth,
ps->root_width, ps->root_height);
if (ps->tgt_buffer.pixmap == XCB_NONE) {
log_fatal("Failed to allocate a screen-sized pixmap for"
@@ -1019,18 +1039,20 @@ void paint_all(session_t *ps, struct managed_win *t) {
}
}
- if (BKEND_GLX != ps->o.backend)
+ if (BKEND_GLX != ps->o.backend) {
ps->tgt_buffer.pict = x_create_picture_with_visual_and_pixmap(
- ps->c, ps->vis, ps->tgt_buffer.pixmap, 0, 0);
+ &ps->c, ps->c.screen_info->root_visual, ps->tgt_buffer.pixmap,
+ 0, 0);
+ }
}
if (BKEND_XRENDER == ps->o.backend) {
- x_set_picture_clip_region(ps->c, ps->tgt_picture, 0, 0, ®ion);
+ x_set_picture_clip_region(&ps->c, ps->tgt_picture, 0, 0, ®ion);
}
#ifdef CONFIG_OPENGL
if (bkend_use_glx(ps)) {
- ps->psglx->z = 0.0;
+ ps->psglx->z = 0;
}
#endif
@@ -1066,18 +1088,21 @@ void paint_all(session_t *ps, struct managed_win *t) {
// Painting shadow
if (w->shadow) {
// Lazy shadow building
- if (!w->shadow_paint.pixmap)
- if (!win_build_shadow(ps, w, 1))
+ if (!w->shadow_paint.pixmap) {
+ if (!win_build_shadow(ps, w, 1)) {
log_error("build shadow failed");
+ }
+ }
// Shadow doesn't need to be painted underneath the body
// of the windows above. Because no one can see it
pixman_region32_subtract(®_tmp, ®ion, w->reg_ignore);
// Mask out the region we don't want shadow on
- if (pixman_region32_not_empty(&ps->shadow_exclude_reg))
+ if (pixman_region32_not_empty(&ps->shadow_exclude_reg)) {
pixman_region32_subtract(®_tmp, ®_tmp,
&ps->shadow_exclude_reg);
+ }
if (pixman_region32_not_empty(®_shadow_clip)) {
pixman_region32_subtract(®_tmp, ®_tmp, ®_shadow_clip);
}
@@ -1093,11 +1118,12 @@ void paint_all(session_t *ps, struct managed_win *t) {
// needed Doing it here instead of in make_shadow() for
// saving GPU power and handling shaped windows (XXX
// unconfirmed)
- if (!ps->o.wintype_option[w->window_type].full_shadow)
+ if (!ps->o.wintype_option[w->window_type].full_shadow) {
pixman_region32_subtract(®_tmp, ®_tmp, &bshape_no_corners);
+ }
if (ps->o.crop_shadow_to_monitor && w->randr_monitor >= 0 &&
- w->randr_monitor < ps->randr_nmonitors) {
+ w->randr_monitor < ps->monitors.count) {
// There can be a window where number of monitors is
// updated, but the monitor number attached to the window
// have not.
@@ -1107,7 +1133,7 @@ void paint_all(session_t *ps, struct managed_win *t) {
// bounds.
pixman_region32_intersect(
®_tmp, ®_tmp,
- &ps->randr_monitor_regs[w->randr_monitor]);
+ &ps->monitors.regions[w->randr_monitor]);
}
// Detect if the region is empty before painting
@@ -1197,13 +1223,14 @@ void paint_all(session_t *ps, struct managed_win *t) {
if (ps->o.vsync) {
// Make sure all previous requests are processed to achieve best
// effect
- x_sync(ps->c);
+ x_sync(&ps->c);
#ifdef CONFIG_OPENGL
if (glx_has_context(ps)) {
- if (ps->o.vsync_use_glfinish)
+ if (ps->o.vsync_use_glfinish) {
glFinish();
- else
+ } else {
glFlush();
+ }
glXWaitX();
}
#endif
@@ -1224,57 +1251,63 @@ void paint_all(session_t *ps, struct managed_win *t) {
// First we create a new picture, and copy content from the buffer
// to it
- auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis);
+ auto pictfmt = x_get_pictform_for_visual(
+ &ps->c, ps->c.screen_info->root_visual);
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
- ps->c, ps->root, rwidth, rheight, pictfmt, 0, NULL);
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
+ &ps->c, rwidth, rheight, pictfmt, 0, NULL);
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_SRC,
ps->tgt_buffer.pict, XCB_NONE, new_pict, 0,
0, 0, 0, 0, 0, rwidth, rheight);
// Next, we set the region of paint and highlight it
- x_set_picture_clip_region(ps->c, new_pict, 0, 0, ®ion);
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
+ x_set_picture_clip_region(&ps->c, new_pict, 0, 0, ®ion);
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0,
0, 0, 0, 0, 0, rwidth, rheight);
// Finally, clear clip regions of new_pict and the screen, and put
// the whole thing on screen
- x_set_picture_clip_region(ps->c, new_pict, 0, 0, &ps->screen_reg);
- x_set_picture_clip_region(ps->c, ps->tgt_picture, 0, 0, &ps->screen_reg);
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict,
+ x_set_picture_clip_region(&ps->c, new_pict, 0, 0, &ps->screen_reg);
+ x_set_picture_clip_region(&ps->c, ps->tgt_picture, 0, 0,
+ &ps->screen_reg);
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_SRC, new_pict,
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
rwidth, rheight);
- xcb_render_free_picture(ps->c, new_pict);
- } else
- xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
+ x_free_picture(&ps->c, new_pict);
+ } else {
+ xcb_render_composite(ps->c.c, XCB_RENDER_PICT_OP_SRC,
ps->tgt_buffer.pict, XCB_NONE, ps->tgt_picture,
0, 0, 0, 0, 0, 0, rwidth, rheight);
+ }
break;
#ifdef CONFIG_OPENGL
case BKEND_XR_GLX_HYBRID:
- x_sync(ps->c);
- if (ps->o.vsync_use_glfinish)
+ x_sync(&ps->c);
+ if (ps->o.vsync_use_glfinish) {
glFinish();
- else
+ } else {
glFlush();
+ }
glXWaitX();
assert(ps->tgt_buffer.pixmap);
paint_bind_tex(ps, &ps->tgt_buffer, ps->root_width, ps->root_height,
- false, ps->depth, ps->vis, !ps->o.glx_no_rebind_pixmap);
- if (ps->o.vsync_use_glfinish)
+ false, ps->c.screen_info->root_depth,
+ ps->c.screen_info->root_visual, !ps->o.glx_no_rebind_pixmap);
+ if (ps->o.vsync_use_glfinish) {
glFinish();
- else
+ } else {
glFlush();
+ }
glXWaitX();
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0, ps->root_width,
ps->root_height, 0, 1.0, false, false, ®ion, NULL);
fallthrough();
- case BKEND_GLX: glXSwapBuffers(ps->dpy, get_tgt_window(ps)); break;
+ case BKEND_GLX: glXSwapBuffers(ps->c.dpy, get_tgt_window(ps)); break;
#endif
default: assert(0);
}
- x_sync(ps->c);
+ x_sync(&ps->c);
#ifdef CONFIG_OPENGL
if (glx_has_context(ps)) {
@@ -1304,7 +1337,7 @@ void paint_all(session_t *ps, struct managed_win *t) {
static bool xr_init_blur(session_t *ps) {
// Query filters
xcb_render_query_filters_reply_t *pf = xcb_render_query_filters_reply(
- ps->c, xcb_render_query_filters(ps->c, get_tgt_window(ps)), NULL);
+ ps->c.c, xcb_render_query_filters(ps->c.c, get_tgt_window(ps)), NULL);
if (pf) {
xcb_str_iterator_t iter = xcb_render_query_filters_filters_iterator(pf);
for (; iter.rem; xcb_str_next(&iter)) {
@@ -1312,8 +1345,9 @@ static bool xr_init_blur(session_t *ps) {
char *name = xcb_str_name(iter.data);
// Check for the convolution filter
if (strlen(XRFILTER_CONVOLUTION) == len &&
- !memcmp(XRFILTER_CONVOLUTION, name, strlen(XRFILTER_CONVOLUTION)))
+ !memcmp(XRFILTER_CONVOLUTION, name, strlen(XRFILTER_CONVOLUTION))) {
ps->xrfilter_convolution_exists = true;
+ }
}
free(pf);
}
@@ -1337,9 +1371,10 @@ static bool init_alpha_picts(session_t *ps) {
for (int i = 0; i <= MAX_ALPHA; ++i) {
double o = (double)i / MAX_ALPHA;
- ps->alpha_picts[i] = solid_picture(ps->c, ps->root, false, o, 0, 0, 0);
- if (ps->alpha_picts[i] == XCB_NONE)
+ ps->alpha_picts[i] = solid_picture(&ps->c, false, o, 0, 0, 0);
+ if (ps->alpha_picts[i] == XCB_NONE) {
return false;
+ }
}
return true;
}
@@ -1351,12 +1386,13 @@ bool init_render(session_t *ps) {
// Initialize OpenGL as early as possible
#ifdef CONFIG_OPENGL
- glxext_init(ps->dpy, ps->scr);
+ glxext_init(ps->c.dpy, ps->c.screen);
#endif
if (bkend_use_glx(ps)) {
#ifdef CONFIG_OPENGL
- if (!glx_init(ps, true))
+ if (!glx_init(ps, true)) {
return false;
+ }
#else
log_error("GLX backend support not compiled in.");
return false;
@@ -1371,8 +1407,9 @@ bool init_render(session_t *ps) {
// Initialize window GL shader
if (BKEND_GLX == ps->o.backend && ps->o.glx_fshader_win_str) {
#ifdef CONFIG_OPENGL
- if (!glx_load_prog_main(NULL, ps->o.glx_fshader_win_str, &ps->glx_prog_win))
+ if (!glx_load_prog_main(NULL, ps->o.glx_fshader_win_str, &ps->glx_prog_win)) {
return false;
+ }
#else
log_error("GLSL supported not compiled in, can't load "
"shader.");
@@ -1411,8 +1448,8 @@ bool init_render(session_t *ps) {
}
}
- ps->black_picture = solid_picture(ps->c, ps->root, true, 1, 0, 0, 0);
- ps->white_picture = solid_picture(ps->c, ps->root, true, 1, 1, 1, 1);
+ ps->black_picture = solid_picture(&ps->c, true, 1, 0, 0, 0);
+ ps->white_picture = solid_picture(&ps->c, true, 1, 1, 1, 1);
if (ps->black_picture == XCB_NONE || ps->white_picture == XCB_NONE) {
log_error("Failed to create solid xrender pictures.");
@@ -1424,7 +1461,7 @@ bool init_render(session_t *ps) {
if (ps->o.shadow_red == 0 && ps->o.shadow_green == 0 && ps->o.shadow_blue == 0) {
ps->cshadow_picture = ps->black_picture;
} else {
- ps->cshadow_picture = solid_picture(ps->c, ps->root, true, 1, ps->o.shadow_red,
+ ps->cshadow_picture = solid_picture(&ps->c, true, 1, ps->o.shadow_red,
ps->o.shadow_green, ps->o.shadow_blue);
if (ps->cshadow_picture == XCB_NONE) {
log_error("Failed to create shadow picture.");
@@ -1450,14 +1487,14 @@ bool init_render(session_t *ps) {
* Free root tile related things.
*/
void free_root_tile(session_t *ps) {
- free_picture(ps->c, &ps->root_tile_paint.pict);
+ x_free_picture(&ps->c, ps->root_tile_paint.pict);
#ifdef CONFIG_OPENGL
free_texture(ps, &ps->root_tile_paint.ptex);
#else
assert(!ps->root_tile_paint.ptex);
#endif
if (ps->root_tile_fill) {
- xcb_free_pixmap(ps->c, ps->root_tile_paint.pixmap);
+ xcb_free_pixmap(ps->c.c, ps->root_tile_paint.pixmap);
ps->root_tile_paint.pixmap = XCB_NONE;
}
ps->root_tile_paint.pixmap = XCB_NONE;
@@ -1466,19 +1503,20 @@ void free_root_tile(session_t *ps) {
void deinit_render(session_t *ps) {
// Free alpha_picts
- for (int i = 0; i <= MAX_ALPHA; ++i)
- free_picture(ps->c, &ps->alpha_picts[i]);
+ for (int i = 0; i <= MAX_ALPHA; ++i) {
+ x_free_picture(&ps->c, ps->alpha_picts[i]);
+ }
free(ps->alpha_picts);
ps->alpha_picts = NULL;
// Free cshadow_picture and black_picture
- if (ps->cshadow_picture == ps->black_picture)
- ps->cshadow_picture = XCB_NONE;
- else
- free_picture(ps->c, &ps->cshadow_picture);
+ if (ps->cshadow_picture != ps->black_picture) {
+ x_free_picture(&ps->c, ps->cshadow_picture);
+ }
- free_picture(ps->c, &ps->black_picture);
- free_picture(ps->c, &ps->white_picture);
+ x_free_picture(&ps->c, ps->black_picture);
+ x_free_picture(&ps->c, ps->white_picture);
+ ps->cshadow_picture = ps->black_picture = ps->white_picture = XCB_NONE;
// Free other X resources
free_root_tile(ps);
diff --git a/src/render.h b/src/render.h
index 249f7bf255..4e0c7a8162 100644
--- a/src/render.h
+++ b/src/render.h
@@ -39,8 +39,6 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint);
void paint_all(session_t *ps, struct managed_win *const t);
-void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);
-
void free_paint(session_t *ps, paint_t *ppaint);
void free_root_tile(session_t *ps);
diff --git a/src/vsync.c b/src/vsync.c
index 5980155837..57fbb595ef 100644
--- a/src/vsync.c
+++ b/src/vsync.c
@@ -77,31 +77,35 @@ static bool vsync_drm_init(session_t *ps) {
* @return true for success, false otherwise
*/
static bool vsync_opengl_init(session_t *ps) {
- if (!ensure_glx_context(ps))
+ if (!ensure_glx_context(ps)) {
return false;
+ }
return glxext.has_GLX_SGI_video_sync;
}
static bool vsync_opengl_oml_init(session_t *ps) {
- if (!ensure_glx_context(ps))
+ if (!ensure_glx_context(ps)) {
return false;
+ }
return glxext.has_GLX_OML_sync_control;
}
static inline bool vsync_opengl_swc_swap_interval(session_t *ps, int interval) {
- if (glxext.has_GLX_MESA_swap_control)
+ if (glxext.has_GLX_MESA_swap_control) {
return glXSwapIntervalMESA((uint)interval) == 0;
- else if (glxext.has_GLX_SGI_swap_control)
+ }
+ if (glxext.has_GLX_SGI_swap_control) {
return glXSwapIntervalSGI(interval) == 0;
- else if (glxext.has_GLX_EXT_swap_control) {
+ }
+ if (glxext.has_GLX_EXT_swap_control) {
GLXDrawable d = glXGetCurrentDrawable();
if (d == None) {
// We don't have a context??
return false;
}
- glXSwapIntervalEXT(ps->dpy, glXGetCurrentDrawable(), interval);
+ glXSwapIntervalEXT(ps->c.dpy, glXGetCurrentDrawable(), interval);
return true;
}
return false;
@@ -140,8 +144,8 @@ static int vsync_opengl_wait(session_t *ps attr_unused) {
static int vsync_opengl_oml_wait(session_t *ps) {
int64_t ust = 0, msc = 0, sbc = 0;
- glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc);
- glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2, &ust, &msc, &sbc);
+ glXGetSyncValuesOML(ps->c.dpy, ps->reg_win, &ust, &msc, &sbc);
+ glXWaitForMscOML(ps->c.dpy, ps->reg_win, 0, 2, (msc + 1) % 2, &ust, &msc, &sbc);
return 0;
}
#endif
diff --git a/src/win.c b/src/win.c
index 1aa10fd217..14e2953f81 100644
--- a/src/win.c
+++ b/src/win.c
@@ -324,7 +324,7 @@ static inline bool win_bind_pixmap(struct backend_base *b, struct managed_win *w
assert(!w->win_image);
auto pixmap = x_new_id(b->c);
auto e = xcb_request_check(
- b->c, xcb_composite_name_window_pixmap_checked(b->c, w->base.id, pixmap));
+ b->c->c, xcb_composite_name_window_pixmap_checked(b->c->c, w->base.id, pixmap));
if (e) {
log_error("Failed to get named pixmap for window %#010x(%s)", w->base.id,
w->name);
@@ -519,7 +519,7 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
win_clear_flags(w, WIN_FLAGS_POSITION_STALE);
}
- win_update_monitor(ps->randr_nmonitors, ps->randr_monitor_regs, w);
+ win_update_monitor(&ps->monitors, w);
}
if (win_check_flags_all(w, WIN_FLAGS_PROPERTY_STALE)) {
@@ -702,7 +702,7 @@ static inline bool win_bounding_shaped(const session_t *ps, xcb_window_t wid) {
Bool bounding_shaped;
reply = xcb_shape_query_extents_reply(
- ps->c, xcb_shape_query_extents(ps->c, wid), NULL);
+ ps->c.c, xcb_shape_query_extents(ps->c.c, wid), NULL);
bounding_shaped = reply && reply->bounding_shaped;
free(reply);
@@ -714,7 +714,7 @@ static inline bool win_bounding_shaped(const session_t *ps, xcb_window_t wid) {
static wintype_t wid_get_prop_wintype(session_t *ps, xcb_window_t wid) {
winprop_t prop =
- x_get_prop(ps->c, wid, ps->atoms->a_NET_WM_WINDOW_TYPE, 32L, XCB_ATOM_ATOM, 32);
+ x_get_prop(&ps->c, wid, ps->atoms->a_NET_WM_WINDOW_TYPE, 32L, XCB_ATOM_ATOM, 32);
for (unsigned i = 0; i < prop.nitems; ++i) {
for (wintype_t j = 1; j < NUM_WINTYPES; ++j) {
@@ -735,7 +735,7 @@ wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def, opacity_t *
bool ret = false;
*out = def;
- winprop_t prop = x_get_prop(ps->c, wid, ps->atoms->a_NET_WM_WINDOW_OPACITY, 1L,
+ winprop_t prop = x_get_prop(&ps->c, wid, ps->atoms->a_NET_WM_WINDOW_OPACITY, 1L,
XCB_ATOM_CARDINAL, 32);
if (prop.nitems) {
@@ -827,11 +827,12 @@ double win_calc_opacity_target(session_t *ps, const struct managed_win *w) {
} else {
// Respect active_opacity only when the window is physically
// focused
- if (win_is_focused_raw(ps, w))
+ if (win_is_focused_raw(ps, w)) {
opacity = ps->o.active_opacity;
- else if (!w->focused)
+ } else if (!w->focused) {
// Respect inactive_opacity in some cases
opacity = ps->o.inactive_opacity;
+ }
}
// respect inactive override
@@ -853,9 +854,8 @@ bool win_should_dim(session_t *ps, const struct managed_win *w) {
if (ps->o.inactive_dim > 0 && !(w->focused)) {
return true;
- } else {
- return false;
}
+ return false;
}
/**
@@ -887,7 +887,7 @@ bool win_should_fade(session_t *ps, const struct managed_win *w) {
* The property must be set on the outermost window, usually the WM frame.
*/
void win_update_prop_shadow_raw(session_t *ps, struct managed_win *w) {
- winprop_t prop = x_get_prop(ps->c, w->base.id, ps->atoms->a_COMPTON_SHADOW, 1,
+ winprop_t prop = x_get_prop(&ps->c, w->base.id, ps->atoms->a_COMPTON_SHADOW, 1,
XCB_ATOM_CARDINAL, 32);
if (!prop.nitems) {
@@ -1085,8 +1085,9 @@ void win_set_shadow_force(session_t *ps, struct managed_win *w, switch_t val) {
static void
win_set_blur_background(session_t *ps, struct managed_win *w, bool blur_background_new) {
- if (w->blur_background == blur_background_new)
+ if (w->blur_background == blur_background_new) {
return;
+ }
w->blur_background = blur_background_new;
@@ -1284,10 +1285,11 @@ void win_update_wintype(session_t *ps, struct managed_win *w) {
// _NET_WM_WINDOW_TYPE_NORMAL, otherwise as _NET_WM_WINDOW_TYPE_DIALOG.
if (WINTYPE_UNKNOWN == w->window_type) {
if (w->a.override_redirect ||
- !wid_has_prop(ps, w->client_win, ps->atoms->aWM_TRANSIENT_FOR))
+ !wid_has_prop(ps, w->client_win, ps->atoms->aWM_TRANSIENT_FOR)) {
w->window_type = WINTYPE_NORMAL;
- else
+ } else {
w->window_type = WINTYPE_DIALOG;
+ }
}
if (w->window_type != wtype_old) {
@@ -1312,9 +1314,9 @@ void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client)
}
auto e = xcb_request_check(
- ps->c, xcb_change_window_attributes_checked(
- ps->c, client, XCB_CW_EVENT_MASK,
- (const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_CLIENT)}));
+ ps->c.c, xcb_change_window_attributes_checked(
+ ps->c.c, client, XCB_CW_EVENT_MASK,
+ (const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_CLIENT)}));
if (e) {
log_error("Failed to change event mask of window %#010x", client);
free(e);
@@ -1339,13 +1341,13 @@ void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client)
win_on_factor_change(ps, w);
auto r = xcb_get_window_attributes_reply(
- ps->c, xcb_get_window_attributes(ps->c, w->client_win), &e);
+ ps->c.c, xcb_get_window_attributes(ps->c.c, w->client_win), &e);
if (!r) {
log_error_x_error(e, "Failed to get client window attributes");
return;
}
- w->client_pictfmt = x_get_pictform_for_visual(ps->c, r->visual);
+ w->client_pictfmt = x_get_pictform_for_visual(&ps->c, r->visual);
free(r);
}
@@ -1364,7 +1366,7 @@ void win_unmark_client(session_t *ps, struct managed_win *w) {
// Recheck event mask
xcb_change_window_attributes(
- ps->c, client, XCB_CW_EVENT_MASK,
+ ps->c.c, client, XCB_CW_EVENT_MASK,
(const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_UNKNOWN)});
}
@@ -1377,7 +1379,7 @@ static xcb_window_t find_client_win(session_t *ps, xcb_window_t w) {
}
xcb_query_tree_reply_t *reply =
- xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, w), NULL);
+ xcb_query_tree_reply(ps->c.c, xcb_query_tree(ps->c.c, w), NULL);
if (!reply) {
return 0;
}
@@ -1451,7 +1453,7 @@ void free_win_res(session_t *ps, struct managed_win *w) {
pixman_region32_fini(&w->bounding_shape);
// BadDamage may be thrown if the window is destroyed
- set_ignore_cookie(ps, xcb_damage_destroy(ps->c, w->damage));
+ set_ignore_cookie(&ps->c, xcb_damage_destroy(ps->c.c, w->damage));
rc_region_unref(&w->reg_ignore);
free(w->name);
free(w->class_instance);
@@ -1619,9 +1621,10 @@ struct win *fill_win(session_t *ps, struct win *w) {
}
log_debug("Managing window %#010x", w->id);
- xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, w->id);
+ xcb_get_window_attributes_cookie_t acookie =
+ xcb_get_window_attributes(ps->c.c, w->id);
xcb_get_window_attributes_reply_t *a =
- xcb_get_window_attributes_reply(ps->c, acookie, NULL);
+ xcb_get_window_attributes_reply(ps->c.c, acookie, NULL);
if (!a || a->map_state == XCB_MAP_STATE_UNVIEWABLE) {
// Failed to get window attributes or geometry probably means
// the window is gone already. Unviewable means the window is
@@ -1656,7 +1659,7 @@ struct win *fill_win(session_t *ps, struct win *w) {
free(a);
xcb_generic_error_t *e;
- auto g = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, w->id), &e);
+ auto g = xcb_get_geometry_reply(ps->c.c, xcb_get_geometry(ps->c.c, w->id), &e);
if (!g) {
log_error_x_error(e, "Failed to get geometry of window %#010x", w->id);
free(e);
@@ -1674,10 +1677,10 @@ struct win *fill_win(session_t *ps, struct win *w) {
free(g);
// Create Damage for window (if not Input Only)
- new->damage = x_new_id(ps->c);
+ new->damage = x_new_id(&ps->c);
e = xcb_request_check(
- ps->c, xcb_damage_create_checked(ps->c, new->damage, w->id,
- XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
+ ps->c.c, xcb_damage_create_checked(ps->c.c, new->damage, w->id,
+ XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
if (e) {
log_error_x_error(e, "Failed to create damage");
free(e);
@@ -1687,15 +1690,15 @@ struct win *fill_win(session_t *ps, struct win *w) {
// Set window event mask
xcb_change_window_attributes(
- ps->c, new->base.id, XCB_CW_EVENT_MASK,
+ ps->c.c, new->base.id, XCB_CW_EVENT_MASK,
(const uint32_t[]){determine_evmask(ps, new->base.id, WIN_EVMODE_FRAME)});
// Get notification when the shape of a window changes
if (ps->shape_exists) {
- xcb_shape_select_input(ps->c, new->base.id, 1);
+ xcb_shape_select_input(ps->c.c, new->base.id, 1);
}
- new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual);
+ new->pictfmt = x_get_pictform_for_visual(&ps->c, new->a.visual);
new->client_pictfmt = NULL;
list_replace(&w->stack_neighbour, &new->base.stack_neighbour);
@@ -1765,12 +1768,12 @@ void win_update_leader(session_t *ps, struct managed_win *w) {
// Read the leader properties
if (ps->o.detect_transient && !leader) {
leader =
- wid_get_prop_window(ps->c, w->client_win, ps->atoms->aWM_TRANSIENT_FOR);
+ wid_get_prop_window(&ps->c, w->client_win, ps->atoms->aWM_TRANSIENT_FOR);
}
if (ps->o.detect_client_leader && !leader) {
leader =
- wid_get_prop_window(ps->c, w->client_win, ps->atoms->aWM_CLIENT_LEADER);
+ wid_get_prop_window(&ps->c, w->client_win, ps->atoms->aWM_CLIENT_LEADER);
}
win_set_leader(ps, w, leader);
@@ -1786,8 +1789,9 @@ static xcb_window_t win_get_leader_raw(session_t *ps, struct managed_win *w, int
// Rebuild the cache if needed
if (!w->cache_leader && (w->client_win || w->leader)) {
// Leader defaults to client window
- if (!(w->cache_leader = w->leader))
+ if (!(w->cache_leader = w->leader)) {
w->cache_leader = w->client_win;
+ }
// If the leader of this window isn't itself, look for its
// ancestors
@@ -1795,8 +1799,9 @@ static xcb_window_t win_get_leader_raw(session_t *ps, struct managed_win *w, int
auto wp = find_toplevel(ps, w->cache_leader);
if (wp) {
// Dead loop?
- if (recursions > WIN_GET_LEADER_MAX_RECURSION)
+ if (recursions > WIN_GET_LEADER_MAX_RECURSION) {
return XCB_NONE;
+ }
w->cache_leader = win_get_leader_raw(ps, wp, recursions + 1);
}
@@ -1815,8 +1820,9 @@ bool win_update_class(session_t *ps, struct managed_win *w) {
int nstr = 0;
// Can't do anything if there's no client window
- if (!w->client_win)
+ if (!w->client_win) {
return false;
+ }
// Free and reset old strings
free(w->class_instance);
@@ -1956,8 +1962,9 @@ void win_update_bounding_shape(session_t *ps, struct managed_win *w) {
*/
xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(
- ps->c,
- xcb_shape_get_rectangles(ps->c, w->base.id, XCB_SHAPE_SK_BOUNDING), NULL);
+ ps->c.c,
+ xcb_shape_get_rectangles(ps->c.c, w->base.id, XCB_SHAPE_SK_BOUNDING),
+ NULL);
if (!r) {
break;
@@ -2030,7 +2037,7 @@ void win_update_opacity_prop(session_t *ps, struct managed_win *w) {
* Retrieve frame extents from a window.
*/
void win_update_frame_extents(session_t *ps, struct managed_win *w, xcb_window_t client) {
- winprop_t prop = x_get_prop(ps->c, client, ps->atoms->a_NET_FRAME_EXTENTS, 4L,
+ winprop_t prop = x_get_prop(&ps->c, client, ps->atoms->a_NET_FRAME_EXTENTS, 4L,
XCB_ATOM_CARDINAL, 32);
if (prop.nitems == 4) {
@@ -2085,7 +2092,7 @@ bool win_is_region_ignore_valid(session_t *ps, const struct managed_win *w) {
* Stop listening for events on a particular window.
*/
void win_ev_stop(session_t *ps, const struct win *w) {
- xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]){0});
+ xcb_change_window_attributes(ps->c.c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]){0});
if (!w->managed) {
return;
@@ -2093,12 +2100,12 @@ void win_ev_stop(session_t *ps, const struct win *w) {
auto mw = (struct managed_win *)w;
if (mw->client_win) {
- xcb_change_window_attributes(ps->c, mw->client_win, XCB_CW_EVENT_MASK,
+ xcb_change_window_attributes(ps->c.c, mw->client_win, XCB_CW_EVENT_MASK,
(const uint32_t[]){0});
}
if (ps->shape_exists) {
- xcb_shape_select_input(ps->c, w->id, 0);
+ xcb_shape_select_input(ps->c.c, w->id, 0);
}
}
@@ -2449,10 +2456,10 @@ bool win_skip_fading(session_t *ps, struct managed_win *w) {
// TODO(absolutelynothelix): rename to x_update_win_(randr_?)monitor and move to
// the x.c.
-void win_update_monitor(int nmons, region_t *mons, struct managed_win *mw) {
+void win_update_monitor(struct x_monitors *monitors, struct managed_win *mw) {
mw->randr_monitor = -1;
- for (int i = 0; i < nmons; i++) {
- auto e = pixman_region32_extents(&mons[i]);
+ for (int i = 0; i < monitors->count; i++) {
+ auto e = pixman_region32_extents(&monitors->regions[i]);
if (e->x1 <= mw->g.x && e->y1 <= mw->g.y &&
e->x2 >= mw->g.x + mw->widthb && e->y2 >= mw->g.y + mw->heightb) {
mw->randr_monitor = i;
@@ -2670,11 +2677,12 @@ struct managed_win *find_managed_window_or_parent(session_t *ps, xcb_window_t wi
// We traverse through its ancestors to find out the frame
// Using find_win here because if we found a unmanaged window we know
// about, we can stop early.
- while (wid && wid != ps->root && !(w = find_win(ps, wid))) {
+ while (wid && wid != ps->c.screen_info->root && !(w = find_win(ps, wid))) {
// xcb_query_tree probably fails if you run picom when X is
// somehow initializing (like add it in .xinitrc). In this case
// just leave it alone.
- auto reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL);
+ auto reply =
+ xcb_query_tree_reply(ps->c.c, xcb_query_tree(ps->c.c, wid), NULL);
if (reply == NULL) {
break;
}
@@ -2811,7 +2819,7 @@ bool win_check_flags_all(struct managed_win *w, uint64_t flags) {
*/
bool win_is_fullscreen(const session_t *ps, const struct managed_win *w) {
if (!ps->o.no_ewmh_fullscreen &&
- win_is_fullscreen_xcb(ps->c, ps->atoms, w->client_win)) {
+ win_is_fullscreen_xcb(ps->c.c, ps->atoms, w->client_win)) {
return true;
}
return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb) &&
@@ -2826,7 +2834,7 @@ bool win_is_fullscreen(const session_t *ps, const struct managed_win *w) {
bool win_is_bypassing_compositor(const session_t *ps, const struct managed_win *w) {
bool ret = false;
- auto prop = x_get_prop(ps->c, w->client_win, ps->atoms->a_NET_WM_BYPASS_COMPOSITOR,
+ auto prop = x_get_prop(&ps->c, w->client_win, ps->atoms->a_NET_WM_BYPASS_COMPOSITOR,
1L, XCB_ATOM_CARDINAL, 32);
if (prop.nitems && *prop.c32 == 1) {
@@ -2847,13 +2855,13 @@ bool win_is_focused_raw(const session_t *ps, const struct managed_win *w) {
// Find the managed window immediately below `i` in the window stack
struct managed_win *
-win_stack_find_next_managed(const session_t *ps, const struct list_node *i) {
- while (!list_node_is_last(&ps->window_stack, i)) {
- auto next = list_entry(i->next, struct win, stack_neighbour);
+win_stack_find_next_managed(const session_t *ps, const struct list_node *w) {
+ while (!list_node_is_last(&ps->window_stack, w)) {
+ auto next = list_entry(w->next, struct win, stack_neighbour);
if (next->managed) {
return (struct managed_win *)next;
}
- i = &next->stack_neighbour;
+ w = &next->stack_neighbour;
}
return NULL;
}
diff --git a/src/win.h b/src/win.h
index da46572b73..b841ffc177 100644
--- a/src/win.h
+++ b/src/win.h
@@ -341,9 +341,7 @@ void win_recheck_client(session_t *ps, struct managed_win *w);
double attr_pure win_calc_opacity_target(session_t *ps, const struct managed_win *w);
bool attr_pure win_should_dim(session_t *ps, const struct managed_win *w);
-// TODO(absolutelynothelix): rename to x_update_win_(randr_?)monitor and move to
-// the x.h.
-void win_update_monitor(int nmons, region_t *mons, struct managed_win *mw);
+void win_update_monitor(struct x_monitors *monitors, struct managed_win *mw);
/**
* Retrieve the bounding shape of a window.
diff --git a/src/x.c b/src/x.c
index a2a7153d74..1840ebb1fe 100644
--- a/src/x.c
+++ b/src/x.c
@@ -4,6 +4,7 @@
#include
#include
+#include
#include
#include
#include
@@ -28,6 +29,72 @@
#include "utils.h"
#include "x.h"
+// === Error handling ===
+
+/**
+ * Xlib error handler function.
+ */
+static int xerror(Display attr_unused *dpy, XErrorEvent *ev) {
+ if (!ps_g) {
+ // Do not ignore errors until the session has been initialized
+ return 0;
+ }
+
+ // Fake a xcb error, fill in just enough information
+ xcb_generic_error_t xcb_err;
+ xcb_err.full_sequence = (uint32_t)ev->serial;
+ xcb_err.major_code = ev->request_code;
+ xcb_err.minor_code = ev->minor_code;
+ xcb_err.error_code = ev->error_code;
+ x_handle_error(&ps_g->c, &xcb_err);
+ return 0;
+}
+
+void x_discard_pending(struct x_connection *c, uint32_t sequence) {
+ while (c->pending_reply_head && sequence > c->pending_reply_head->sequence) {
+ auto next = c->pending_reply_head->next;
+ free(c->pending_reply_head);
+ c->pending_reply_head = next;
+ }
+ if (!c->pending_reply_head) {
+ c->pending_reply_tail = &c->pending_reply_head;
+ }
+}
+
+void x_handle_error(struct x_connection *c, xcb_generic_error_t *ev) {
+ x_discard_pending(c, ev->full_sequence);
+ if (c->pending_reply_head && c->pending_reply_head->sequence == ev->full_sequence) {
+ if (c->pending_reply_head->action != PENDING_REPLY_ACTION_IGNORE) {
+ x_log_error(LOG_LEVEL_ERROR, ev->full_sequence, ev->major_code,
+ ev->minor_code, ev->error_code);
+ }
+ switch (c->pending_reply_head->action) {
+ case PENDING_REPLY_ACTION_ABORT:
+ log_fatal("An unrecoverable X error occurred, aborting...");
+ abort();
+ case PENDING_REPLY_ACTION_DEBUG_ABORT: assert(false); break;
+ case PENDING_REPLY_ACTION_IGNORE: break;
+ }
+ return;
+ }
+ x_log_error(LOG_LEVEL_WARN, ev->full_sequence, ev->major_code, ev->minor_code,
+ ev->error_code);
+}
+
+/// Initialize x_connection struct from an Xlib Display.
+///
+/// Note this function doesn't take ownership of the Display, the caller is still
+/// responsible for closing it after `free_x_connection` is called.
+void x_connection_init(struct x_connection *c, Display *dpy) {
+ c->dpy = dpy;
+ c->c = XGetXCBConnection(dpy);
+ c->pending_reply_tail = &c->pending_reply_head;
+ c->previous_xerror_handler = XSetErrorHandler(xerror);
+
+ c->screen = DefaultScreen(dpy);
+ c->screen_info = x_screen_of_display(c, c->screen);
+}
+
/**
* Get a specific attribute of a window.
*
@@ -43,11 +110,11 @@
* @return a winprop_t
structure containing the attribute
* and number of items. A blank one on failure.
*/
-winprop_t x_get_prop_with_offset(xcb_connection_t *c, xcb_window_t w, xcb_atom_t atom,
+winprop_t x_get_prop_with_offset(const struct x_connection *c, xcb_window_t w, xcb_atom_t atom,
int offset, int length, xcb_atom_t rtype, int rformat) {
xcb_get_property_reply_t *r = xcb_get_property_reply(
- c,
- xcb_get_property(c, 0, w, atom, rtype, to_u32_checked(offset),
+ c->c,
+ xcb_get_property(c->c, 0, w, atom, rtype, to_u32_checked(offset),
to_u32_checked(length)),
NULL);
@@ -71,10 +138,10 @@ winprop_t x_get_prop_with_offset(xcb_connection_t *c, xcb_window_t w, xcb_atom_t
}
/// Get the type, format and size in bytes of a window's specific attribute.
-winprop_info_t x_get_prop_info(xcb_connection_t *c, xcb_window_t w, xcb_atom_t atom) {
+winprop_info_t x_get_prop_info(const struct x_connection *c, xcb_window_t w, xcb_atom_t atom) {
xcb_generic_error_t *e = NULL;
auto r = xcb_get_property_reply(
- c, xcb_get_property(c, 0, w, atom, XCB_ATOM_ANY, 0, 0), &e);
+ c->c, xcb_get_property(c->c, 0, w, atom, XCB_ATOM_ANY, 0, 0), &e);
if (!r) {
log_debug_x_error(e, "Failed to get property info for window %#010x", w);
free(e);
@@ -94,7 +161,7 @@ winprop_info_t x_get_prop_info(xcb_connection_t *c, xcb_window_t w, xcb_atom_t a
*
* @return the value if successful, 0 otherwise
*/
-xcb_window_t wid_get_prop_window(xcb_connection_t *c, xcb_window_t wid, xcb_atom_t aprop) {
+xcb_window_t wid_get_prop_window(struct x_connection *c, xcb_window_t wid, xcb_atom_t aprop) {
// Get the attribute
xcb_window_t p = XCB_NONE;
winprop_t prop = x_get_prop(c, wid, aprop, 1L, XCB_ATOM_WINDOW, 32);
@@ -115,7 +182,7 @@ xcb_window_t wid_get_prop_window(xcb_connection_t *c, xcb_window_t wid, xcb_atom
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
int *pnstr) {
assert(ps->server_grabbed);
- auto prop_info = x_get_prop_info(ps->c, wid, prop);
+ auto prop_info = x_get_prop_info(&ps->c, wid, prop);
auto type = prop_info.type;
auto format = prop_info.format;
auto length = prop_info.length;
@@ -140,7 +207,7 @@ bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char **
xcb_generic_error_t *e = NULL;
auto word_count = (length + 4 - 1) / 4;
auto r = xcb_get_property_reply(
- ps->c, xcb_get_property(ps->c, 0, wid, prop, type, 0, word_count), &e);
+ ps->c.c, xcb_get_property(ps->c.c, 0, wid, prop, type, 0, word_count), &e);
if (!r) {
log_debug_x_error(e, "Failed to get window property for %#010x", wid);
free(e);
@@ -198,14 +265,14 @@ bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char **
// of this program
static thread_local xcb_render_query_pict_formats_reply_t *g_pictfmts = NULL;
-static inline void x_get_server_pictfmts(xcb_connection_t *c) {
+static inline void x_get_server_pictfmts(struct x_connection *c) {
if (g_pictfmts) {
return;
}
xcb_generic_error_t *e = NULL;
// Get window picture format
- g_pictfmts =
- xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats(c), &e);
+ g_pictfmts = xcb_render_query_pict_formats_reply(
+ c->c, xcb_render_query_pict_formats(c->c), &e);
if (e || !g_pictfmts) {
log_fatal("failed to get pict formats\n");
abort();
@@ -213,7 +280,7 @@ static inline void x_get_server_pictfmts(xcb_connection_t *c) {
}
const xcb_render_pictforminfo_t *
-x_get_pictform_for_visual(xcb_connection_t *c, xcb_visualid_t visual) {
+x_get_pictform_for_visual(struct x_connection *c, xcb_visualid_t visual) {
x_get_server_pictfmts(c);
xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual);
@@ -244,7 +311,7 @@ static xcb_visualid_t attr_pure x_get_visual_for_pictfmt(xcb_render_query_pict_f
return XCB_NONE;
}
-xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) {
+xcb_visualid_t x_get_visual_for_standard(struct x_connection *c, xcb_pict_standard_t std) {
x_get_server_pictfmts(c);
auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, std);
@@ -253,7 +320,7 @@ xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_
}
xcb_render_pictformat_t
-x_get_pictfmt_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) {
+x_get_pictfmt_for_standard(struct x_connection *c, xcb_pict_standard_t std) {
x_get_server_pictfmts(c);
auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, std);
@@ -261,8 +328,8 @@ x_get_pictfmt_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) {
return pictfmt->id;
}
-int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
- auto setup = xcb_get_setup(c);
+int x_get_visual_depth(struct x_connection *c, xcb_visualid_t visual) {
+ auto setup = xcb_get_setup(c->c);
for (auto screen = xcb_setup_roots_iterator(setup); screen.rem;
xcb_screen_next(&screen)) {
for (auto depth = xcb_screen_allowed_depths_iterator(screen.data);
@@ -280,7 +347,7 @@ int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
}
xcb_render_picture_t
-x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
+x_create_picture_with_pictfmt_and_pixmap(struct x_connection *c,
const xcb_render_pictforminfo_t *pictfmt,
xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) {
@@ -294,9 +361,9 @@ x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
}
xcb_render_picture_t tmp_picture = x_new_id(c);
- xcb_generic_error_t *e =
- xcb_request_check(c, xcb_render_create_picture_checked(
- c, tmp_picture, pixmap, pictfmt->id, valuemask, buf));
+ xcb_generic_error_t *e = xcb_request_check(
+ c->c, xcb_render_create_picture_checked(c->c, tmp_picture, pixmap,
+ pictfmt->id, valuemask, buf));
free(buf);
if (e) {
log_error_x_error(e, "failed to create picture");
@@ -307,7 +374,7 @@ x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
}
xcb_render_picture_t
-x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual,
+x_create_picture_with_visual_and_pixmap(struct x_connection *c, xcb_visualid_t visual,
xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) {
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
@@ -315,7 +382,7 @@ x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visu
}
xcb_render_picture_t
-x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard,
+x_create_picture_with_standard_and_pixmap(struct x_connection *c, xcb_pict_standard_t standard,
xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) {
x_get_server_pictfmts(c);
@@ -326,26 +393,26 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard
}
xcb_render_picture_t
-x_create_picture_with_standard(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
+x_create_picture_with_standard(struct x_connection *c, int w, int h,
xcb_pict_standard_t standard, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) {
x_get_server_pictfmts(c);
auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, standard);
assert(pictfmt);
- return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
+ return x_create_picture_with_pictfmt(c, w, h, pictfmt, valuemask, attr);
}
/**
* Create an picture.
*/
xcb_render_picture_t
-x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
+x_create_picture_with_pictfmt(struct x_connection *c, int w, int h,
const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) {
uint8_t depth = pictfmt->depth;
- xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, w, h);
+ xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, w, h);
if (!tmp_pixmap) {
return XCB_NONE;
}
@@ -353,23 +420,23 @@ x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int w, int
xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap(
c, pictfmt, tmp_pixmap, valuemask, attr);
- xcb_free_pixmap(c, tmp_pixmap);
+ set_cant_fail_cookie(c, xcb_free_pixmap(c->c, tmp_pixmap));
return picture;
}
xcb_render_picture_t
-x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
- xcb_visualid_t visual, uint32_t valuemask,
+x_create_picture_with_visual(struct x_connection *c, int w, int h, xcb_visualid_t visual,
+ uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) {
auto pictfmt = x_get_pictform_for_visual(c, visual);
- return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
+ return x_create_picture_with_pictfmt(c, w, h, pictfmt, valuemask, attr);
}
-bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_t *res) {
+bool x_fetch_region(struct x_connection *c, xcb_xfixes_region_t r, pixman_region32_t *res) {
xcb_generic_error_t *e = NULL;
xcb_xfixes_fetch_region_reply_t *xr =
- xcb_xfixes_fetch_region_reply(c, xcb_xfixes_fetch_region(c, r), &e);
+ xcb_xfixes_fetch_region_reply(c->c, xcb_xfixes_fetch_region(c->c, r), &e);
if (!xr) {
log_error_x_error(e, "Failed to fetch rectangles");
return false;
@@ -390,7 +457,7 @@ bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_
return ret;
}
-uint32_t x_create_region(xcb_connection_t *c, const region_t *reg) {
+uint32_t x_create_region(struct x_connection *c, const region_t *reg) {
if (!reg) {
return XCB_NONE;
}
@@ -410,8 +477,8 @@ uint32_t x_create_region(xcb_connection_t *c, const region_t *reg) {
}
xcb_xfixes_region_t ret = x_new_id(c);
- bool success =
- XCB_AWAIT_VOID(xcb_xfixes_create_region, c, ret, to_u32_checked(nrects), xrects);
+ bool success = XCB_AWAIT_VOID(xcb_xfixes_create_region, c->c, ret,
+ to_u32_checked(nrects), xrects);
free(xrects);
if (!success) {
return XCB_NONE;
@@ -419,13 +486,13 @@ uint32_t x_create_region(xcb_connection_t *c, const region_t *reg) {
return ret;
}
-void x_destroy_region(xcb_connection_t *c, xcb_xfixes_region_t r) {
+void x_destroy_region(struct x_connection *c, xcb_xfixes_region_t r) {
if (r != XCB_NONE) {
- xcb_xfixes_destroy_region(c, r);
+ set_debug_cant_fail_cookie(c, xcb_xfixes_destroy_region(c->c, r));
}
}
-void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
+void x_set_picture_clip_region(struct x_connection *c, xcb_render_picture_t pict,
int16_t clip_x_origin, int16_t clip_y_origin,
const region_t *reg) {
int nrects;
@@ -440,9 +507,10 @@ void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
};
}
- xcb_generic_error_t *e = xcb_request_check(
- c, xcb_render_set_picture_clip_rectangles_checked(
- c, pict, clip_x_origin, clip_y_origin, to_u32_checked(nrects), xrects));
+ xcb_generic_error_t *e =
+ xcb_request_check(c->c, xcb_render_set_picture_clip_rectangles_checked(
+ c->c, pict, clip_x_origin, clip_y_origin,
+ to_u32_checked(nrects), xrects));
if (e) {
log_error_x_error(e, "Failed to set clip region");
free(e);
@@ -450,17 +518,28 @@ void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
free(xrects);
}
-void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict) {
+void x_clear_picture_clip_region(struct x_connection *c, xcb_render_picture_t pict) {
assert(pict != XCB_NONE);
xcb_render_change_picture_value_list_t v = {.clipmask = XCB_NONE};
xcb_generic_error_t *e = xcb_request_check(
- c, xcb_render_change_picture_checked(c, pict, XCB_RENDER_CP_CLIP_MASK, &v));
+ c->c, xcb_render_change_picture_checked(c->c, pict, XCB_RENDER_CP_CLIP_MASK, &v));
if (e) {
log_error_x_error(e, "failed to clear clip region");
free(e);
}
}
+/**
+ * Destroy a Picture
.
+ *
+ * Picture must be valid.
+ */
+void x_free_picture(struct x_connection *c, xcb_render_picture_t p) {
+ assert(p != XCB_NONE);
+ auto cookie = xcb_render_free_picture(c->c, p);
+ set_debug_cant_fail_cookie(c, cookie);
+}
+
enum {
XSyncBadCounter = 0,
XSyncBadAlarm = 1,
@@ -593,12 +672,12 @@ const char *x_strerror(xcb_generic_error_t *e) {
/**
* Create a pixmap and check that creation succeeded.
*/
-xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable,
- int width, int height) {
+xcb_pixmap_t x_create_pixmap(struct x_connection *c, uint8_t depth, int width, int height) {
xcb_pixmap_t pix = x_new_id(c);
- xcb_void_cookie_t cookie = xcb_create_pixmap_checked(
- c, depth, pix, drawable, to_u16_checked(width), to_u16_checked(height));
- xcb_generic_error_t *err = xcb_request_check(c, cookie);
+ xcb_void_cookie_t cookie =
+ xcb_create_pixmap_checked(c->c, depth, pix, c->screen_info->root,
+ to_u16_checked(width), to_u16_checked(height));
+ xcb_generic_error_t *err = xcb_request_check(c->c, cookie);
if (err == NULL) {
return pix;
}
@@ -614,12 +693,12 @@ xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t
* Detect whether the pixmap is valid with XGetGeometry. Well, maybe there
* are better ways.
*/
-bool x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) {
+bool x_validate_pixmap(struct x_connection *c, xcb_pixmap_t pixmap) {
if (pixmap == XCB_NONE) {
return false;
}
- auto r = xcb_get_geometry_reply(c, xcb_get_geometry(c, pixmap), NULL);
+ auto r = xcb_get_geometry_reply(c->c, xcb_get_geometry(c->c, pixmap), NULL);
if (!r) {
return false;
}
@@ -641,14 +720,14 @@ bool x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) {
/// https://github.com/ImageMagick/ImageMagick/blob/d04a47227637dbb3af9231b0107ccf9677bf985e/MagickCore/xwindow.c#L1853-L1922
/// https://www.fvwm.org/Archive/Manpages/fvwm-root.html
-xcb_pixmap_t
-x_get_root_back_pixmap(xcb_connection_t *c, xcb_window_t root, struct atom *atoms) {
+xcb_pixmap_t x_get_root_back_pixmap(struct x_connection *c, struct atom *atoms) {
xcb_pixmap_t pixmap = XCB_NONE;
xcb_atom_t root_back_pixmap_atoms[] = {atoms->a_XROOTPMAP_ID, atoms->aESETROOT_PMAP_ID};
for (size_t i = 0; i < ARR_SIZE(root_back_pixmap_atoms); i++) {
winprop_t prop =
- x_get_prop(c, root, root_back_pixmap_atoms[i], 1, XCB_ATOM_PIXMAP, 32);
+ x_get_prop(c, c->screen_info->root, root_back_pixmap_atoms[i], 1,
+ XCB_ATOM_PIXMAP, 32);
if (prop.nitems) {
pixmap = (xcb_pixmap_t)*prop.p32;
free_winprop(&prop);
@@ -669,24 +748,24 @@ bool x_is_root_back_pixmap_atom(struct atom *atoms, xcb_atom_t atom) {
* Synchronizes a X Render drawable to ensure all pending painting requests
* are completed.
*/
-bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) {
+bool x_fence_sync(struct x_connection *c, xcb_sync_fence_t f) {
// TODO(richardgv): If everybody just follows the rules stated in X Sync
// prototype, we need only one fence per screen, but let's stay a bit
// cautious right now
- auto e = xcb_request_check(c, xcb_sync_trigger_fence_checked(c, f));
+ auto e = xcb_request_check(c->c, xcb_sync_trigger_fence_checked(c->c, f));
if (e) {
log_error_x_error(e, "Failed to trigger the fence");
goto err;
}
- e = xcb_request_check(c, xcb_sync_await_fence_checked(c, 1, &f));
+ e = xcb_request_check(c->c, xcb_sync_await_fence_checked(c->c, 1, &f));
if (e) {
log_error_x_error(e, "Failed to await on a fence");
goto err;
}
- e = xcb_request_check(c, xcb_sync_reset_fence_checked(c, f));
+ e = xcb_request_check(c->c, xcb_sync_reset_fence_checked(c->c, f));
if (e) {
log_error_x_error(e, "Failed to reset the fence");
goto err;
@@ -748,7 +827,7 @@ void x_create_convolution_kernel(const conv *kernel, double center,
/// Generate a search criteria for fbconfig from a X visual.
/// Returns {-1, -1, -1, -1, -1, 0} on failure
-struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
+struct xvisual_info x_get_visual_info(struct x_connection *c, xcb_visualid_t visual) {
auto pictfmt = x_get_pictform_for_visual(c, visual);
auto depth = x_get_visual_depth(c, visual);
if (!pictfmt || depth == -1) {
@@ -776,10 +855,10 @@ struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual
};
}
-xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) {
+xcb_screen_t *x_screen_of_display(struct x_connection *c, int screen) {
xcb_screen_iterator_t iter;
- iter = xcb_setup_roots_iterator(xcb_get_setup(c));
+ iter = xcb_setup_roots_iterator(xcb_get_setup(c->c));
for (; iter.rem; --screen, xcb_screen_next(&iter)) {
if (screen == 0) {
return iter.data;
@@ -789,39 +868,34 @@ xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) {
return NULL;
}
-void x_update_randr_monitors(session_t *ps) {
- x_free_randr_info(ps);
-
- if (!ps->o.crop_shadow_to_monitor || !ps->randr_exists) {
- return;
- }
+void x_update_monitors(struct x_connection *c, struct x_monitors *m) {
+ x_free_monitor_info(m);
xcb_randr_get_monitors_reply_t *r = xcb_randr_get_monitors_reply(
- ps->c, xcb_randr_get_monitors(ps->c, ps->root, true), NULL);
+ c->c, xcb_randr_get_monitors(c->c, c->screen_info->root, true), NULL);
if (!r) {
return;
}
- ps->randr_nmonitors = xcb_randr_get_monitors_monitors_length(r);
- ps->randr_monitor_regs = ccalloc(ps->randr_nmonitors, region_t);
+ m->count = xcb_randr_get_monitors_monitors_length(r);
+ m->regions = ccalloc(m->count, region_t);
xcb_randr_monitor_info_iterator_t monitor_info_it =
xcb_randr_get_monitors_monitors_iterator(r);
for (int i = 0; monitor_info_it.rem; xcb_randr_monitor_info_next(&monitor_info_it)) {
xcb_randr_monitor_info_t *mi = monitor_info_it.data;
- pixman_region32_init_rect(&ps->randr_monitor_regs[i++], mi->x, mi->y,
- mi->width, mi->height);
+ pixman_region32_init_rect(&m->regions[i++], mi->x, mi->y, mi->width, mi->height);
}
free(r);
}
-void x_free_randr_info(session_t *ps) {
- if (ps->randr_monitor_regs) {
- for (int i = 0; i < ps->randr_nmonitors; i++) {
- pixman_region32_fini(&ps->randr_monitor_regs[i]);
+void x_free_monitor_info(struct x_monitors *m) {
+ if (m->regions) {
+ for (int i = 0; i < m->count; i++) {
+ pixman_region32_fini(&m->regions[i]);
}
- free(ps->randr_monitor_regs);
- ps->randr_monitor_regs = NULL;
+ free(m->regions);
+ m->regions = NULL;
}
- ps->randr_nmonitors = 0;
+ m->count = 0;
}
diff --git a/src/x.h b/src/x.h
index fc105c7857..b5bd1a59d3 100644
--- a/src/x.h
+++ b/src/x.h
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2018 Yuxuan Shui
#pragma once
+#include
#include
#include
#include
@@ -55,6 +56,42 @@ struct xvisual_info {
xcb_visualid_t visual;
};
+enum pending_reply_action {
+ PENDING_REPLY_ACTION_IGNORE,
+ PENDING_REPLY_ACTION_ABORT,
+ PENDING_REPLY_ACTION_DEBUG_ABORT,
+};
+
+typedef struct pending_reply {
+ struct pending_reply *next;
+ unsigned long sequence;
+ enum pending_reply_action action;
+} pending_reply_t;
+
+struct x_connection {
+ /// XCB connection.
+ xcb_connection_t *c;
+ /// Display in use.
+ Display *dpy;
+ /// Head pointer of the error ignore linked list.
+ pending_reply_t *pending_reply_head;
+ /// Pointer to the next
member of tail element of the error
+ /// ignore linked list.
+ pending_reply_t **pending_reply_tail;
+ /// Previous handler of X errors
+ XErrorHandler previous_xerror_handler;
+ /// Default screen
+ int screen;
+ /// Information about the default screen
+ xcb_screen_t *screen_info;
+};
+
+/// Monitor info
+struct x_monitors {
+ int count;
+ region_t *regions;
+};
+
#define XCB_AWAIT_VOID(func, c, ...) \
({ \
bool __success = true; \
@@ -92,8 +129,8 @@ struct xvisual_info {
#define DOUBLE_TO_XFIXED(value) ((xcb_render_fixed_t)(((double)(value)) * 65536))
/// Wraps x_new_id. abort the program if x_new_id returns error
-static inline uint32_t x_new_id(xcb_connection_t *c) {
- auto ret = xcb_generate_id(c);
+static inline uint32_t x_new_id(struct x_connection *c) {
+ auto ret = xcb_generate_id(c->c);
if (ret == (uint32_t)-1) {
log_fatal("We seems to have run of XIDs. This is either a bug in the X "
"server, or a resource leakage in the compositor. Please open "
@@ -103,6 +140,73 @@ static inline uint32_t x_new_id(xcb_connection_t *c) {
return ret;
}
+static void set_reply_action(struct x_connection *c, uint32_t sequence,
+ enum pending_reply_action action) {
+ auto i = cmalloc(pending_reply_t);
+
+ i->sequence = sequence;
+ i->next = 0;
+ i->action = action;
+ *c->pending_reply_tail = i;
+ c->pending_reply_tail = &i->next;
+}
+
+/**
+ * Ignore X errors caused by given X request.
+ */
+static inline void attr_unused set_ignore_cookie(struct x_connection *c,
+ xcb_void_cookie_t cookie) {
+ set_reply_action(c, cookie.sequence, PENDING_REPLY_ACTION_IGNORE);
+}
+
+static inline void attr_unused set_cant_fail_cookie(struct x_connection *c,
+ xcb_void_cookie_t cookie) {
+ set_reply_action(c, cookie.sequence, PENDING_REPLY_ACTION_ABORT);
+}
+
+static inline void attr_unused set_debug_cant_fail_cookie(struct x_connection *c,
+ xcb_void_cookie_t cookie) {
+#ifndef NDEBUG
+ set_reply_action(c, cookie.sequence, PENDING_REPLY_ACTION_DEBUG_ABORT);
+#else
+ (void)c;
+ (void)cookie;
+#endif
+}
+
+static inline void attr_unused free_x_connection(struct x_connection *c) {
+ pending_reply_t *next = NULL;
+ for (auto ign = c->pending_reply_head; ign; ign = next) {
+ next = ign->next;
+
+ free(ign);
+ }
+
+ // Reset head and tail
+ c->pending_reply_head = NULL;
+ c->pending_reply_tail = &c->pending_reply_head;
+
+ XSetErrorHandler(c->previous_xerror_handler);
+}
+
+/// Initialize x_connection struct from an Xlib Display.
+///
+/// Note this function doesn't take ownership of the Display, the caller is still
+/// responsible for closing it after `free_x_connection` is called.
+void x_connection_init(struct x_connection *c, Display *dpy);
+
+/// Discard queued pending replies.
+///
+/// We have received reply with sequence number `sequence`, which means all pending
+/// replies with sequence number less than `sequence` will never be received. So discard
+/// them.
+void x_discard_pending(struct x_connection *c, uint32_t sequence);
+
+/// Handle X errors.
+///
+/// This function logs X errors, or aborts the program based on severity of the error.
+void x_handle_error(struct x_connection *c, xcb_generic_error_t *ev);
+
/**
* Send a request to X server and get the reply to make sure all previous
* requests are processed, and their replies received
@@ -110,8 +214,8 @@ static inline uint32_t x_new_id(xcb_connection_t *c) {
* 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));
+static inline void x_sync(struct x_connection *c) {
+ free(xcb_get_input_focus_reply(c->c, xcb_get_input_focus(c->c), NULL));
}
/**
@@ -129,25 +233,26 @@ static inline void x_sync(xcb_connection_t *c) {
* @return a winprop_t
structure containing the attribute
* and number of items. A blank one on failure.
*/
-winprop_t x_get_prop_with_offset(xcb_connection_t *c, xcb_window_t w, xcb_atom_t atom,
+winprop_t x_get_prop_with_offset(const struct x_connection *c, xcb_window_t w, xcb_atom_t atom,
int offset, int length, xcb_atom_t rtype, int rformat);
/**
* Wrapper of wid_get_prop_adv().
*/
-static inline winprop_t x_get_prop(xcb_connection_t *c, xcb_window_t wid, xcb_atom_t atom,
- int length, xcb_atom_t rtype, int rformat) {
+static inline winprop_t
+x_get_prop(const struct x_connection *c, xcb_window_t wid, xcb_atom_t atom, int length,
+ xcb_atom_t rtype, int rformat) {
return x_get_prop_with_offset(c, wid, atom, 0L, length, rtype, rformat);
}
/// Get the type, format and size in bytes of a window's specific attribute.
-winprop_info_t x_get_prop_info(xcb_connection_t *c, xcb_window_t w, xcb_atom_t atom);
+winprop_info_t x_get_prop_info(const struct x_connection *c, xcb_window_t w, xcb_atom_t atom);
/// Discard all X events in queue or in flight. Should only be used when the server is
/// grabbed
-static inline void x_discard_events(xcb_connection_t *c) {
+static inline void x_discard_events(struct x_connection *c) {
xcb_generic_event_t *e;
- while ((e = xcb_poll_for_event(c))) {
+ while ((e = xcb_poll_for_event(c->c))) {
free(e);
}
}
@@ -157,7 +262,7 @@ static inline void x_discard_events(xcb_connection_t *c) {
*
* @return the value if successful, 0 otherwise
*/
-xcb_window_t wid_get_prop_window(xcb_connection_t *c, xcb_window_t wid, xcb_atom_t aprop);
+xcb_window_t wid_get_prop_window(struct x_connection *c, xcb_window_t wid, xcb_atom_t aprop);
/**
* Get the value of a text property of a window.
@@ -170,30 +275,30 @@ bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char **
int *pnstr);
const xcb_render_pictforminfo_t *
-x_get_pictform_for_visual(xcb_connection_t *, xcb_visualid_t);
-int x_get_visual_depth(xcb_connection_t *, xcb_visualid_t);
+x_get_pictform_for_visual(struct x_connection *, xcb_visualid_t);
+int x_get_visual_depth(struct x_connection *, xcb_visualid_t);
xcb_render_picture_t
-x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *,
+x_create_picture_with_pictfmt_and_pixmap(struct x_connection *,
const xcb_render_pictforminfo_t *pictfmt,
xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1, 2);
xcb_render_picture_t
-x_create_picture_with_visual_and_pixmap(xcb_connection_t *, xcb_visualid_t visual,
+x_create_picture_with_visual_and_pixmap(struct x_connection *, xcb_visualid_t visual,
xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1);
xcb_render_picture_t
-x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_t standard,
+x_create_picture_with_standard_and_pixmap(struct x_connection *, xcb_pict_standard_t standard,
xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1);
xcb_render_picture_t
-x_create_picture_with_standard(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
+x_create_picture_with_standard(struct x_connection *c, int w, int h,
xcb_pict_standard_t standard, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1);
@@ -202,30 +307,37 @@ x_create_picture_with_standard(xcb_connection_t *c, xcb_drawable_t d, int w, int
* Create an picture.
*/
xcb_render_picture_t
-x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int w, int h,
+x_create_picture_with_pictfmt(struct x_connection *, int w, int h,
const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr)
- attr_nonnull(1, 5);
+ attr_nonnull(1, 4);
xcb_render_picture_t
-x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h,
- xcb_visualid_t visual, uint32_t valuemask,
+x_create_picture_with_visual(struct x_connection *, int w, int h, xcb_visualid_t visual,
+ uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1);
/// Fetch a X region and store it in a pixman region
-bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res);
+bool x_fetch_region(struct x_connection *, xcb_xfixes_region_t r, region_t *res);
/// Create a X region from a pixman region
-uint32_t x_create_region(xcb_connection_t *c, const region_t *reg);
+uint32_t x_create_region(struct x_connection *c, const region_t *reg);
/// Destroy a X region
-void x_destroy_region(xcb_connection_t *c, uint32_t region);
+void x_destroy_region(struct x_connection *c, uint32_t region);
-void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t, int16_t clip_x_origin,
- int16_t clip_y_origin, const region_t *);
+void x_set_picture_clip_region(struct x_connection *, xcb_render_picture_t,
+ int16_t clip_x_origin, int16_t clip_y_origin, const region_t *);
-void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict);
+void x_clear_picture_clip_region(struct x_connection *, xcb_render_picture_t pict);
+
+/**
+ * Destroy a Picture
.
+ *
+ * Picture must be valid.
+ */
+void x_free_picture(struct x_connection *c, xcb_render_picture_t p);
/**
* Log a X11 error
@@ -242,10 +354,9 @@ void x_log_error(enum log_level level, unsigned long serial, uint8_t major,
*/
const char *x_strerror(xcb_generic_error_t *e);
-xcb_pixmap_t x_create_pixmap(xcb_connection_t *, uint8_t depth, xcb_drawable_t drawable,
- int width, int height);
+xcb_pixmap_t x_create_pixmap(struct x_connection *, uint8_t depth, int width, int height);
-bool x_validate_pixmap(xcb_connection_t *, xcb_pixmap_t pxmap);
+bool x_validate_pixmap(struct x_connection *, xcb_pixmap_t pxmap);
/**
* Free a winprop_t
.
@@ -254,22 +365,22 @@ bool x_validate_pixmap(xcb_connection_t *, xcb_pixmap_t pxmap);
*/
static inline void free_winprop(winprop_t *pprop) {
// Empty the whole structure to avoid possible issues
- if (pprop->r)
+ if (pprop->r) {
free(pprop->r);
+ }
pprop->ptr = NULL;
pprop->r = NULL;
pprop->nitems = 0;
}
/// Get the back pixmap of the root window
-xcb_pixmap_t
-x_get_root_back_pixmap(xcb_connection_t *c, xcb_window_t root, struct atom *atoms);
+xcb_pixmap_t x_get_root_back_pixmap(struct x_connection *c, struct atom *atoms);
/// Return true if the atom refers to a property name that is used for the
/// root window background pixmap
bool x_is_root_back_pixmap_atom(struct atom *atoms, xcb_atom_t atom);
-bool x_fence_sync(xcb_connection_t *, xcb_sync_fence_t);
+bool x_fence_sync(struct x_connection *, xcb_sync_fence_t);
struct x_convolution_kernel {
int size;
@@ -293,23 +404,18 @@ void attr_nonnull(1, 3) x_create_convolution_kernel(const conv *kernel, double c
/// Generate a search criteria for fbconfig from a X visual.
/// Returns {-1, -1, -1, -1, -1, -1} on failure
-struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
+struct xvisual_info x_get_visual_info(struct x_connection *c, xcb_visualid_t visual);
-xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
+xcb_visualid_t x_get_visual_for_standard(struct x_connection *c, xcb_pict_standard_t std);
xcb_render_pictformat_t
-x_get_pictfmt_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
+x_get_pictfmt_for_standard(struct x_connection *c, xcb_pict_standard_t std);
-xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen);
+xcb_screen_t *x_screen_of_display(struct x_connection *c, int screen);
-/**
- * X RandR-related functions.
- *
- * The x_update_randr_monitors function populates ps->randr_nmonitors and
- * ps->randr_monitor_regs with the data X RandR provided and the
- * x_free_randr_info function frees them.
- */
-void x_update_randr_monitors(session_t *ps);
-void x_free_randr_info(session_t *ps);
+/// Populates a `struct x_monitors` with the current monitor configuration.
+void x_update_monitors(struct x_connection *, struct x_monitors *);
+/// Free memory allocated for a `struct x_monitors`.
+void x_free_monitor_info(struct x_monitors *);
uint32_t attr_deprecated xcb_generate_id(xcb_connection_t *c);