Port more stuff to xcb
To avoid interoperability issues between xcb and xlib.
This commit is contained in:
parent
7af815a0aa
commit
209b751b25
4
Makefile
4
Makefile
|
@ -9,14 +9,14 @@ MANDIR ?= $(PREFIX)/share/man/man1
|
|||
APPDIR ?= $(PREFIX)/share/applications
|
||||
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
|
||||
INCS =
|
||||
|
||||
OBJS = compton.o config.o win.o x.o
|
||||
|
||||
# === 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"
|
||||
CFG += -Wconditional-uninitialized
|
||||
|
|
14
src/c2.c
14
src/c2.c
|
@ -1387,15 +1387,15 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf,
|
|||
*perr = false;
|
||||
switch (pleaf->predef) {
|
||||
case C2_L_PID: tgt = wid; break;
|
||||
case C2_L_PX: tgt = w->a.x; break;
|
||||
case C2_L_PY: tgt = w->a.y; break;
|
||||
case C2_L_PX2: tgt = w->a.x + w->widthb; break;
|
||||
case C2_L_PY2: tgt = w->a.y + w->heightb; break;
|
||||
case C2_L_PWIDTH: tgt = w->a.width; break;
|
||||
case C2_L_PHEIGHT: tgt = w->a.height; break;
|
||||
case C2_L_PX: tgt = w->g.x; break;
|
||||
case C2_L_PY: tgt = w->g.y; break;
|
||||
case C2_L_PX2: tgt = w->g.x + w->widthb; break;
|
||||
case C2_L_PY2: tgt = w->g.y + w->heightb; break;
|
||||
case C2_L_PWIDTH: tgt = w->g.width; break;
|
||||
case C2_L_PHEIGHT: tgt = w->g.height; break;
|
||||
case C2_L_PWIDTHB: tgt = w->widthb; 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_POVREDIR: tgt = w->a.override_redirect; break;
|
||||
case C2_L_PARGB: tgt = (WMODE_ARGB == w->mode); break;
|
||||
|
|
34
src/common.h
34
src/common.h
|
@ -96,6 +96,8 @@
|
|||
#include <X11/extensions/Xinerama.h>
|
||||
#endif
|
||||
|
||||
#include <xcb/render.h>
|
||||
|
||||
// Workarounds for missing definitions in very old versions of X headers,
|
||||
// thanks to consolers for reporting
|
||||
#ifndef PictOpDifference
|
||||
|
@ -787,7 +789,9 @@ typedef struct session {
|
|||
/// Default screen.
|
||||
int scr;
|
||||
/// Default visual.
|
||||
Visual *vis;
|
||||
xcb_visualid_t vis;
|
||||
/// Pict formats info
|
||||
xcb_render_query_pict_formats_reply_t *pictfmts;
|
||||
/// Default depth.
|
||||
int depth;
|
||||
/// Root window.
|
||||
|
@ -1041,13 +1045,14 @@ struct win {
|
|||
/// ID of the top-level frame window.
|
||||
Window id;
|
||||
/// Window attributes.
|
||||
XWindowAttributes a;
|
||||
xcb_get_window_attributes_reply_t a;
|
||||
xcb_get_geometry_reply_t g;
|
||||
#ifdef CONFIG_XINERAMA
|
||||
/// Xinerama screen this window is on.
|
||||
int xinerama_scr;
|
||||
#endif
|
||||
/// Window visual pict format;
|
||||
XRenderPictFormat *pictfmt;
|
||||
xcb_render_pictforminfo_t *pictfmt;
|
||||
/// Window painting mode.
|
||||
winmode_t mode;
|
||||
/// Whether the window has been damaged at least once.
|
||||
|
@ -1852,16 +1857,6 @@ find_toplevel(session_t *ps, Window id) {
|
|||
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.
|
||||
*/
|
||||
|
@ -2007,7 +2002,7 @@ set_ignore_next(session_t *ps) {
|
|||
*/
|
||||
static inline bool
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2515,3 +2510,14 @@ wintype_arr_enable(bool arr[]) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
360
src/compton.c
360
src/compton.c
|
@ -13,6 +13,8 @@
|
|||
#include <xcb/shape.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/damage.h>
|
||||
#include <xcb/render.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
|
||||
#include "compton.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,
|
||||
XserverRegion reg_clip);
|
||||
|
||||
static bool
|
||||
fork_after(session_t *ps);
|
||||
|
||||
static void
|
||||
get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass);
|
||||
|
||||
static void
|
||||
init_atoms(session_t *ps);
|
||||
|
||||
static void
|
||||
update_refresh_rate(session_t *ps);
|
||||
|
||||
|
@ -59,15 +55,6 @@ static void
|
|||
cxinerama_upd_scrs(session_t *ps);
|
||||
#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
|
||||
vsync_drm_init(session_t *ps);
|
||||
|
||||
|
@ -111,86 +98,24 @@ redir_start(session_t *ps);
|
|||
static void
|
||||
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 *
|
||||
recheck_focus(session_t *ps);
|
||||
|
||||
static bool
|
||||
get_root_tile(session_t *ps);
|
||||
|
||||
static void
|
||||
paint_root(session_t *ps, XserverRegion reg_paint);
|
||||
|
||||
static void
|
||||
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
|
||||
get_opacity_percent(win *w);
|
||||
|
||||
static void
|
||||
restack_win(session_t *ps, win *w, Window new_above);
|
||||
|
||||
static void
|
||||
finish_destroy_win(session_t *ps, win *w);
|
||||
|
||||
static void
|
||||
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
|
||||
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.
|
||||
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) {
|
||||
// Ignore damage when screen isn't 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,
|
||||
int width, int height) {
|
||||
XImage *ximage;
|
||||
unsigned char *data;
|
||||
xcb_image_t *ximage;
|
||||
int ylimit, xlimit;
|
||||
int swidth = width + ps->cgsize;
|
||||
int sheight = height + ps->cgsize;
|
||||
|
@ -558,17 +512,18 @@ make_shadow(session_t *ps, double opacity,
|
|||
int x_diff;
|
||||
int opacity_int = (int)(opacity * 25);
|
||||
|
||||
data = malloc(swidth * sheight * sizeof(unsigned char));
|
||||
if (!data) return 0;
|
||||
|
||||
ximage = XCreateImage(ps->dpy, ps->vis, 8,
|
||||
ZPixmap, 0, (char *) data, swidth, sheight, 8, swidth * sizeof(char));
|
||||
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
|
||||
ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
|
||||
0, 0, NULL);
|
||||
|
||||
if (!ximage) {
|
||||
free(data);
|
||||
printf_errf("(): failed to create an X image");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char *data = ximage->data;
|
||||
uint32_t sstride = ximage->stride;
|
||||
|
||||
/*
|
||||
* Build the gaussian in sections
|
||||
*/
|
||||
|
@ -611,10 +566,10 @@ make_shadow(session_t *ps, double opacity,
|
|||
d = sum_gaussian(ps->gaussian_map,
|
||||
opacity, x - center, y - center, width, height);
|
||||
}
|
||||
data[y * swidth + x] = d;
|
||||
data[(sheight - y - 1) * swidth + x] = d;
|
||||
data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
|
||||
data[y * swidth + (swidth - x - 1)] = d;
|
||||
data[y * sstride + x] = d;
|
||||
data[(sheight - y - 1) * sstride + x] = d;
|
||||
data[(sheight - y - 1) * sstride + (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,
|
||||
opacity, center, y - center, width, height);
|
||||
}
|
||||
memset(&data[y * swidth + ps->cgsize], d, x_diff);
|
||||
memset(&data[(sheight - y - 1) * swidth + ps->cgsize], d, x_diff);
|
||||
memset(&data[y * sstride + 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);
|
||||
}
|
||||
for (y = ps->cgsize; y < sheight - ps->cgsize; y++) {
|
||||
data[y * swidth + x] = d;
|
||||
data[y * swidth + (swidth - x - 1)] = d;
|
||||
data[y * sstride + x] = 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 height = w->heightb;
|
||||
|
||||
XImage *shadow_image = NULL;
|
||||
xcb_image_t *shadow_image = NULL;
|
||||
Pixmap shadow_pixmap = None, shadow_pixmap_argb = None;
|
||||
Picture shadow_picture = None, shadow_picture_argb = None;
|
||||
GC gc = None;
|
||||
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
|
||||
|
||||
shadow_image = make_shadow(ps, opacity, width, height);
|
||||
if (!shadow_image)
|
||||
if (!shadow_image) {
|
||||
printf_errf("(): failed to make shadow");
|
||||
return None;
|
||||
}
|
||||
|
||||
shadow_pixmap = XCreatePixmap(ps->dpy, ps->root,
|
||||
shadow_image->width, shadow_image->height, 8);
|
||||
shadow_pixmap_argb = XCreatePixmap(ps->dpy, ps->root,
|
||||
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;
|
||||
}
|
||||
|
||||
shadow_picture = XRenderCreatePicture(ps->dpy, shadow_pixmap,
|
||||
XRenderFindStandardFormat(ps->dpy, PictStandardA8), 0, 0);
|
||||
shadow_picture_argb = XRenderCreatePicture(ps->dpy, shadow_pixmap_argb,
|
||||
XRenderFindStandardFormat(ps->dpy, PictStandardARGB32), 0, 0);
|
||||
shadow_picture = x_create_picture_with_standard_and_pixmap(ps,
|
||||
XCB_PICT_STANDARD_A_8, shadow_pixmap, 0, NULL);
|
||||
shadow_picture_argb = x_create_picture_with_standard_and_pixmap(ps,
|
||||
XCB_PICT_STANDARD_ARGB_32, shadow_pixmap_argb, 0, NULL);
|
||||
if (!shadow_picture || !shadow_picture_argb)
|
||||
goto shadow_picture_err;
|
||||
|
||||
gc = XCreateGC(ps->dpy, shadow_pixmap, 0, 0);
|
||||
if (!gc)
|
||||
if (!gc) {
|
||||
printf_errf("(): failed to create graphic context");
|
||||
goto shadow_picture_err;
|
||||
}
|
||||
|
||||
XPutImage(ps->dpy, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0,
|
||||
shadow_image->width, shadow_image->height);
|
||||
xcb_image_put(c, shadow_pixmap, XGContextFromGC(gc), shadow_image, 0, 0, 0);
|
||||
XRenderComposite(ps->dpy, PictOpSrc, ps->cshadow_picture, shadow_picture,
|
||||
shadow_picture_argb, 0, 0, 0, 0, 0, 0,
|
||||
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);
|
||||
|
||||
XFreeGC(ps->dpy, gc);
|
||||
XDestroyImage(shadow_image);
|
||||
xcb_image_destroy(shadow_image);
|
||||
XFreePixmap(ps->dpy, shadow_pixmap);
|
||||
XRenderFreePicture(ps->dpy, shadow_picture);
|
||||
|
||||
|
@ -733,7 +694,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
|
|||
|
||||
shadow_picture_err:
|
||||
if (shadow_image)
|
||||
XDestroyImage(shadow_image);
|
||||
xcb_image_destroy(shadow_image);
|
||||
if (shadow_pixmap)
|
||||
XFreePixmap(ps->dpy, shadow_pixmap);
|
||||
if (shadow_pixmap_argb)
|
||||
|
@ -756,7 +717,7 @@ solid_picture(session_t *ps, bool argb, double a,
|
|||
double r, double g, double b) {
|
||||
Pixmap pixmap;
|
||||
Picture picture;
|
||||
XRenderPictureAttributes pa;
|
||||
xcb_render_create_picture_value_list_t pa;
|
||||
XRenderColor c;
|
||||
|
||||
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;
|
||||
|
||||
pa.repeat = True;
|
||||
picture = XRenderCreatePicture(ps->dpy, pixmap,
|
||||
XRenderFindStandardFormat(ps->dpy, argb
|
||||
? PictStandardARGB32 : PictStandardA8),
|
||||
CPRepeat,
|
||||
&pa);
|
||||
picture = x_create_picture_with_standard_and_pixmap(ps,
|
||||
argb ? XCB_PICT_STANDARD_ARGB_32 : XCB_PICT_STANDARD_A_8, pixmap,
|
||||
CPRepeat, &pa);
|
||||
|
||||
if (!picture) {
|
||||
XFreePixmap(ps->dpy, pixmap);
|
||||
|
@ -951,14 +910,11 @@ get_root_tile(session_t *ps) {
|
|||
}
|
||||
|
||||
// Create Picture
|
||||
{
|
||||
XRenderPictureAttributes pa = {
|
||||
.repeat = True,
|
||||
};
|
||||
ps->root_tile_paint.pict = XRenderCreatePicture(
|
||||
ps->dpy, pixmap, XRenderFindVisualFormat(ps->dpy, ps->vis),
|
||||
CPRepeat, &pa);
|
||||
}
|
||||
xcb_render_create_picture_value_list_t pa = {
|
||||
.repeat = True,
|
||||
};
|
||||
ps->root_tile_paint.pict = x_create_picture_with_visual_and_pixmap(
|
||||
ps, ps->vis, pixmap, CPRepeat, &pa);
|
||||
|
||||
// Fill pixmap if needed
|
||||
if (fill) {
|
||||
|
@ -1078,6 +1034,7 @@ paint_preprocess(session_t *ps, win *list) {
|
|||
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
|
||||
if (IsUnmapped == w->a.map_state) {
|
||||
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
|
||||
// excluded
|
||||
if (!w->ever_damaged
|
||||
|| w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1
|
||||
|| w->a.x >= ps->root_width || w->a.y >= ps->root_height
|
||||
|| w->g.x + w->g.width < 1 || w->g.y + w->g.height < 1
|
||||
|| w->g.x >= ps->root_width || w->g.y >= ps->root_height
|
||||
|| ((IsUnmapped == w->a.map_state || w->destroyed) && !w->paint.pixmap)
|
||||
|| get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0]
|
||||
|| 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_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.
|
||||
*
|
||||
|
@ -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
|
||||
// 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) {
|
||||
printf_errf("(): Failed to build intermediate Picture.");
|
||||
|
@ -1390,8 +1325,8 @@ xr_take_screenshot(session_t *ps) {
|
|||
static inline void
|
||||
win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
|
||||
XserverRegion reg_paint, const reg_data_t *pcache_reg) {
|
||||
const int x = w->a.x;
|
||||
const int y = w->a.y;
|
||||
const int x = w->g.x;
|
||||
const int y = w->g.y;
|
||||
const int wid = w->widthb;
|
||||
const int hei = w->heightb;
|
||||
|
||||
|
@ -1527,12 +1462,12 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
|
|||
// XRender: Build picture
|
||||
if (bkend_use_xrender(ps) && !w->paint.pict) {
|
||||
{
|
||||
XRenderPictureAttributes pa = {
|
||||
.subwindow_mode = IncludeInferiors,
|
||||
xcb_render_create_picture_value_list_t pa = {
|
||||
.subwindowmode = IncludeInferiors,
|
||||
};
|
||||
|
||||
w->paint.pict = XRenderCreatePicture(ps->dpy, draw, w->pictfmt,
|
||||
CPSubwindowMode, &pa);
|
||||
w->paint.pict = x_create_picture_with_pictfmt_and_pixmap(ps, w->pictfmt,
|
||||
draw, CPSubwindowMode, &pa);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1554,8 +1489,8 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
|
|||
return;
|
||||
}
|
||||
|
||||
const int x = w->a.x;
|
||||
const int y = w->a.y;
|
||||
const int x = w->g.x;
|
||||
const int y = w->g.y;
|
||||
const int wid = w->widthb;
|
||||
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
|
||||
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) {
|
||||
// Apply clipping region to save some CPU
|
||||
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)) {
|
||||
// DBE painting mode: Directly paint to a Picture of the back buffer
|
||||
if (BKEND_XRENDER == ps->o.backend && ps->o.dbe) {
|
||||
ps->tgt_buffer.pict = XRenderCreatePicture(ps->dpy, ps->root_dbe,
|
||||
XRenderFindVisualFormat(ps->dpy, ps->vis),
|
||||
0, 0);
|
||||
ps->tgt_buffer.pict = x_create_picture_with_visual_and_pixmap(
|
||||
ps, ps->vis, ps->root_dbe, 0, 0);
|
||||
}
|
||||
// No-DBE painting mode: Paint to an intermediate Picture then paint
|
||||
// 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)
|
||||
ps->tgt_buffer.pict = XRenderCreatePicture(ps->dpy,
|
||||
ps->tgt_buffer.pixmap, XRenderFindVisualFormat(ps->dpy, ps->vis),
|
||||
0, 0);
|
||||
ps->tgt_buffer.pict = x_create_picture_with_visual_and_pixmap(
|
||||
ps, ps->vis, ps->tgt_buffer.pixmap, 0, 0);
|
||||
}
|
||||
}
|
||||
#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
|
||||
reg_paint = reg_tmp = XFixesCreateRegion(ps->dpy, NULL, 0);
|
||||
XFixesSubtractRegion(ps->dpy, reg_paint, region, t->reg_ignore);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
reg_paint = region;
|
||||
}
|
||||
|
||||
|
@ -1831,8 +1763,10 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
|
|||
// Painting shadow
|
||||
if (w->shadow) {
|
||||
// Lazy shadow building
|
||||
if (!w->shadow_paint.pixmap)
|
||||
win_build_shadow(ps, w, 1);
|
||||
if (!w->shadow_paint.pixmap) {
|
||||
if (!win_build_shadow(ps, w, 1))
|
||||
printf_errf("(): build shadow failed");
|
||||
}
|
||||
|
||||
// Shadow is to be painted based on the ignore region of current
|
||||
// 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
|
||||
{
|
||||
XRectangle rec_shadow_border = {
|
||||
.x = w->a.x + w->shadow_dx,
|
||||
.y = w->a.y + w->shadow_dy,
|
||||
.x = w->g.x + w->shadow_dx,
|
||||
.y = w->g.y + w->shadow_dy,
|
||||
.width = w->shadow_width,
|
||||
.height = w->shadow_height
|
||||
};
|
||||
|
@ -2071,8 +2005,8 @@ repair_win(session_t *ps, win *w) {
|
|||
set_ignore_next(ps);
|
||||
XDamageSubtract(ps->dpy, w->damage, None, parts);
|
||||
XFixesTranslateRegion(ps->dpy, parts,
|
||||
w->a.x + w->a.border_width,
|
||||
w->a.y + w->a.border_width);
|
||||
w->g.x + w->g.border_width,
|
||||
w->g.y + w->g.border_width);
|
||||
}
|
||||
|
||||
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
|
||||
// Try avoiding mapping a window twice
|
||||
if (!w || InputOnly == w->a.class
|
||||
if (!w || InputOnly == w->a._class
|
||||
|| IsViewable == w->a.map_state)
|
||||
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 (w->a.x != ce->x || w->a.y != ce->y
|
||||
|| w->a.width != ce->width || w->a.height != ce->height
|
||||
|| w->a.border_width != ce->border_width) {
|
||||
if (w->g.x != ce->x || w->g.y != ce->y
|
||||
|| w->g.width != ce->width || w->g.height != ce->height
|
||||
|| w->g.border_width != ce->border_width) {
|
||||
factor_change = true;
|
||||
free_region(ps, &w->extents);
|
||||
free_region(ps, &w->border_size);
|
||||
}
|
||||
|
||||
w->a.x = ce->x;
|
||||
w->a.y = ce->y;
|
||||
w->g.x = ce->x;
|
||||
w->g.y = ce->y;
|
||||
|
||||
if (w->a.width != ce->width || w->a.height != ce->height
|
||||
|| w->a.border_width != ce->border_width)
|
||||
if (w->g.width != ce->width || w->g.height != ce->height
|
||||
|| w->g.border_width != ce->border_width)
|
||||
free_wpaint(ps, w);
|
||||
|
||||
if (w->a.width != ce->width || w->a.height != ce->height
|
||||
|| w->a.border_width != ce->border_width) {
|
||||
w->a.width = ce->width;
|
||||
w->a.height = ce->height;
|
||||
w->a.border_width = ce->border_width;
|
||||
if (w->g.width != ce->width || w->g.height != ce->height
|
||||
|| w->g.border_width != ce->border_width) {
|
||||
w->g.width = ce->width;
|
||||
w->g.height = ce->height;
|
||||
w->g.border_width = ce->border_width;
|
||||
calc_win_size(ps, w);
|
||||
|
||||
// Rounded corner detection is affected by window size
|
||||
|
@ -2776,15 +2710,12 @@ opts_set_no_fading_openclose(session_t *ps, bool newval) {
|
|||
//!@}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
ev_serial(XEvent *ev) {
|
||||
if ((ev->type & 0x7f) != KeymapNotify) {
|
||||
return ev->xany.serial;
|
||||
}
|
||||
return NextRequest(ev->xany.display);
|
||||
static inline int __attribute__((unused))
|
||||
ev_serial(xcb_generic_event_t *ev) {
|
||||
return ev->full_sequence;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
static inline const char * __attribute__((unused))
|
||||
ev_name(session_t *ps, xcb_generic_event_t *ev) {
|
||||
static char buf[128];
|
||||
switch (ev->response_type & 0x7f) {
|
||||
|
@ -2823,7 +2754,7 @@ ev_name(session_t *ps, xcb_generic_event_t *ev) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
static inline Window
|
||||
static inline Window __attribute__((unused))
|
||||
ev_window(session_t *ps, xcb_generic_event_t *ev) {
|
||||
switch (ev->response_type) {
|
||||
case FocusIn:
|
||||
|
@ -2863,7 +2794,7 @@ ev_window(session_t *ps, xcb_generic_event_t *ev) {
|
|||
}
|
||||
|
||||
static inline const char *
|
||||
ev_focus_mode_name(XFocusChangeEvent* ev) {
|
||||
ev_focus_mode_name(xcb_focus_in_event_t* ev) {
|
||||
switch (ev->mode) {
|
||||
CASESTRRET(NotifyNormal);
|
||||
CASESTRRET(NotifyWhileGrabbed);
|
||||
|
@ -2875,7 +2806,7 @@ ev_focus_mode_name(XFocusChangeEvent* ev) {
|
|||
}
|
||||
|
||||
static inline const char *
|
||||
ev_focus_detail_name(XFocusChangeEvent* ev) {
|
||||
ev_focus_detail_name(xcb_focus_in_event_t* ev) {
|
||||
switch (ev->detail) {
|
||||
CASESTRRET(NotifyAncestor);
|
||||
CASESTRRET(NotifyVirtual);
|
||||
|
@ -2890,8 +2821,8 @@ ev_focus_detail_name(XFocusChangeEvent* ev) {
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
static inline void
|
||||
ev_focus_report(XFocusChangeEvent* ev) {
|
||||
static inline void __attribute__((unused))
|
||||
ev_focus_report(xcb_focus_in_event_t *ev) {
|
||||
printf(" { mode: %s, detail: %s }\n", ev_focus_mode_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) {
|
||||
#ifdef DEBUG_EVENTS
|
||||
printf(" { send_event: %d, "
|
||||
" above: %#010lx, "
|
||||
" above: %#010x, "
|
||||
" override_redirect: %d }\n",
|
||||
ev->send_event, ev->above, ev->override_redirect);
|
||||
ev->event, ev->above_sibling, ev->override_redirect);
|
||||
#endif
|
||||
configure_win(ps, ev);
|
||||
}
|
||||
|
@ -2965,7 +2896,7 @@ ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) {
|
|||
inline static void
|
||||
ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
|
||||
#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);
|
||||
#endif
|
||||
|
||||
|
@ -3258,7 +3189,7 @@ ev_selection_clear(session_t *ps,
|
|||
/**
|
||||
* 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) {
|
||||
*name = "";
|
||||
if (wid) {
|
||||
|
@ -3289,7 +3220,7 @@ ev_handle(session_t *ps, xcb_generic_event_t *ev) {
|
|||
}
|
||||
|
||||
#ifdef DEBUG_EVENTS
|
||||
if (!isdamagenotify(ps, ev)) {
|
||||
if (ev->response_type == ps->damage_event + XDamageNotify) {
|
||||
Window wid = ev_window(ps, ev);
|
||||
char *window_name = NULL;
|
||||
ev_window_name(ps, wid, &window_name);
|
||||
|
@ -4726,9 +4657,10 @@ init_alpha_picts(session_t *ps) {
|
|||
|
||||
for (i = 0; i < num; ++i) {
|
||||
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);
|
||||
else
|
||||
assert(ps->alpha_picts[i] != None);
|
||||
} else
|
||||
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 = {
|
||||
.dpy = NULL,
|
||||
.scr = 0,
|
||||
.vis = NULL,
|
||||
.vis = 0,
|
||||
.depth = 0,
|
||||
.root = None,
|
||||
.root_height = 0,
|
||||
|
@ -5392,7 +5324,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
|||
ps->scr = DefaultScreen(ps->dpy);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
{
|
||||
XRenderPictureAttributes pa;
|
||||
pa.subwindow_mode = IncludeInferiors;
|
||||
xcb_render_create_picture_value_list_t pa = {
|
||||
.subwindowmode = IncludeInferiors,
|
||||
};
|
||||
|
||||
ps->root_picture = XRenderCreatePicture(ps->dpy, ps->root,
|
||||
XRenderFindVisualFormat(ps->dpy, ps->vis),
|
||||
CPSubwindowMode, &pa);
|
||||
ps->root_picture = x_create_picture_with_visual_and_pixmap(ps,
|
||||
ps->vis, ps->root, CPSubwindowMode, &pa);
|
||||
if (ps->o.paint_on_overlay) {
|
||||
ps->tgt_picture = XRenderCreatePicture(ps->dpy, ps->overlay,
|
||||
XRenderFindVisualFormat(ps->dpy, ps->vis),
|
||||
CPSubwindowMode, &pa);
|
||||
}
|
||||
else {
|
||||
ps->tgt_picture = x_create_picture_with_visual_and_pixmap(ps,
|
||||
ps->vis, ps->overlay, CPSubwindowMode, &pa);
|
||||
} else
|
||||
ps->tgt_picture = ps->root_picture;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize filters, must be preceded by OpenGL context creation
|
||||
|
@ -5817,6 +5746,7 @@ session_destroy(session_t *ps) {
|
|||
free(ps->pfds_except);
|
||||
free(ps->o.glx_fshader_win_str);
|
||||
free_xinerama_info(ps);
|
||||
free(ps->pictfmts);
|
||||
|
||||
#ifdef CONFIG_OPENGL
|
||||
glx_destroy(ps);
|
||||
|
|
|
@ -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>.
|
||||
*/
|
||||
|
@ -203,27 +192,6 @@ free_xinerama_info(session_t *ps) {
|
|||
#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.
|
||||
*/
|
||||
|
@ -435,7 +403,7 @@ update_reg_ignore_expire(session_t *ps, const win *w) {
|
|||
*/
|
||||
static inline bool __attribute__((pure))
|
||||
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.right || w->frame_extents.bottom;
|
||||
}
|
||||
|
@ -447,10 +415,10 @@ win_has_frame(const win *w) {
|
|||
static inline margin_t __attribute__((pure))
|
||||
win_calc_frame_extents(session_t *ps, const win *w) {
|
||||
margin_t result = w->frame_extents;
|
||||
result.top = max_i(result.top, w->a.border_width);
|
||||
result.left = max_i(result.left, w->a.border_width);
|
||||
result.bottom = max_i(result.bottom, w->a.border_width);
|
||||
result.right = max_i(result.right, w->a.border_width);
|
||||
result.top = max_i(result.top, w->g.border_width);
|
||||
result.left = max_i(result.left, w->g.border_width);
|
||||
result.bottom = max_i(result.bottom, w->g.border_width);
|
||||
result.right = max_i(result.right, w->g.border_width);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -527,8 +495,8 @@ static inline void
|
|||
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,
|
||||
Picture pict) {
|
||||
const int dx = (w ? w->a.x: 0) + x;
|
||||
const int dy = (w ? w->a.y: 0) + y;
|
||||
const int dx = (w ? w->g.x: 0) + x;
|
||||
const int dy = (w ? w->g.y: 0) + y;
|
||||
const bool argb = (w && (WMODE_ARGB == w->mode || ps->o.force_win_blend));
|
||||
const bool neg = (w && w->invert_color);
|
||||
|
||||
|
@ -678,9 +646,9 @@ cxinerama_win_upd_scr(session_t *ps, win *w) {
|
|||
w->xinerama_scr = -1;
|
||||
for (XineramaScreenInfo *s = ps->xinerama_scrs;
|
||||
s < ps->xinerama_scrs + ps->xinerama_nscrs; ++s)
|
||||
if (s->x_org <= w->a.x && s->y_org <= w->a.y
|
||||
&& s->x_org + s->width >= w->a.x + w->widthb
|
||||
&& s->y_org + s->height >= w->a.y + w->heightb) {
|
||||
if (s->x_org <= w->g.x && s->y_org <= w->g.y
|
||||
&& s->x_org + s->width >= w->g.x + w->widthb
|
||||
&& s->y_org + s->height >= w->g.y + w->heightb) {
|
||||
w->xinerama_scr = s - ps->xinerama_scrs;
|
||||
return;
|
||||
}
|
||||
|
|
86
src/opengl.c
86
src/opengl.c
|
@ -10,6 +10,14 @@
|
|||
|
||||
#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
|
||||
void
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*/
|
||||
|
|
16
src/opengl.h
16
src/opengl.h
|
@ -121,25 +121,9 @@ glx_hasglext(session_t *ps, const char *ext) {
|
|||
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
|
||||
glx_update_fbconfig(session_t *ps);
|
||||
|
||||
static int
|
||||
glx_cmp_fbconfig(session_t *ps,
|
||||
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);
|
||||
|
|
71
src/win.c
71
src/win.c
|
@ -1,5 +1,8 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <xcb/render.h>
|
||||
#include <xcb/damage.h>
|
||||
#include <xcb/xcb_renderutil.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
|
@ -76,8 +79,8 @@ XserverRegion
|
|||
win_get_region(session_t *ps, win *w, bool use_offset) {
|
||||
XRectangle r;
|
||||
|
||||
r.x = (use_offset ? w->a.x: 0);
|
||||
r.y = (use_offset ? w->a.y: 0);
|
||||
r.x = (use_offset ? w->g.x: 0);
|
||||
r.y = (use_offset ? w->g.y: 0);
|
||||
r.width = w->widthb;
|
||||
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);
|
||||
XRectangle r;
|
||||
|
||||
r.x = (use_offset ? w->a.x: 0) + extents.left;
|
||||
r.y = (use_offset ? w->a.y: 0) + extents.top;
|
||||
r.width = max_i(w->a.width - extents.left - extents.right, 0);
|
||||
r.height = max_i(w->a.height - extents.top - extents.bottom, 0);
|
||||
r.x = (use_offset ? w->g.x: 0) + extents.left;
|
||||
r.y = (use_offset ? w->g.y: 0) + extents.top;
|
||||
r.width = max_i(w->g.width - extents.left - extents.right, 0);
|
||||
r.height = max_i(w->g.height - extents.top - extents.bottom, 0);
|
||||
|
||||
if (r.width > 0 && r.height > 0)
|
||||
return XFixesCreateRegion(ps->dpy, &r, 1);
|
||||
|
@ -280,7 +283,7 @@ void win_determine_mode(session_t *ps, win *w) {
|
|||
winmode_t mode = WMODE_SOLID;
|
||||
|
||||
if (w->pictfmt && w->pictfmt->type == PictTypeDirect &&
|
||||
w->pictfmt->direct.alphaMask) {
|
||||
w->pictfmt->direct.alpha_mask) {
|
||||
mode = WMODE_ARGB;
|
||||
} else if (w->opacity != OPAQUE) {
|
||||
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.
|
||||
*/
|
||||
void calc_win_size(session_t *ps, win *w) {
|
||||
w->widthb = w->a.width + w->a.border_width * 2;
|
||||
w->heightb = w->a.height + w->a.border_width * 2;
|
||||
w->widthb = w->g.width + w->g.border_width * 2;
|
||||
w->heightb = w->g.height + w->g.border_width * 2;
|
||||
calc_shadow_geometry(ps, w);
|
||||
w->flags |= WFLAG_SIZE_CHANGE;
|
||||
}
|
||||
|
@ -857,28 +860,48 @@ bool add_win(session_t *ps, Window id, Window prev) {
|
|||
// Fill structure
|
||||
new->id = id;
|
||||
|
||||
set_ignore_next(ps);
|
||||
if (!XGetWindowAttributes(ps->dpy, id, &new->a) ||
|
||||
IsUnviewable == new->a.map_state) {
|
||||
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
|
||||
xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(c, id);
|
||||
xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(c, id);
|
||||
xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(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
|
||||
// already. IsUnviewable means the window is already reparented
|
||||
// elsewhere.
|
||||
free(a);
|
||||
free(g);
|
||||
free(new);
|
||||
return false;
|
||||
}
|
||||
|
||||
new->a = *a;
|
||||
free(a);
|
||||
|
||||
if (!g) {
|
||||
free(new);
|
||||
return false;
|
||||
}
|
||||
|
||||
new->g = *g;
|
||||
free(g);
|
||||
|
||||
// Delay window mapping
|
||||
int map_state = new->a.map_state;
|
||||
assert(IsViewable == map_state || IsUnmapped == map_state);
|
||||
new->a.map_state = IsUnmapped;
|
||||
|
||||
if (InputOutput == new->a.class) {
|
||||
// Get window picture format
|
||||
new->pictfmt = XRenderFindVisualFormat(ps->dpy, new->a.visual);
|
||||
|
||||
if (InputOutput == new->a._class) {
|
||||
// Create Damage for window
|
||||
set_ignore_next(ps);
|
||||
new->damage = XDamageCreate(ps->dpy, id, XDamageReportNonEmpty);
|
||||
new->damage = xcb_generate_id(c);
|
||||
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);
|
||||
|
@ -1133,16 +1156,16 @@ win_set_focused(session_t *ps, win *w, bool focused) {
|
|||
XserverRegion win_extents(session_t *ps, win *w) {
|
||||
XRectangle r;
|
||||
|
||||
r.x = w->a.x;
|
||||
r.y = w->a.y;
|
||||
r.x = w->g.x;
|
||||
r.y = w->g.y;
|
||||
r.width = w->widthb;
|
||||
r.height = w->heightb;
|
||||
|
||||
if (w->shadow) {
|
||||
XRectangle sr;
|
||||
|
||||
sr.x = w->a.x + w->shadow_dx;
|
||||
sr.y = w->a.y + w->shadow_dy;
|
||||
sr.x = w->g.x + w->shadow_dx;
|
||||
sr.y = w->g.y + w->shadow_dy;
|
||||
sr.width = w->shadow_width;
|
||||
sr.height = w->shadow_height;
|
||||
|
||||
|
@ -1195,8 +1218,8 @@ win_border_size(session_t *ps, win *w, bool use_offset) {
|
|||
if (use_offset) {
|
||||
// Translate the region to the correct place
|
||||
XFixesTranslateRegion(ps->dpy, border,
|
||||
w->a.x + w->a.border_width,
|
||||
w->a.y + w->a.border_width);
|
||||
w->g.x + w->g.border_width,
|
||||
w->g.y + w->g.border_width);
|
||||
}
|
||||
|
||||
// Intersect the bounding region we got with the window rectangle, to
|
||||
|
|
110
src/x.c
110
src/x.c
|
@ -1,4 +1,5 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb_renderutil.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "x.h"
|
||||
|
@ -93,3 +94,112 @@ bool wid_get_text_prop(session_t *ps, Window wid, Atom prop,
|
|||
cxfree(text_prop.value);
|
||||
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
31
src/x.h
|
@ -1,6 +1,9 @@
|
|||
#pragma once
|
||||
#include <stdbool.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 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,
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue