Port more stuff to xcb

To avoid interoperability issues between xcb and xlib.
This commit is contained in:
Yuxuan Shui 2018-09-23 19:10:46 +01:00
parent 7af815a0aa
commit 209b751b25
10 changed files with 380 additions and 398 deletions

View File

@ -9,14 +9,14 @@ MANDIR ?= $(PREFIX)/share/man/man1
APPDIR ?= $(PREFIX)/share/applications APPDIR ?= $(PREFIX)/share/applications
ICODIR ?= $(PREFIX)/share/icons/hicolor/ ICODIR ?= $(PREFIX)/share/icons/hicolor/
PACKAGES = x11 x11-xcb xcomposite xfixes xdamage xrender xext xrandr PACKAGES = x11 x11-xcb xcb-renderutil xcb-render xcb-damage xcb-image xcomposite xfixes xdamage xrender xext xrandr
LIBS = -lm -lrt LIBS = -lm -lrt
INCS = INCS =
OBJS = compton.o config.o win.o x.o OBJS = compton.o config.o win.o x.o
# === Configuration flags === # === Configuration flags ===
CFG = -std=c11 -D_GNU_SOURCE -Wall -Wextra -Wno-unused-parameter CFG = -std=c11 -D_GNU_SOURCE -Wall -Wextra -Wno-unused-parameter -Wnonnull
ifeq "$(CC)" "clang" ifeq "$(CC)" "clang"
CFG += -Wconditional-uninitialized CFG += -Wconditional-uninitialized

View File

@ -1387,15 +1387,15 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf,
*perr = false; *perr = false;
switch (pleaf->predef) { switch (pleaf->predef) {
case C2_L_PID: tgt = wid; break; case C2_L_PID: tgt = wid; break;
case C2_L_PX: tgt = w->a.x; break; case C2_L_PX: tgt = w->g.x; break;
case C2_L_PY: tgt = w->a.y; break; case C2_L_PY: tgt = w->g.y; break;
case C2_L_PX2: tgt = w->a.x + w->widthb; break; case C2_L_PX2: tgt = w->g.x + w->widthb; break;
case C2_L_PY2: tgt = w->a.y + w->heightb; break; case C2_L_PY2: tgt = w->g.y + w->heightb; break;
case C2_L_PWIDTH: tgt = w->a.width; break; case C2_L_PWIDTH: tgt = w->g.width; break;
case C2_L_PHEIGHT: tgt = w->a.height; break; case C2_L_PHEIGHT: tgt = w->g.height; break;
case C2_L_PWIDTHB: tgt = w->widthb; break; case C2_L_PWIDTHB: tgt = w->widthb; break;
case C2_L_PHEIGHTB: tgt = w->heightb; break; case C2_L_PHEIGHTB: tgt = w->heightb; break;
case C2_L_PBDW: tgt = w->a.border_width; break; case C2_L_PBDW: tgt = w->g.border_width; break;
case C2_L_PFULLSCREEN: tgt = win_is_fullscreen(ps, w); break; case C2_L_PFULLSCREEN: tgt = win_is_fullscreen(ps, w); break;
case C2_L_POVREDIR: tgt = w->a.override_redirect; break; case C2_L_POVREDIR: tgt = w->a.override_redirect; break;
case C2_L_PARGB: tgt = (WMODE_ARGB == w->mode); break; case C2_L_PARGB: tgt = (WMODE_ARGB == w->mode); break;

View File

@ -96,6 +96,8 @@
#include <X11/extensions/Xinerama.h> #include <X11/extensions/Xinerama.h>
#endif #endif
#include <xcb/render.h>
// Workarounds for missing definitions in very old versions of X headers, // Workarounds for missing definitions in very old versions of X headers,
// thanks to consolers for reporting // thanks to consolers for reporting
#ifndef PictOpDifference #ifndef PictOpDifference
@ -787,7 +789,9 @@ typedef struct session {
/// Default screen. /// Default screen.
int scr; int scr;
/// Default visual. /// Default visual.
Visual *vis; xcb_visualid_t vis;
/// Pict formats info
xcb_render_query_pict_formats_reply_t *pictfmts;
/// Default depth. /// Default depth.
int depth; int depth;
/// Root window. /// Root window.
@ -1041,13 +1045,14 @@ struct win {
/// ID of the top-level frame window. /// ID of the top-level frame window.
Window id; Window id;
/// Window attributes. /// Window attributes.
XWindowAttributes a; xcb_get_window_attributes_reply_t a;
xcb_get_geometry_reply_t g;
#ifdef CONFIG_XINERAMA #ifdef CONFIG_XINERAMA
/// Xinerama screen this window is on. /// Xinerama screen this window is on.
int xinerama_scr; int xinerama_scr;
#endif #endif
/// Window visual pict format; /// Window visual pict format;
XRenderPictFormat *pictfmt; xcb_render_pictforminfo_t *pictfmt;
/// Window painting mode. /// Window painting mode.
winmode_t mode; winmode_t mode;
/// Whether the window has been damaged at least once. /// Whether the window has been damaged at least once.
@ -1852,16 +1857,6 @@ find_toplevel(session_t *ps, Window id) {
return NULL; return NULL;
} }
/**
* Check if current backend uses XRender for rendering.
*/
static inline bool
bkend_use_xrender(session_t *ps) {
return BKEND_XRENDER == ps->o.backend
|| BKEND_XR_GLX_HYBRID == ps->o.backend;
}
/** /**
* Check if current backend uses GLX. * Check if current backend uses GLX.
*/ */
@ -2007,7 +2002,7 @@ set_ignore_next(session_t *ps) {
*/ */
static inline bool static inline bool
win_is_fullscreen(session_t *ps, const win *w) { win_is_fullscreen(session_t *ps, const win *w) {
return rect_is_fullscreen(ps, w->a.x, w->a.y, w->widthb, w->heightb) return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb)
&& (!w->bounding_shaped || w->rounded_corners); && (!w->bounding_shaped || w->rounded_corners);
} }
@ -2515,3 +2510,14 @@ wintype_arr_enable(bool arr[]) {
arr[i] = true; arr[i] = true;
} }
} }
/**
* Destroy a <code>Pixmap</code>.
*/
static inline void
free_pixmap(session_t *ps, Pixmap *p) {
if (*p) {
XFreePixmap(ps->dpy, *p);
*p = None;
}
}

View File

@ -13,6 +13,8 @@
#include <xcb/shape.h> #include <xcb/shape.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <xcb/damage.h> #include <xcb/damage.h>
#include <xcb/render.h>
#include <xcb/xcb_image.h>
#include "compton.h" #include "compton.h"
#include "win.h" #include "win.h"
@ -27,15 +29,9 @@ xr_blur_dst(session_t *ps, Picture tgt_buffer,
int x, int y, int wid, int hei, XFixed **blur_kerns, int x, int y, int wid, int hei, XFixed **blur_kerns,
XserverRegion reg_clip); XserverRegion reg_clip);
static bool
fork_after(session_t *ps);
static void static void
get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass); get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass);
static void
init_atoms(session_t *ps);
static void static void
update_refresh_rate(session_t *ps); update_refresh_rate(session_t *ps);
@ -59,15 +55,6 @@ static void
cxinerama_upd_scrs(session_t *ps); cxinerama_upd_scrs(session_t *ps);
#endif #endif
static void
timeout_clear(session_t *ps);
static bool
tmout_unredir_callback(session_t *ps, timeout_t *tmout);
static bool
mainloop(session_t *ps);
static bool static bool
vsync_drm_init(session_t *ps); vsync_drm_init(session_t *ps);
@ -111,86 +98,24 @@ redir_start(session_t *ps);
static void static void
redir_stop(session_t *ps); redir_stop(session_t *ps);
static void
discard_ignore(session_t *ps, unsigned long sequence);
static int
should_ignore(session_t *ps, unsigned long sequence);
static void
run_fade(session_t *ps, win *w, unsigned steps);
static double
gaussian(double r, double x, double y);
static conv *
make_gaussian_map(double r);
static unsigned char
sum_gaussian(conv *map, double opacity,
int x, int y, int width, int height);
static void
presum_gaussian(session_t *ps, conv *map);
static XImage *
make_shadow(session_t *ps, double opacity, int width, int height);
static bool
win_build_shadow(session_t *ps, win *w, double opacity);
static Picture
solid_picture(session_t *ps, bool argb, double a,
double r, double g, double b);
static win * static win *
recheck_focus(session_t *ps); recheck_focus(session_t *ps);
static bool static bool
get_root_tile(session_t *ps); get_root_tile(session_t *ps);
static void
paint_root(session_t *ps, XserverRegion reg_paint);
static void static void
finish_map_win(session_t *ps, win *w); finish_map_win(session_t *ps, win *w);
static void
finish_unmap_win(session_t *ps, win *w);
static void
unmap_callback(session_t *ps, win *w);
static void
unmap_win(session_t *ps, win *w);
static double static double
get_opacity_percent(win *w); get_opacity_percent(win *w);
static void static void
restack_win(session_t *ps, win *w, Window new_above); restack_win(session_t *ps, win *w, Window new_above);
static void
finish_destroy_win(session_t *ps, win *w);
static void static void
destroy_callback(session_t *ps, win *w); destroy_callback(session_t *ps, win *w);
static void
destroy_win(session_t *ps, Window id);
static int
xerror(Display *dpy, XErrorEvent *ev);
static void
expose_root(session_t *ps, XRectangle *rects, int nrects);
static void __attribute__ ((noreturn))
usage(int ret);
static bool
register_cm(session_t *ps);
static void static void
update_ewmh_active_win(session_t *ps); update_ewmh_active_win(session_t *ps);
@ -277,6 +202,36 @@ static const char *background_props_str[] = {
/// have a pointer to current session passed in. /// have a pointer to current session passed in.
session_t *ps_g = NULL; session_t *ps_g = NULL;
/**
* Check if current backend uses XRender for rendering.
*/
static inline bool
bkend_use_xrender(session_t *ps) {
return BKEND_XRENDER == ps->o.backend
|| BKEND_XR_GLX_HYBRID == ps->o.backend;
}
/**
* Check whether a paint_t contains enough data.
*/
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)
return false;
if (bkend_use_xrender(ps) && !ppaint->pict)
return false;
#ifdef CONFIG_OPENGL
if (BKEND_GLX == ps->o.backend && !glx_tex_binded(ppaint->ptex, None))
return false;
#endif
return true;
}
void add_damage(session_t *ps, XserverRegion damage) { void add_damage(session_t *ps, XserverRegion damage) {
// Ignore damage when screen isn't redirected // Ignore damage when screen isn't redirected
if (!ps->redirected) if (!ps->redirected)
@ -544,11 +499,10 @@ presum_gaussian(session_t *ps, conv *map) {
} }
} }
static XImage * static xcb_image_t *
make_shadow(session_t *ps, double opacity, make_shadow(session_t *ps, double opacity,
int width, int height) { int width, int height) {
XImage *ximage; xcb_image_t *ximage;
unsigned char *data;
int ylimit, xlimit; int ylimit, xlimit;
int swidth = width + ps->cgsize; int swidth = width + ps->cgsize;
int sheight = height + ps->cgsize; int sheight = height + ps->cgsize;
@ -558,17 +512,18 @@ make_shadow(session_t *ps, double opacity,
int x_diff; int x_diff;
int opacity_int = (int)(opacity * 25); int opacity_int = (int)(opacity * 25);
data = malloc(swidth * sheight * sizeof(unsigned char)); xcb_connection_t *c = XGetXCBConnection(ps->dpy);
if (!data) return 0; ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
0, 0, NULL);
ximage = XCreateImage(ps->dpy, ps->vis, 8,
ZPixmap, 0, (char *) data, swidth, sheight, 8, swidth * sizeof(char));
if (!ximage) { if (!ximage) {
free(data); printf_errf("(): failed to create an X image");
return 0; return 0;
} }
unsigned char *data = ximage->data;
uint32_t sstride = ximage->stride;
/* /*
* Build the gaussian in sections * Build the gaussian in sections
*/ */
@ -611,10 +566,10 @@ make_shadow(session_t *ps, double opacity,
d = sum_gaussian(ps->gaussian_map, d = sum_gaussian(ps->gaussian_map,
opacity, x - center, y - center, width, height); opacity, x - center, y - center, width, height);
} }
data[y * swidth + x] = d; data[y * sstride + x] = d;
data[(sheight - y - 1) * swidth + x] = d; data[(sheight - y - 1) * sstride + x] = d;
data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d; data[(sheight - y - 1) * sstride + (swidth - x - 1)] = d;
data[y * swidth + (swidth - x - 1)] = d; data[y * sstride + (swidth - x - 1)] = d;
} }
} }
@ -631,8 +586,8 @@ make_shadow(session_t *ps, double opacity,
d = sum_gaussian(ps->gaussian_map, d = sum_gaussian(ps->gaussian_map,
opacity, center, y - center, width, height); opacity, center, y - center, width, height);
} }
memset(&data[y * swidth + ps->cgsize], d, x_diff); memset(&data[y * sstride + ps->cgsize], d, x_diff);
memset(&data[(sheight - y - 1) * swidth + ps->cgsize], d, x_diff); memset(&data[(sheight - y - 1) * sstride + ps->cgsize], d, x_diff);
} }
} }
@ -648,8 +603,8 @@ make_shadow(session_t *ps, double opacity,
opacity, x - center, center, width, height); opacity, x - center, center, width, height);
} }
for (y = ps->cgsize; y < sheight - ps->cgsize; y++) { for (y = ps->cgsize; y < sheight - ps->cgsize; y++) {
data[y * swidth + x] = d; data[y * sstride + x] = d;
data[y * swidth + (swidth - x - 1)] = d; data[y * sstride + (swidth - x - 1)] = d;
} }
} }
@ -682,36 +637,42 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
const int width = w->widthb; const int width = w->widthb;
const int height = w->heightb; const int height = w->heightb;
XImage *shadow_image = NULL; xcb_image_t *shadow_image = NULL;
Pixmap shadow_pixmap = None, shadow_pixmap_argb = None; Pixmap shadow_pixmap = None, shadow_pixmap_argb = None;
Picture shadow_picture = None, shadow_picture_argb = None; Picture shadow_picture = None, shadow_picture_argb = None;
GC gc = None; GC gc = None;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
shadow_image = make_shadow(ps, opacity, width, height); shadow_image = make_shadow(ps, opacity, width, height);
if (!shadow_image) if (!shadow_image) {
printf_errf("(): failed to make shadow");
return None; return None;
}
shadow_pixmap = XCreatePixmap(ps->dpy, ps->root, shadow_pixmap = XCreatePixmap(ps->dpy, ps->root,
shadow_image->width, shadow_image->height, 8); shadow_image->width, shadow_image->height, 8);
shadow_pixmap_argb = XCreatePixmap(ps->dpy, ps->root, shadow_pixmap_argb = XCreatePixmap(ps->dpy, ps->root,
shadow_image->width, shadow_image->height, 32); shadow_image->width, shadow_image->height, 32);
if (!shadow_pixmap || !shadow_pixmap_argb) if (!shadow_pixmap || !shadow_pixmap_argb) {
printf_errf("(): failed to create shadow pixmaps");
goto shadow_picture_err; goto shadow_picture_err;
}
shadow_picture = XRenderCreatePicture(ps->dpy, shadow_pixmap, shadow_picture = x_create_picture_with_standard_and_pixmap(ps,
XRenderFindStandardFormat(ps->dpy, PictStandardA8), 0, 0); XCB_PICT_STANDARD_A_8, shadow_pixmap, 0, NULL);
shadow_picture_argb = XRenderCreatePicture(ps->dpy, shadow_pixmap_argb, shadow_picture_argb = x_create_picture_with_standard_and_pixmap(ps,
XRenderFindStandardFormat(ps->dpy, PictStandardARGB32), 0, 0); XCB_PICT_STANDARD_ARGB_32, shadow_pixmap_argb, 0, NULL);
if (!shadow_picture || !shadow_picture_argb) if (!shadow_picture || !shadow_picture_argb)
goto shadow_picture_err; goto shadow_picture_err;
gc = XCreateGC(ps->dpy, shadow_pixmap, 0, 0); gc = XCreateGC(ps->dpy, shadow_pixmap, 0, 0);
if (!gc) if (!gc) {
printf_errf("(): failed to create graphic context");
goto shadow_picture_err; goto shadow_picture_err;
}
XPutImage(ps->dpy, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0, xcb_image_put(c, shadow_pixmap, XGContextFromGC(gc), shadow_image, 0, 0, 0);
shadow_image->width, shadow_image->height);
XRenderComposite(ps->dpy, PictOpSrc, ps->cshadow_picture, shadow_picture, XRenderComposite(ps->dpy, PictOpSrc, ps->cshadow_picture, shadow_picture,
shadow_picture_argb, 0, 0, 0, 0, 0, 0, shadow_picture_argb, 0, 0, 0, 0, 0, 0,
shadow_image->width, shadow_image->height); shadow_image->width, shadow_image->height);
@ -725,7 +686,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
xr_sync(ps, w->shadow_paint.pixmap, NULL); xr_sync(ps, w->shadow_paint.pixmap, NULL);
XFreeGC(ps->dpy, gc); XFreeGC(ps->dpy, gc);
XDestroyImage(shadow_image); xcb_image_destroy(shadow_image);
XFreePixmap(ps->dpy, shadow_pixmap); XFreePixmap(ps->dpy, shadow_pixmap);
XRenderFreePicture(ps->dpy, shadow_picture); XRenderFreePicture(ps->dpy, shadow_picture);
@ -733,7 +694,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
shadow_picture_err: shadow_picture_err:
if (shadow_image) if (shadow_image)
XDestroyImage(shadow_image); xcb_image_destroy(shadow_image);
if (shadow_pixmap) if (shadow_pixmap)
XFreePixmap(ps->dpy, shadow_pixmap); XFreePixmap(ps->dpy, shadow_pixmap);
if (shadow_pixmap_argb) if (shadow_pixmap_argb)
@ -756,7 +717,7 @@ solid_picture(session_t *ps, bool argb, double a,
double r, double g, double b) { double r, double g, double b) {
Pixmap pixmap; Pixmap pixmap;
Picture picture; Picture picture;
XRenderPictureAttributes pa; xcb_render_create_picture_value_list_t pa;
XRenderColor c; XRenderColor c;
pixmap = XCreatePixmap(ps->dpy, ps->root, 1, 1, argb ? 32 : 8); pixmap = XCreatePixmap(ps->dpy, ps->root, 1, 1, argb ? 32 : 8);
@ -764,11 +725,9 @@ solid_picture(session_t *ps, bool argb, double a,
if (!pixmap) return None; if (!pixmap) return None;
pa.repeat = True; pa.repeat = True;
picture = XRenderCreatePicture(ps->dpy, pixmap, picture = x_create_picture_with_standard_and_pixmap(ps,
XRenderFindStandardFormat(ps->dpy, argb argb ? XCB_PICT_STANDARD_ARGB_32 : XCB_PICT_STANDARD_A_8, pixmap,
? PictStandardARGB32 : PictStandardA8), CPRepeat, &pa);
CPRepeat,
&pa);
if (!picture) { if (!picture) {
XFreePixmap(ps->dpy, pixmap); XFreePixmap(ps->dpy, pixmap);
@ -951,14 +910,11 @@ get_root_tile(session_t *ps) {
} }
// Create Picture // Create Picture
{ xcb_render_create_picture_value_list_t pa = {
XRenderPictureAttributes pa = { .repeat = True,
.repeat = True, };
}; ps->root_tile_paint.pict = x_create_picture_with_visual_and_pixmap(
ps->root_tile_paint.pict = XRenderCreatePicture( ps, ps->vis, pixmap, CPRepeat, &pa);
ps->dpy, pixmap, XRenderFindVisualFormat(ps->dpy, ps->vis),
CPRepeat, &pa);
}
// Fill pixmap if needed // Fill pixmap if needed
if (fill) { if (fill) {
@ -1078,6 +1034,7 @@ paint_preprocess(session_t *ps, win *list) {
free_region(ps, &w->reg_ignore); free_region(ps, &w->reg_ignore);
} }
//printf_errf("(): %d %d %s", w->a.map_state, w->ever_damaged, w->name);
// Restore flags from last paint if the window is being faded out // Restore flags from last paint if the window is being faded out
if (IsUnmapped == w->a.map_state) { if (IsUnmapped == w->a.map_state) {
win_set_shadow(ps, w, w->shadow_last); win_set_shadow(ps, w, w->shadow_last);
@ -1101,8 +1058,8 @@ paint_preprocess(session_t *ps, win *list) {
// pixmap is gone (for example due to a ConfigureNotify), or when it's // pixmap is gone (for example due to a ConfigureNotify), or when it's
// excluded // excluded
if (!w->ever_damaged if (!w->ever_damaged
|| w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 || w->g.x + w->g.width < 1 || w->g.y + w->g.height < 1
|| w->a.x >= ps->root_width || w->a.y >= ps->root_height || w->g.x >= ps->root_width || w->g.y >= ps->root_height
|| ((IsUnmapped == w->a.map_state || w->destroyed) && !w->paint.pixmap) || ((IsUnmapped == w->a.map_state || w->destroyed) && !w->paint.pixmap)
|| get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0] || get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0]
|| w->paint_excluded) || w->paint_excluded)
@ -1272,37 +1229,15 @@ win_paint_shadow(session_t *ps, win *w,
paint_bind_tex(ps, &w->shadow_paint, 0, 0, 32, false); paint_bind_tex(ps, &w->shadow_paint, 0, 0, 32, false);
if (!paint_isvalid(ps, &w->shadow_paint)) { if (!paint_isvalid(ps, &w->shadow_paint)) {
printf_errf("(%#010lx): Missing painting data. This is a bad sign.", w->id); printf_errf("(%#010lx): Missing shadow data.", w->id);
return; return;
} }
render(ps, 0, 0, w->a.x + w->shadow_dx, w->a.y + w->shadow_dy, render(ps, 0, 0, w->g.x + w->shadow_dx, w->g.y + w->shadow_dy,
w->shadow_width, w->shadow_height, w->shadow_opacity, true, false, w->shadow_width, w->shadow_height, w->shadow_opacity, true, false,
w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, pcache_reg, NULL); w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, pcache_reg, NULL);
} }
/**
* Create an picture.
*/
static inline Picture
xr_build_picture(session_t *ps, int wid, int hei,
XRenderPictFormat *pictfmt) {
if (!pictfmt)
pictfmt = XRenderFindVisualFormat(ps->dpy, ps->vis);
int depth = pictfmt->depth;
Pixmap tmp_pixmap = XCreatePixmap(ps->dpy, ps->root, wid, hei, depth);
if (!tmp_pixmap)
return None;
Picture tmp_picture = XRenderCreatePicture(ps->dpy, tmp_pixmap,
pictfmt, 0, 0);
free_pixmap(ps, &tmp_pixmap);
return tmp_picture;
}
/** /**
* @brief Blur an area on a buffer. * @brief Blur an area on a buffer.
* *
@ -1326,7 +1261,7 @@ xr_blur_dst(session_t *ps, Picture tgt_buffer,
// Directly copying from tgt_buffer to it does not work, so we create a // Directly copying from tgt_buffer to it does not work, so we create a
// Picture in the middle. // Picture in the middle.
Picture tmp_picture = xr_build_picture(ps, wid, hei, NULL); Picture tmp_picture = x_create_picture(ps, wid, hei, NULL, 0, NULL);
if (!tmp_picture) { if (!tmp_picture) {
printf_errf("(): Failed to build intermediate Picture."); printf_errf("(): Failed to build intermediate Picture.");
@ -1390,8 +1325,8 @@ xr_take_screenshot(session_t *ps) {
static inline void static inline void
win_blur_background(session_t *ps, win *w, Picture tgt_buffer, win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
XserverRegion reg_paint, const reg_data_t *pcache_reg) { XserverRegion reg_paint, const reg_data_t *pcache_reg) {
const int x = w->a.x; const int x = w->g.x;
const int y = w->a.y; const int y = w->g.y;
const int wid = w->widthb; const int wid = w->widthb;
const int hei = w->heightb; const int hei = w->heightb;
@ -1527,12 +1462,12 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
// XRender: Build picture // XRender: Build picture
if (bkend_use_xrender(ps) && !w->paint.pict) { if (bkend_use_xrender(ps) && !w->paint.pict) {
{ {
XRenderPictureAttributes pa = { xcb_render_create_picture_value_list_t pa = {
.subwindow_mode = IncludeInferiors, .subwindowmode = IncludeInferiors,
}; };
w->paint.pict = XRenderCreatePicture(ps->dpy, draw, w->pictfmt, w->paint.pict = x_create_picture_with_pictfmt_and_pixmap(ps, w->pictfmt,
CPSubwindowMode, &pa); draw, CPSubwindowMode, &pa);
} }
} }
@ -1554,8 +1489,8 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
return; return;
} }
const int x = w->a.x; const int x = w->g.x;
const int y = w->a.y; const int y = w->g.y;
const int wid = w->widthb; const int wid = w->widthb;
const int hei = w->heightb; const int hei = w->heightb;
@ -1563,7 +1498,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
// Invert window color, if required // Invert window color, if required
if (bkend_use_xrender(ps) && w->invert_color) { if (bkend_use_xrender(ps) && w->invert_color) {
Picture newpict = xr_build_picture(ps, wid, hei, w->pictfmt); Picture newpict = x_create_picture(ps, wid, hei, w->pictfmt, 0, NULL);
if (newpict) { if (newpict) {
// Apply clipping region to save some CPU // Apply clipping region to save some CPU
if (reg_paint) { if (reg_paint) {
@ -1769,9 +1704,8 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
if (!paint_isvalid(ps, &ps->tgt_buffer)) { if (!paint_isvalid(ps, &ps->tgt_buffer)) {
// DBE painting mode: Directly paint to a Picture of the back buffer // DBE painting mode: Directly paint to a Picture of the back buffer
if (BKEND_XRENDER == ps->o.backend && ps->o.dbe) { if (BKEND_XRENDER == ps->o.backend && ps->o.dbe) {
ps->tgt_buffer.pict = XRenderCreatePicture(ps->dpy, ps->root_dbe, ps->tgt_buffer.pict = x_create_picture_with_visual_and_pixmap(
XRenderFindVisualFormat(ps->dpy, ps->vis), ps, ps->vis, ps->root_dbe, 0, 0);
0, 0);
} }
// No-DBE painting mode: Paint to an intermediate Picture then paint // No-DBE painting mode: Paint to an intermediate Picture then paint
// the Picture to root window // the Picture to root window
@ -1783,9 +1717,8 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
} }
if (BKEND_GLX != ps->o.backend) if (BKEND_GLX != ps->o.backend)
ps->tgt_buffer.pict = XRenderCreatePicture(ps->dpy, ps->tgt_buffer.pict = x_create_picture_with_visual_and_pixmap(
ps->tgt_buffer.pixmap, XRenderFindVisualFormat(ps->dpy, ps->vis), ps, ps->vis, ps->tgt_buffer.pixmap, 0, 0);
0, 0);
} }
} }
#endif #endif
@ -1814,8 +1747,7 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
// based on the ignore region of the lowest window, if available // based on the ignore region of the lowest window, if available
reg_paint = reg_tmp = XFixesCreateRegion(ps->dpy, NULL, 0); reg_paint = reg_tmp = XFixesCreateRegion(ps->dpy, NULL, 0);
XFixesSubtractRegion(ps->dpy, reg_paint, region, t->reg_ignore); XFixesSubtractRegion(ps->dpy, reg_paint, region, t->reg_ignore);
} } else {
else {
reg_paint = region; reg_paint = region;
} }
@ -1831,8 +1763,10 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
// Painting shadow // Painting shadow
if (w->shadow) { if (w->shadow) {
// Lazy shadow building // Lazy shadow building
if (!w->shadow_paint.pixmap) if (!w->shadow_paint.pixmap) {
win_build_shadow(ps, w, 1); if (!win_build_shadow(ps, w, 1))
printf_errf("(): build shadow failed");
}
// Shadow is to be painted based on the ignore region of current // Shadow is to be painted based on the ignore region of current
// window // window
@ -1861,8 +1795,8 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
// Might be worthwhile to crop the region to shadow border // Might be worthwhile to crop the region to shadow border
{ {
XRectangle rec_shadow_border = { XRectangle rec_shadow_border = {
.x = w->a.x + w->shadow_dx, .x = w->g.x + w->shadow_dx,
.y = w->a.y + w->shadow_dy, .y = w->g.y + w->shadow_dy,
.width = w->shadow_width, .width = w->shadow_width,
.height = w->shadow_height .height = w->shadow_height
}; };
@ -2071,8 +2005,8 @@ repair_win(session_t *ps, win *w) {
set_ignore_next(ps); set_ignore_next(ps);
XDamageSubtract(ps->dpy, w->damage, None, parts); XDamageSubtract(ps->dpy, w->damage, None, parts);
XFixesTranslateRegion(ps->dpy, parts, XFixesTranslateRegion(ps->dpy, parts,
w->a.x + w->a.border_width, w->g.x + w->g.border_width,
w->a.y + w->a.border_width); w->g.y + w->g.border_width);
} }
w->ever_damaged = true; w->ever_damaged = true;
@ -2109,7 +2043,7 @@ map_win(session_t *ps, Window id) {
// Don't care about window mapping if it's an InputOnly window // Don't care about window mapping if it's an InputOnly window
// Try avoiding mapping a window twice // Try avoiding mapping a window twice
if (!w || InputOnly == w->a.class if (!w || InputOnly == w->a._class
|| IsViewable == w->a.map_state) || IsViewable == w->a.map_state)
return; return;
@ -2412,26 +2346,26 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
} }
// If window geometry did not change, don't free extents here // If window geometry did not change, don't free extents here
if (w->a.x != ce->x || w->a.y != ce->y if (w->g.x != ce->x || w->g.y != ce->y
|| w->a.width != ce->width || w->a.height != ce->height || w->g.width != ce->width || w->g.height != ce->height
|| w->a.border_width != ce->border_width) { || w->g.border_width != ce->border_width) {
factor_change = true; factor_change = true;
free_region(ps, &w->extents); free_region(ps, &w->extents);
free_region(ps, &w->border_size); free_region(ps, &w->border_size);
} }
w->a.x = ce->x; w->g.x = ce->x;
w->a.y = ce->y; w->g.y = ce->y;
if (w->a.width != ce->width || w->a.height != ce->height if (w->g.width != ce->width || w->g.height != ce->height
|| w->a.border_width != ce->border_width) || w->g.border_width != ce->border_width)
free_wpaint(ps, w); free_wpaint(ps, w);
if (w->a.width != ce->width || w->a.height != ce->height if (w->g.width != ce->width || w->g.height != ce->height
|| w->a.border_width != ce->border_width) { || w->g.border_width != ce->border_width) {
w->a.width = ce->width; w->g.width = ce->width;
w->a.height = ce->height; w->g.height = ce->height;
w->a.border_width = ce->border_width; w->g.border_width = ce->border_width;
calc_win_size(ps, w); calc_win_size(ps, w);
// Rounded corner detection is affected by window size // Rounded corner detection is affected by window size
@ -2776,15 +2710,12 @@ opts_set_no_fading_openclose(session_t *ps, bool newval) {
//!@} //!@}
#endif #endif
static inline int static inline int __attribute__((unused))
ev_serial(XEvent *ev) { ev_serial(xcb_generic_event_t *ev) {
if ((ev->type & 0x7f) != KeymapNotify) { return ev->full_sequence;
return ev->xany.serial;
}
return NextRequest(ev->xany.display);
} }
static inline const char * static inline const char * __attribute__((unused))
ev_name(session_t *ps, xcb_generic_event_t *ev) { ev_name(session_t *ps, xcb_generic_event_t *ev) {
static char buf[128]; static char buf[128];
switch (ev->response_type & 0x7f) { switch (ev->response_type & 0x7f) {
@ -2823,7 +2754,7 @@ ev_name(session_t *ps, xcb_generic_event_t *ev) {
return buf; return buf;
} }
static inline Window static inline Window __attribute__((unused))
ev_window(session_t *ps, xcb_generic_event_t *ev) { ev_window(session_t *ps, xcb_generic_event_t *ev) {
switch (ev->response_type) { switch (ev->response_type) {
case FocusIn: case FocusIn:
@ -2863,7 +2794,7 @@ ev_window(session_t *ps, xcb_generic_event_t *ev) {
} }
static inline const char * static inline const char *
ev_focus_mode_name(XFocusChangeEvent* ev) { ev_focus_mode_name(xcb_focus_in_event_t* ev) {
switch (ev->mode) { switch (ev->mode) {
CASESTRRET(NotifyNormal); CASESTRRET(NotifyNormal);
CASESTRRET(NotifyWhileGrabbed); CASESTRRET(NotifyWhileGrabbed);
@ -2875,7 +2806,7 @@ ev_focus_mode_name(XFocusChangeEvent* ev) {
} }
static inline const char * static inline const char *
ev_focus_detail_name(XFocusChangeEvent* ev) { ev_focus_detail_name(xcb_focus_in_event_t* ev) {
switch (ev->detail) { switch (ev->detail) {
CASESTRRET(NotifyAncestor); CASESTRRET(NotifyAncestor);
CASESTRRET(NotifyVirtual); CASESTRRET(NotifyVirtual);
@ -2890,8 +2821,8 @@ ev_focus_detail_name(XFocusChangeEvent* ev) {
return "Unknown"; return "Unknown";
} }
static inline void static inline void __attribute__((unused))
ev_focus_report(XFocusChangeEvent* ev) { ev_focus_report(xcb_focus_in_event_t *ev) {
printf(" { mode: %s, detail: %s }\n", ev_focus_mode_name(ev), printf(" { mode: %s, detail: %s }\n", ev_focus_mode_name(ev),
ev_focus_detail_name(ev)); ev_focus_detail_name(ev));
} }
@ -2937,9 +2868,9 @@ inline static void
ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) { ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) {
#ifdef DEBUG_EVENTS #ifdef DEBUG_EVENTS
printf(" { send_event: %d, " printf(" { send_event: %d, "
" above: %#010lx, " " above: %#010x, "
" override_redirect: %d }\n", " override_redirect: %d }\n",
ev->send_event, ev->above, ev->override_redirect); ev->event, ev->above_sibling, ev->override_redirect);
#endif #endif
configure_win(ps, ev); configure_win(ps, ev);
} }
@ -2965,7 +2896,7 @@ ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) {
inline static void inline static void
ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
#ifdef DEBUG_EVENTS #ifdef DEBUG_EVENTS
printf_dbg(" { new_parent: %#010lx, override_redirect: %d }\n", printf_dbg(" { new_parent: %#010x, override_redirect: %d }\n",
ev->parent, ev->override_redirect); ev->parent, ev->override_redirect);
#endif #endif
@ -3258,7 +3189,7 @@ ev_selection_clear(session_t *ps,
/** /**
* Get a window's name from window ID. * Get a window's name from window ID.
*/ */
static inline void static inline void __attribute__((unused))
ev_window_name(session_t *ps, Window wid, char **name) { ev_window_name(session_t *ps, Window wid, char **name) {
*name = ""; *name = "";
if (wid) { if (wid) {
@ -3289,7 +3220,7 @@ ev_handle(session_t *ps, xcb_generic_event_t *ev) {
} }
#ifdef DEBUG_EVENTS #ifdef DEBUG_EVENTS
if (!isdamagenotify(ps, ev)) { if (ev->response_type == ps->damage_event + XDamageNotify) {
Window wid = ev_window(ps, ev); Window wid = ev_window(ps, ev);
char *window_name = NULL; char *window_name = NULL;
ev_window_name(ps, wid, &window_name); ev_window_name(ps, wid, &window_name);
@ -4726,9 +4657,10 @@ init_alpha_picts(session_t *ps) {
for (i = 0; i < num; ++i) { for (i = 0; i < num; ++i) {
double o = i * ps->o.alpha_step; double o = i * ps->o.alpha_step;
if ((1.0 - o) > ps->o.alpha_step) if ((1.0 - o) > ps->o.alpha_step) {
ps->alpha_picts[i] = solid_picture(ps, false, o, 0, 0, 0); ps->alpha_picts[i] = solid_picture(ps, false, o, 0, 0, 0);
else assert(ps->alpha_picts[i] != None);
} else
ps->alpha_picts[i] = None; ps->alpha_picts[i] = None;
} }
} }
@ -5173,7 +5105,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
static const session_t s_def = { static const session_t s_def = {
.dpy = NULL, .dpy = NULL,
.scr = 0, .scr = 0,
.vis = NULL, .vis = 0,
.depth = 0, .depth = 0,
.root = None, .root = None,
.root_height = 0, .root_height = 0,
@ -5392,7 +5324,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->scr = DefaultScreen(ps->dpy); ps->scr = DefaultScreen(ps->dpy);
ps->root = RootWindow(ps->dpy, ps->scr); ps->root = RootWindow(ps->dpy, ps->scr);
ps->vis = DefaultVisual(ps->dpy, ps->scr); ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr));
ps->depth = DefaultDepth(ps->dpy, ps->scr); ps->depth = DefaultDepth(ps->dpy, ps->scr);
// Start listening to events on root earlier to catch all possible // Start listening to events on root earlier to catch all possible
@ -5590,20 +5522,17 @@ session_init(session_t *ps_old, int argc, char **argv) {
presum_gaussian(ps, ps->gaussian_map); presum_gaussian(ps, ps->gaussian_map);
{ {
XRenderPictureAttributes pa; xcb_render_create_picture_value_list_t pa = {
pa.subwindow_mode = IncludeInferiors; .subwindowmode = IncludeInferiors,
};
ps->root_picture = XRenderCreatePicture(ps->dpy, ps->root, ps->root_picture = x_create_picture_with_visual_and_pixmap(ps,
XRenderFindVisualFormat(ps->dpy, ps->vis), ps->vis, ps->root, CPSubwindowMode, &pa);
CPSubwindowMode, &pa);
if (ps->o.paint_on_overlay) { if (ps->o.paint_on_overlay) {
ps->tgt_picture = XRenderCreatePicture(ps->dpy, ps->overlay, ps->tgt_picture = x_create_picture_with_visual_and_pixmap(ps,
XRenderFindVisualFormat(ps->dpy, ps->vis), ps->vis, ps->overlay, CPSubwindowMode, &pa);
CPSubwindowMode, &pa); } else
}
else {
ps->tgt_picture = ps->root_picture; ps->tgt_picture = ps->root_picture;
}
} }
// Initialize filters, must be preceded by OpenGL context creation // Initialize filters, must be preceded by OpenGL context creation
@ -5817,6 +5746,7 @@ session_destroy(session_t *ps) {
free(ps->pfds_except); free(ps->pfds_except);
free(ps->o.glx_fshader_win_str); free(ps->o.glx_fshader_win_str);
free_xinerama_info(ps); free_xinerama_info(ps);
free(ps->pictfmts);
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
glx_destroy(ps); glx_destroy(ps);

View File

@ -153,17 +153,6 @@ free_picture(session_t *ps, Picture *p) {
} }
} }
/**
* Destroy a <code>Pixmap</code>.
*/
inline static void
free_pixmap(session_t *ps, Pixmap *p) {
if (*p) {
XFreePixmap(ps->dpy, *p);
*p = None;
}
}
/** /**
* Destroy a <code>Damage</code>. * Destroy a <code>Damage</code>.
*/ */
@ -203,27 +192,6 @@ free_xinerama_info(session_t *ps) {
#endif #endif
} }
/**
* Check whether a paint_t contains enough data.
*/
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)
return false;
if (bkend_use_xrender(ps) && !ppaint->pict)
return false;
#ifdef CONFIG_OPENGL
if (BKEND_GLX == ps->o.backend && !glx_tex_binded(ppaint->ptex, None))
return false;
#endif
return true;
}
/** /**
* Bind texture in paint_t if we are using GLX backend. * Bind texture in paint_t if we are using GLX backend.
*/ */
@ -435,7 +403,7 @@ update_reg_ignore_expire(session_t *ps, const win *w) {
*/ */
static inline bool __attribute__((pure)) static inline bool __attribute__((pure))
win_has_frame(const win *w) { win_has_frame(const win *w) {
return w->a.border_width return w->g.border_width
|| w->frame_extents.top || w->frame_extents.left || w->frame_extents.top || w->frame_extents.left
|| w->frame_extents.right || w->frame_extents.bottom; || w->frame_extents.right || w->frame_extents.bottom;
} }
@ -447,10 +415,10 @@ win_has_frame(const win *w) {
static inline margin_t __attribute__((pure)) static inline margin_t __attribute__((pure))
win_calc_frame_extents(session_t *ps, const win *w) { win_calc_frame_extents(session_t *ps, const win *w) {
margin_t result = w->frame_extents; margin_t result = w->frame_extents;
result.top = max_i(result.top, w->a.border_width); result.top = max_i(result.top, w->g.border_width);
result.left = max_i(result.left, w->a.border_width); result.left = max_i(result.left, w->g.border_width);
result.bottom = max_i(result.bottom, w->a.border_width); result.bottom = max_i(result.bottom, w->g.border_width);
result.right = max_i(result.right, w->a.border_width); result.right = max_i(result.right, w->g.border_width);
return result; return result;
} }
@ -527,8 +495,8 @@ static inline void
win_render(session_t *ps, win *w, int x, int y, int wid, int hei, win_render(session_t *ps, win *w, int x, int y, int wid, int hei,
double opacity, XserverRegion reg_paint, const reg_data_t *pcache_reg, double opacity, XserverRegion reg_paint, const reg_data_t *pcache_reg,
Picture pict) { Picture pict) {
const int dx = (w ? w->a.x: 0) + x; const int dx = (w ? w->g.x: 0) + x;
const int dy = (w ? w->a.y: 0) + y; const int dy = (w ? w->g.y: 0) + y;
const bool argb = (w && (WMODE_ARGB == w->mode || ps->o.force_win_blend)); const bool argb = (w && (WMODE_ARGB == w->mode || ps->o.force_win_blend));
const bool neg = (w && w->invert_color); const bool neg = (w && w->invert_color);
@ -678,9 +646,9 @@ cxinerama_win_upd_scr(session_t *ps, win *w) {
w->xinerama_scr = -1; w->xinerama_scr = -1;
for (XineramaScreenInfo *s = ps->xinerama_scrs; for (XineramaScreenInfo *s = ps->xinerama_scrs;
s < ps->xinerama_scrs + ps->xinerama_nscrs; ++s) s < ps->xinerama_scrs + ps->xinerama_nscrs; ++s)
if (s->x_org <= w->a.x && s->y_org <= w->a.y if (s->x_org <= w->g.x && s->y_org <= w->g.y
&& s->x_org + s->width >= w->a.x + w->widthb && s->x_org + s->width >= w->g.x + w->widthb
&& s->y_org + s->height >= w->a.y + w->heightb) { && s->y_org + s->height >= w->g.y + w->heightb) {
w->xinerama_scr = s - ps->xinerama_scrs; w->xinerama_scr = s - ps->xinerama_scrs;
return; return;
} }

View File

@ -10,6 +10,14 @@
#include "opengl.h" #include "opengl.h"
static inline XVisualInfo *
get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) {
XVisualInfo vreq = { .visualid = visual };
int nitems = 0;
return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
}
#ifdef CONFIG_GLX_SYNC #ifdef CONFIG_GLX_SYNC
void void
xr_glx_sync(session_t *ps, Drawable d, XSyncFence *pfence) { xr_glx_sync(session_t *ps, Drawable d, XSyncFence *pfence) {
@ -1620,84 +1628,6 @@ glx_render_(session_t *ps, const glx_texture_t *ptex,
return true; return true;
} }
/**
* Render a region with color.
*
* Unused but can be useful for debugging
*/
static void __attribute__((unused))
glx_render_color(session_t *ps, int dx, int dy, int width, int height, int z,
XserverRegion reg_tgt, const reg_data_t *pcache_reg) {
static int color = 0;
color = color % (3 * 3 * 3 - 1) + 1;
glColor4f(1.0 / 3.0 * (color / (3 * 3)),
1.0 / 3.0 * (color % (3 * 3) / 3),
1.0 / 3.0 * (color % 3),
1.0f
);
z -= 0.2;
{
P_PAINTREG_START();
{
GLint rdx = crect.x;
GLint rdy = ps->root_height - crect.y;
GLint rdxe = rdx + crect.width;
GLint rdye = rdy - crect.height;
glVertex3i(rdx, rdy, z);
glVertex3i(rdxe, rdy, z);
glVertex3i(rdxe, rdye, z);
glVertex3i(rdx, rdye, z);
}
P_PAINTREG_END();
}
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glx_check_err(ps);
}
/**
* Render a region with dots.
*
* Unused but can be useful for debugging
*/
static void __attribute__((unused))
glx_render_dots(session_t *ps, int dx, int dy, int width, int height, int z,
XserverRegion reg_tgt, const reg_data_t *pcache_reg) {
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
z -= 0.1;
{
P_PAINTREG_START();
{
static const GLint BLK_WID = 5, BLK_HEI = 5;
glEnd();
glPointSize(1.0);
glBegin(GL_POINTS);
GLint rdx = crect.x;
GLint rdy = ps->root_height - crect.y;
GLint rdxe = rdx + crect.width;
GLint rdye = rdy - crect.height;
rdx = (rdx) / BLK_WID * BLK_WID;
rdy = (rdy) / BLK_HEI * BLK_HEI;
rdxe = (rdxe) / BLK_WID * BLK_WID;
rdye = (rdye) / BLK_HEI * BLK_HEI;
for (GLint cdx = rdx; cdx < rdxe; cdx += BLK_WID)
for (GLint cdy = rdy; cdy > rdye; cdy -= BLK_HEI)
glVertex3i(cdx + BLK_WID / 2, cdy - BLK_HEI / 2, z);
}
P_PAINTREG_END();
}
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glx_check_err(ps);
}
/** /**
* Swap buffer with glXCopySubBufferMESA(). * Swap buffer with glXCopySubBufferMESA().
*/ */

View File

@ -121,25 +121,9 @@ glx_hasglext(session_t *ps, const char *ext) {
return found; return found;
} }
static inline XVisualInfo *
get_visualinfo_from_visual(session_t *ps, Visual *visual) {
XVisualInfo vreq = { .visualid = XVisualIDFromVisual(visual) };
int nitems = 0;
return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems);
}
static bool static bool
glx_update_fbconfig(session_t *ps); glx_update_fbconfig(session_t *ps);
static int static int
glx_cmp_fbconfig(session_t *ps, glx_cmp_fbconfig(session_t *ps,
const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b); const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b);
static void
glx_render_color(session_t *ps, int dx, int dy, int width, int height, int z,
XserverRegion reg_tgt, const reg_data_t *pcache_reg);
static void
glx_render_dots(session_t *ps, int dx, int dy, int width, int height, int z,
XserverRegion reg_tgt, const reg_data_t *pcache_reg);

View File

@ -1,5 +1,8 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h> #include <X11/extensions/Xfixes.h>
#include <xcb/render.h>
#include <xcb/damage.h>
#include <xcb/xcb_renderutil.h>
#include <stdbool.h> #include <stdbool.h>
#include <math.h> #include <math.h>
@ -76,8 +79,8 @@ XserverRegion
win_get_region(session_t *ps, win *w, bool use_offset) { win_get_region(session_t *ps, win *w, bool use_offset) {
XRectangle r; XRectangle r;
r.x = (use_offset ? w->a.x: 0); r.x = (use_offset ? w->g.x: 0);
r.y = (use_offset ? w->a.y: 0); r.y = (use_offset ? w->g.y: 0);
r.width = w->widthb; r.width = w->widthb;
r.height = w->heightb; r.height = w->heightb;
@ -93,10 +96,10 @@ win_get_region_noframe(session_t *ps, win *w, bool use_offset) {
const margin_t extents = win_calc_frame_extents(ps, w); const margin_t extents = win_calc_frame_extents(ps, w);
XRectangle r; XRectangle r;
r.x = (use_offset ? w->a.x: 0) + extents.left; r.x = (use_offset ? w->g.x: 0) + extents.left;
r.y = (use_offset ? w->a.y: 0) + extents.top; r.y = (use_offset ? w->g.y: 0) + extents.top;
r.width = max_i(w->a.width - extents.left - extents.right, 0); r.width = max_i(w->g.width - extents.left - extents.right, 0);
r.height = max_i(w->a.height - extents.top - extents.bottom, 0); r.height = max_i(w->g.height - extents.top - extents.bottom, 0);
if (r.width > 0 && r.height > 0) if (r.width > 0 && r.height > 0)
return XFixesCreateRegion(ps->dpy, &r, 1); return XFixesCreateRegion(ps->dpy, &r, 1);
@ -280,7 +283,7 @@ void win_determine_mode(session_t *ps, win *w) {
winmode_t mode = WMODE_SOLID; winmode_t mode = WMODE_SOLID;
if (w->pictfmt && w->pictfmt->type == PictTypeDirect && if (w->pictfmt && w->pictfmt->type == PictTypeDirect &&
w->pictfmt->direct.alphaMask) { w->pictfmt->direct.alpha_mask) {
mode = WMODE_ARGB; mode = WMODE_ARGB;
} else if (w->opacity != OPAQUE) { } else if (w->opacity != OPAQUE) {
mode = WMODE_TRANS; mode = WMODE_TRANS;
@ -602,8 +605,8 @@ void win_on_factor_change(session_t *ps, win *w) {
* Update cache data in struct _win that depends on window size. * Update cache data in struct _win that depends on window size.
*/ */
void calc_win_size(session_t *ps, win *w) { void calc_win_size(session_t *ps, win *w) {
w->widthb = w->a.width + w->a.border_width * 2; w->widthb = w->g.width + w->g.border_width * 2;
w->heightb = w->a.height + w->a.border_width * 2; w->heightb = w->g.height + w->g.border_width * 2;
calc_shadow_geometry(ps, w); calc_shadow_geometry(ps, w);
w->flags |= WFLAG_SIZE_CHANGE; w->flags |= WFLAG_SIZE_CHANGE;
} }
@ -857,28 +860,48 @@ bool add_win(session_t *ps, Window id, Window prev) {
// Fill structure // Fill structure
new->id = id; new->id = id;
set_ignore_next(ps); xcb_connection_t *c = XGetXCBConnection(ps->dpy);
if (!XGetWindowAttributes(ps->dpy, id, &new->a) || xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(c, id);
IsUnviewable == new->a.map_state) { xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(c, id);
xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(c, acookie, NULL);
xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(c, gcookie, NULL);
if (!a || IsUnviewable == a->map_state) {
// Failed to get window attributes probably means the window is gone // Failed to get window attributes probably means the window is gone
// already. IsUnviewable means the window is already reparented // already. IsUnviewable means the window is already reparented
// elsewhere. // elsewhere.
free(a);
free(g);
free(new); free(new);
return false; return false;
} }
new->a = *a;
free(a);
if (!g) {
free(new);
return false;
}
new->g = *g;
free(g);
// Delay window mapping // Delay window mapping
int map_state = new->a.map_state; int map_state = new->a.map_state;
assert(IsViewable == map_state || IsUnmapped == map_state); assert(IsViewable == map_state || IsUnmapped == map_state);
new->a.map_state = IsUnmapped; new->a.map_state = IsUnmapped;
if (InputOutput == new->a.class) { if (InputOutput == new->a._class) {
// Get window picture format
new->pictfmt = XRenderFindVisualFormat(ps->dpy, new->a.visual);
// Create Damage for window // Create Damage for window
set_ignore_next(ps); new->damage = xcb_generate_id(c);
new->damage = XDamageCreate(ps->dpy, id, XDamageReportNonEmpty); xcb_generic_error_t *e = xcb_request_check(c,
xcb_damage_create_checked(c, new->damage, id, XDamageReportNonEmpty));
if (e) {
free(e);
free(new);
return false;
}
new->pictfmt = x_get_pictform_for_visual(ps, new->a.visual);
} }
calc_win_size(ps, new); calc_win_size(ps, new);
@ -1133,16 +1156,16 @@ win_set_focused(session_t *ps, win *w, bool focused) {
XserverRegion win_extents(session_t *ps, win *w) { XserverRegion win_extents(session_t *ps, win *w) {
XRectangle r; XRectangle r;
r.x = w->a.x; r.x = w->g.x;
r.y = w->a.y; r.y = w->g.y;
r.width = w->widthb; r.width = w->widthb;
r.height = w->heightb; r.height = w->heightb;
if (w->shadow) { if (w->shadow) {
XRectangle sr; XRectangle sr;
sr.x = w->a.x + w->shadow_dx; sr.x = w->g.x + w->shadow_dx;
sr.y = w->a.y + w->shadow_dy; sr.y = w->g.y + w->shadow_dy;
sr.width = w->shadow_width; sr.width = w->shadow_width;
sr.height = w->shadow_height; sr.height = w->shadow_height;
@ -1195,8 +1218,8 @@ win_border_size(session_t *ps, win *w, bool use_offset) {
if (use_offset) { if (use_offset) {
// Translate the region to the correct place // Translate the region to the correct place
XFixesTranslateRegion(ps->dpy, border, XFixesTranslateRegion(ps->dpy, border,
w->a.x + w->a.border_width, w->g.x + w->g.border_width,
w->a.y + w->a.border_width); w->g.y + w->g.border_width);
} }
// Intersect the bounding region we got with the window rectangle, to // Intersect the bounding region we got with the window rectangle, to

110
src/x.c
View File

@ -1,4 +1,5 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <xcb/xcb_renderutil.h>
#include "common.h" #include "common.h"
#include "x.h" #include "x.h"
@ -93,3 +94,112 @@ bool wid_get_text_prop(session_t *ps, Window wid, Atom prop,
cxfree(text_prop.value); cxfree(text_prop.value);
return true; return true;
} }
static inline void x_get_server_pictfmts(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_generic_error_t *e = NULL;
// Get window picture format
ps->pictfmts =
xcb_render_query_pict_formats_reply(c,
xcb_render_query_pict_formats(c), &e);
if (e || !ps->pictfmts) {
printf_errf("(): failed to get pict formats\n");
abort();
}
}
xcb_render_pictforminfo_t *x_get_pictform_for_visual(session_t *ps, xcb_visualid_t visual) {
if (!ps->pictfmts)
x_get_server_pictfmts(ps);
xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(ps->pictfmts, visual);
for(xcb_render_pictforminfo_iterator_t i =
xcb_render_query_pict_formats_formats_iterator(ps->pictfmts); i.rem;
xcb_render_pictforminfo_next(&i)) {
if (i.data->id == pv->format)
return i.data;
}
return NULL;
}
xcb_render_picture_t
x_create_picture_with_pictfmt_and_pixmap(
session_t *ps, xcb_render_pictforminfo_t * pictfmt,
xcb_pixmap_t pixmap, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
{
void *buf = NULL;
if (attr) {
xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr);
if (!buf) {
printf_errf("(): failed to serialize picture attributes");
return None;
}
}
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_render_picture_t tmp_picture = xcb_generate_id(c);
xcb_generic_error_t *e =
xcb_request_check(c, xcb_render_create_picture_checked(c, tmp_picture,
pixmap, pictfmt->id, valuemask, buf));
free(buf);
if (e) {
printf_errf("(): failed to create picture");
return None;
}
return tmp_picture;
}
xcb_render_picture_t
x_create_picture_with_visual_and_pixmap(
session_t *ps, xcb_visualid_t visual,
xcb_pixmap_t pixmap, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
{
xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(ps, visual);
return x_create_picture_with_pictfmt_and_pixmap(ps, pictfmt, pixmap, valuemask, attr);
}
xcb_render_picture_t
x_create_picture_with_standard_and_pixmap(
session_t *ps, xcb_pict_standard_t standard,
xcb_pixmap_t pixmap, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
{
if (!ps->pictfmts)
x_get_server_pictfmts(ps);
xcb_render_pictforminfo_t *pictfmt =
xcb_render_util_find_standard_format(ps->pictfmts, standard);
assert(pictfmt);
return x_create_picture_with_pictfmt_and_pixmap(ps, pictfmt, pixmap, valuemask, attr);
}
/**
* Create an picture.
*/
xcb_render_picture_t
x_create_picture(session_t *ps, int wid, int hei,
xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
{
if (!pictfmt)
pictfmt = x_get_pictform_for_visual(ps, ps->vis);
if (!pictfmt) {
printf_errf("(): default visual is invalid");
abort();
}
int depth = pictfmt->depth;
Pixmap tmp_pixmap = XCreatePixmap(ps->dpy, ps->root, wid, hei, depth);
if (!tmp_pixmap)
return None;
xcb_render_picture_t picture =
x_create_picture_with_pictfmt_and_pixmap(ps, pictfmt, tmp_pixmap, valuemask, attr);
free_pixmap(ps, &tmp_pixmap);
return picture;
}

31
src/x.h
View File

@ -1,6 +1,9 @@
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <xcb/xcb.h>
#include <xcb/render.h>
#include <xcb/xcb_renderutil.h>
typedef struct session session_t; typedef struct session session_t;
typedef struct winprop winprop_t; typedef struct winprop winprop_t;
/** /**
@ -35,3 +38,31 @@ wid_get_prop_window(session_t *ps, Window wid, Atom aprop);
*/ */
bool wid_get_text_prop(session_t *ps, Window wid, Atom prop, bool wid_get_text_prop(session_t *ps, Window wid, Atom prop,
char ***pstrlst, int *pnstr); char ***pstrlst, int *pnstr);
xcb_render_pictforminfo_t *x_get_pictform_for_visual(session_t *, xcb_visualid_t);
xcb_render_picture_t x_create_picture_with_pictfmt_and_pixmap(
session_t *ps, xcb_render_pictforminfo_t *pictfmt,
xcb_pixmap_t pixmap, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
__attribute__((nonnull(1, 2)));
xcb_render_picture_t x_create_picture_with_visual_and_pixmap(
session_t *ps, xcb_visualid_t visual,
xcb_pixmap_t pixmap, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
__attribute__((nonnull(1)));
xcb_render_picture_t x_create_picture_with_standard_and_pixmap(
session_t *ps, xcb_pict_standard_t standard,
xcb_pixmap_t pixmap, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr)
__attribute__((nonnull(1)));
/**
* Create an picture.
*/
xcb_render_picture_t
x_create_picture(session_t *ps, int wid, int hei,
xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr);