Convert XfixesRegion to pixman region

Re-did the painting logic, and document it.

It is unclear to me what is the previous painting logic. But the current
one is basically this:

1. Go through all windows top to bottom, and put visible windows (not
   unmapped, opacity > 0, etc) into a linked list, from bottom to top
2. Accumulate a region of ignore on each window, which is basically the
   region of screen that is obscured by all the windows above current
   one.
3. Paint all the visible windows from bottom to top. Subtract the region
   of ignore from the painting region. If we need to paint shadow, we
   subtract the body of the window from the shadow painting region too,
   because we don't want shadow behind the window.
4. region of ignore is invalidated when window stack change, an
   window on top moved or changed shape, when window changed between
   opaque and transparent, etc.

Notes:

It is unclear whether all the different shapes of a window (extents,
noframe, border, bounding shape, etc) are calculated correctly or not.

It is unclear if window shape related events are handled correctly or
not. Need more testing.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2018-09-30 04:56:00 +01:00
parent 56f7dd36f6
commit 28a2cc62fa
11 changed files with 691 additions and 1111 deletions

View File

@ -3,6 +3,7 @@
#include "common.h"
#include "config.h"
#include "utils.h"
#include "c2.h"
/**
@ -201,19 +202,24 @@ parse_conv_kern_lst(session_t *ps, const char *src, xcb_render_fixed_t **dest, i
/**
* Parse a X geometry.
*
* ps->root_width and ps->root_height must be valid
*/
bool
parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
parse_geometry(session_t *ps, const char *src, region_t *dest) {
pixman_region32_clear(dest);
if (!src)
return true;
if (!ps->root_width || !ps->root_height)
return true;
geometry_t geom = { .wid = -1, .hei = -1, .x = -1, .y = -1 };
long val = 0L;
char *endptr = NULL;
#define T_STRIPSPACE() do { \
while (*src && isspace(*src)) ++src; \
if (!*src) goto parse_geometry_end; \
} while(0)
T_STRIPSPACE();
src = skip_space(src);
if (!*src)
goto parse_geometry_end;
// Parse width
// Must be base 10, because "0x0..." may appear
@ -221,10 +227,13 @@ parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
val = strtol(src, &endptr, 10);
if (endptr && src != endptr) {
geom.wid = val;
assert(geom.wid >= 0);
if (geom.wid < 0) {
printf_errf("(\"%s\"): Invalid width.", src);
return false;
}
src = endptr;
}
T_STRIPSPACE();
src = skip_space(src);
}
// Parse height
@ -239,7 +248,7 @@ parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
}
src = endptr;
}
T_STRIPSPACE();
src = skip_space(src);
}
// Parse x
@ -247,11 +256,11 @@ parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
val = strtol(src, &endptr, 10);
if (endptr && src != endptr) {
geom.x = val;
if ('-' == *src && geom.x <= 0)
geom.x -= 2;
if (*src == '-')
geom.x += ps->root_width - geom.wid;
src = endptr;
}
T_STRIPSPACE();
src = skip_space(src);
}
// Parse y
@ -259,11 +268,11 @@ parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
val = strtol(src, &endptr, 10);
if (endptr && src != endptr) {
geom.y = val;
if ('-' == *src && geom.y <= 0)
geom.y -= 2;
if (*src == '-')
geom.y += ps->root_height - geom.hei;
src = endptr;
}
T_STRIPSPACE();
src = skip_space(src);
}
if (*src) {
@ -272,7 +281,7 @@ parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
}
parse_geometry_end:
*dest = geom;
pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei);
return true;
}