Move w->bounding_shape to local coordinates
This way we don't need to update the bounding region after window moves. Also add some comments about the coordinate systems in compton. Also change a few function that takes a `bool global` parameter to always return region in local coordinates.
This commit is contained in:
parent
4f071ffc30
commit
aa2098eefd
13
src/common.h
13
src/common.h
|
@ -1028,6 +1028,16 @@ typedef struct session {
|
||||||
#endif
|
#endif
|
||||||
} session_t;
|
} session_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* About coordinate systems
|
||||||
|
*
|
||||||
|
* In general, X is the horizontal axis, Y is the vertical axis.
|
||||||
|
* X goes from left to right, Y goes downwards.
|
||||||
|
*
|
||||||
|
* Global: the origin is the top left corner of the Xorg screen.
|
||||||
|
* Local: the origin is the top left corner of the window, including border.
|
||||||
|
*/
|
||||||
|
|
||||||
/// Structure representing a top-level window compton manages.
|
/// Structure representing a top-level window compton manages.
|
||||||
struct win {
|
struct win {
|
||||||
/// Pointer to the next lower window in window stack.
|
/// Pointer to the next lower window in window stack.
|
||||||
|
@ -1061,7 +1071,8 @@ struct win {
|
||||||
xcb_damage_damage_t damage;
|
xcb_damage_damage_t damage;
|
||||||
/// Paint info of the window.
|
/// Paint info of the window.
|
||||||
paint_t paint;
|
paint_t paint;
|
||||||
/// Bounding shape of the window.
|
/// Bounding shape of the window. In local coordinates.
|
||||||
|
/// See above about coordinate systems.
|
||||||
region_t bounding_shape;
|
region_t bounding_shape;
|
||||||
/// Window flags. Definitions above.
|
/// Window flags. Definitions above.
|
||||||
int_fast16_t flags;
|
int_fast16_t flags;
|
||||||
|
|
|
@ -654,6 +654,7 @@ static bool
|
||||||
win_build_shadow(session_t *ps, win *w, double opacity) {
|
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;
|
||||||
|
//printf_errf("(): building shadow for %s %d %d", w->name, width, height);
|
||||||
|
|
||||||
xcb_image_t *shadow_image = NULL;
|
xcb_image_t *shadow_image = NULL;
|
||||||
xcb_pixmap_t shadow_pixmap = None, shadow_pixmap_argb = None;
|
xcb_pixmap_t shadow_pixmap = None, shadow_pixmap_argb = None;
|
||||||
|
@ -1113,6 +1114,7 @@ paint_preprocess(session_t *ps, win *list) {
|
||||||
|| 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)
|
||||||
to_paint = false;
|
to_paint = false;
|
||||||
|
//printf_errf("(): %s %d %d %d", w->name, to_paint, w->opacity, w->paint_excluded);
|
||||||
|
|
||||||
// Add window to damaged area if its painting status changes
|
// Add window to damaged area if its painting status changes
|
||||||
// or opacity changes
|
// or opacity changes
|
||||||
|
@ -1125,11 +1127,6 @@ paint_preprocess(session_t *ps, win *list) {
|
||||||
if (!to_paint)
|
if (!to_paint)
|
||||||
goto skip_window;
|
goto skip_window;
|
||||||
|
|
||||||
// XXX shouldn't need these
|
|
||||||
// Fetch bounding region
|
|
||||||
if (!pixman_region32_not_empty(&w->bounding_shape))
|
|
||||||
win_update_bounding_shape(ps, w);
|
|
||||||
|
|
||||||
// Fetch window extents
|
// Fetch window extents
|
||||||
region_t extents;
|
region_t extents;
|
||||||
pixman_region32_init(&extents);
|
pixman_region32_init(&extents);
|
||||||
|
@ -1148,10 +1145,11 @@ paint_preprocess(session_t *ps, win *list) {
|
||||||
if (w->mode == WMODE_SOLID && !ps->o.force_win_blend) {
|
if (w->mode == WMODE_SOLID && !ps->o.force_win_blend) {
|
||||||
region_t *tmp = rc_region_new();
|
region_t *tmp = rc_region_new();
|
||||||
if (w->frame_opacity == 1)
|
if (w->frame_opacity == 1)
|
||||||
copy_region(tmp, &w->bounding_shape);
|
*tmp = win_get_bounding_shape_global_by_val(w);
|
||||||
else {
|
else {
|
||||||
win_get_region_noframe(ps, w, true, tmp);
|
win_get_region_noframe_local(ps, w, tmp);
|
||||||
pixman_region32_intersect(tmp, tmp, &w->bounding_shape);
|
pixman_region32_intersect(tmp, tmp, &w->bounding_shape);
|
||||||
|
pixman_region32_translate(tmp, w->g.x, w->g.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_union(tmp, tmp, last_reg_ignore);
|
pixman_region32_union(tmp, tmp, last_reg_ignore);
|
||||||
|
@ -1389,13 +1387,12 @@ win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
||||||
|
|
||||||
// Minimize the region we try to blur, if the window itself is not
|
// Minimize the region we try to blur, if the window itself is not
|
||||||
// opaque, only the frame is.
|
// opaque, only the frame is.
|
||||||
region_t reg_blur;
|
region_t reg_blur = win_get_bounding_shape_global_by_val(w);
|
||||||
pixman_region32_init(®_blur);
|
|
||||||
pixman_region32_copy(®_blur, &w->bounding_shape);
|
|
||||||
if (win_is_solid(ps, w)) {
|
if (win_is_solid(ps, w)) {
|
||||||
region_t reg_noframe;
|
region_t reg_noframe;
|
||||||
pixman_region32_init(®_noframe);
|
pixman_region32_init(®_noframe);
|
||||||
win_get_region_noframe(ps, w, true, ®_noframe);
|
win_get_region_noframe_local(ps, w, ®_noframe);
|
||||||
|
pixman_region32_translate(®_noframe, w->g.x, w->g.y);
|
||||||
pixman_region32_subtract(®_blur, ®_blur, ®_noframe);
|
pixman_region32_subtract(®_blur, ®_blur, ®_noframe);
|
||||||
pixman_region32_fini(®_noframe);
|
pixman_region32_fini(®_noframe);
|
||||||
}
|
}
|
||||||
|
@ -1754,6 +1751,7 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co
|
||||||
//
|
//
|
||||||
// Whether this is beneficial is to be determined XXX
|
// Whether this is beneficial is to be determined XXX
|
||||||
for (win *w = t; w; w = w->prev_trans) {
|
for (win *w = t; w; w = w->prev_trans) {
|
||||||
|
region_t bshape = win_get_bounding_shape_global_by_val(w);
|
||||||
// Painting shadow
|
// Painting shadow
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
// Lazy shadow building
|
// Lazy shadow building
|
||||||
|
@ -1777,7 +1775,7 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co
|
||||||
// Mask out the body of the window from the shadow
|
// Mask out the body of the window from the shadow
|
||||||
// Doing it here instead of in make_shadow() for saving GPU
|
// Doing it here instead of in make_shadow() for saving GPU
|
||||||
// power and handling shaped windows (XXX unconfirmed)
|
// power and handling shaped windows (XXX unconfirmed)
|
||||||
pixman_region32_subtract(®_tmp, ®_tmp, &w->bounding_shape);
|
pixman_region32_subtract(®_tmp, ®_tmp, &bshape);
|
||||||
|
|
||||||
#ifdef CONFIG_XINERAMA
|
#ifdef CONFIG_XINERAMA
|
||||||
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0)
|
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0)
|
||||||
|
@ -1796,7 +1794,8 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co
|
||||||
// window and the bounding region
|
// window and the bounding region
|
||||||
// XXX XXX
|
// XXX XXX
|
||||||
pixman_region32_subtract(®_tmp, region, w->reg_ignore);
|
pixman_region32_subtract(®_tmp, region, w->reg_ignore);
|
||||||
pixman_region32_intersect(®_tmp, ®_tmp, &w->bounding_shape);
|
pixman_region32_intersect(®_tmp, ®_tmp, &bshape);
|
||||||
|
pixman_region32_fini(&bshape);
|
||||||
|
|
||||||
if (pixman_region32_not_empty(®_tmp)) {
|
if (pixman_region32_not_empty(®_tmp)) {
|
||||||
set_tgt_clip(ps, ®_tmp);
|
set_tgt_clip(ps, ®_tmp);
|
||||||
|
@ -2280,18 +2279,12 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
||||||
// If window geometry change, free old extents
|
// If window geometry change, free old extents
|
||||||
if (w->g.x != ce->x || w->g.y != ce->y
|
if (w->g.x != ce->x || w->g.y != ce->y
|
||||||
|| w->g.width != ce->width || w->g.height != ce->height
|
|| w->g.width != ce->width || w->g.height != ce->height
|
||||||
|| w->g.border_width != ce->border_width) {
|
|| w->g.border_width != ce->border_width)
|
||||||
factor_change = true;
|
factor_change = true;
|
||||||
pixman_region32_clear(&w->bounding_shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
w->g.x = ce->x;
|
w->g.x = ce->x;
|
||||||
w->g.y = ce->y;
|
w->g.y = ce->y;
|
||||||
|
|
||||||
if (w->g.width != ce->width || w->g.height != ce->height
|
|
||||||
|| w->g.border_width != ce->border_width)
|
|
||||||
free_wpaint(ps, w);
|
|
||||||
|
|
||||||
if (w->g.width != ce->width || w->g.height != ce->height
|
if (w->g.width != ce->width || w->g.height != ce->height
|
||||||
|| w->g.border_width != ce->border_width) {
|
|| w->g.border_width != ce->border_width) {
|
||||||
w->g.width = ce->width;
|
w->g.width = ce->width;
|
||||||
|
@ -2310,7 +2303,6 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
||||||
if (factor_change) {
|
if (factor_change) {
|
||||||
add_damage(ps, &damage);
|
add_damage(ps, &damage);
|
||||||
cxinerama_win_upd_scr(ps, w);
|
cxinerama_win_upd_scr(ps, w);
|
||||||
win_on_factor_change(ps, w);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2981,10 +2973,17 @@ ev_shape_notify(session_t *ps, xcb_shape_notify_event_t *ev) {
|
||||||
* if we attempt to rebuild border_size
|
* if we attempt to rebuild border_size
|
||||||
*/
|
*/
|
||||||
// Mark the old border_size as damaged
|
// Mark the old border_size as damaged
|
||||||
add_damage(ps, &w->bounding_shape);
|
region_t tmp = win_get_bounding_shape_global_by_val(w);
|
||||||
|
add_damage(ps, &tmp);
|
||||||
|
pixman_region32_fini(&tmp);
|
||||||
|
|
||||||
win_update_bounding_shape(ps, w);
|
win_update_bounding_shape(ps, w);
|
||||||
|
|
||||||
// Mark the new border_size as damaged
|
// Mark the new border_size as damaged
|
||||||
add_damage(ps, &w->bounding_shape);
|
tmp = win_get_bounding_shape_global_by_val(w);
|
||||||
|
add_damage(ps, &tmp);
|
||||||
|
pixman_region32_fini(&tmp);
|
||||||
|
|
||||||
w->reg_ignore_valid = false;
|
w->reg_ignore_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
43
src/win.c
43
src/win.c
|
@ -16,6 +16,16 @@
|
||||||
|
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
|
|
||||||
|
/// Generate a "return by value" function, from a function that returns the
|
||||||
|
/// region via a region_t pointer argument.
|
||||||
|
/// Function signature has to be (win *, region_t *)
|
||||||
|
#define gen_by_val(fun) void region_t fun##_by_val(win *w) { \
|
||||||
|
region_t ret; \
|
||||||
|
pixman_region32_init(&ret); \
|
||||||
|
fun(w, &ret); \
|
||||||
|
return ret; \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear leader cache of all windows.
|
* Clear leader cache of all windows.
|
||||||
*/
|
*/
|
||||||
|
@ -78,23 +88,20 @@ group_is_focused(session_t *ps, Window leader) {
|
||||||
/**
|
/**
|
||||||
* Get a rectangular region a window occupies, excluding shadow.
|
* Get a rectangular region a window occupies, excluding shadow.
|
||||||
*/
|
*/
|
||||||
void win_get_region(session_t *ps, win *w, bool global, region_t *res) {
|
static void win_get_region_local(session_t *ps, win *w, region_t *res) {
|
||||||
pixman_region32_fini(res);
|
pixman_region32_fini(res);
|
||||||
pixman_region32_init_rect(res,
|
pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb);
|
||||||
global ? w->g.x : 0,
|
|
||||||
global ? w->g.y : 0,
|
|
||||||
w->widthb, w->heightb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a rectangular region a window occupies, excluding frame and shadow.
|
* Get a rectangular region a window occupies, excluding frame and shadow.
|
||||||
*/
|
*/
|
||||||
void win_get_region_noframe(session_t *ps, win *w, bool global, region_t *res) {
|
void win_get_region_noframe_local(session_t *ps, win *w, region_t *res) {
|
||||||
const margin_t extents = win_calc_frame_extents(ps, w);
|
const margin_t extents = win_calc_frame_extents(ps, w);
|
||||||
|
|
||||||
int x = (global ? w->g.x: 0) + extents.left;
|
int x = extents.left;
|
||||||
int y = (global ? w->g.y: 0) + extents.top;
|
int y = extents.top;
|
||||||
int width = max_i(w->g.width - extents.left - extents.right, 0);
|
int width = max_i(w->g.width - extents.left - extents.right, 0);
|
||||||
int height = max_i(w->g.height - extents.top - extents.bottom, 0);
|
int height = max_i(w->g.height - extents.top - extents.bottom, 0);
|
||||||
|
|
||||||
|
@ -880,6 +887,7 @@ bool add_win(session_t *ps, Window id, Window prev) {
|
||||||
|
|
||||||
new->next = *p;
|
new->next = *p;
|
||||||
*p = new;
|
*p = new;
|
||||||
|
win_update_bounding_shape(ps, new);
|
||||||
|
|
||||||
#ifdef CONFIG_DBUS
|
#ifdef CONFIG_DBUS
|
||||||
// Send D-Bus signal
|
// Send D-Bus signal
|
||||||
|
@ -1144,10 +1152,11 @@ void win_update_bounding_shape(session_t *ps, win *w) {
|
||||||
|
|
||||||
pixman_region32_clear(&w->bounding_shape);
|
pixman_region32_clear(&w->bounding_shape);
|
||||||
// Start with the window rectangular region
|
// Start with the window rectangular region
|
||||||
win_get_region(ps, w, true, &w->bounding_shape);
|
win_get_region_local(ps, w, &w->bounding_shape);
|
||||||
|
|
||||||
// Only request for a bounding region if the window is shaped
|
// Only request for a bounding region if the window is shaped
|
||||||
if (w->bounding_shaped) {
|
// (while loop is used to avoid goto, not an actual loop)
|
||||||
|
while (w->bounding_shaped) {
|
||||||
/*
|
/*
|
||||||
* if window doesn't exist anymore, this will generate an error
|
* if window doesn't exist anymore, this will generate an error
|
||||||
* as well as not generate a region.
|
* as well as not generate a region.
|
||||||
|
@ -1157,7 +1166,7 @@ void win_update_bounding_shape(session_t *ps, win *w) {
|
||||||
xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
|
xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
return;
|
break;
|
||||||
|
|
||||||
xcb_rectangle_t *xrects = xcb_shape_get_rectangles_rectangles(r);
|
xcb_rectangle_t *xrects = xcb_shape_get_rectangles_rectangles(r);
|
||||||
int nrects = xcb_shape_get_rectangles_rectangles_length(r);
|
int nrects = xcb_shape_get_rectangles_rectangles_length(r);
|
||||||
|
@ -1171,22 +1180,24 @@ void win_update_bounding_shape(session_t *ps, win *w) {
|
||||||
// Add border width because we are using a different origin.
|
// Add border width because we are using a different origin.
|
||||||
// X thinks the top left of the inner window is the origin,
|
// X thinks the top left of the inner window is the origin,
|
||||||
// We think the top left of the border is the origin
|
// We think the top left of the border is the origin
|
||||||
pixman_region32_translate(&br, w->g.x + w->g.border_width,
|
pixman_region32_translate(&br, w->g.border_width, w->g.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
|
||||||
// make sure the bounding region is not bigger than the window
|
// make sure the bounding region is not bigger than the window
|
||||||
// rectangle
|
// rectangle
|
||||||
pixman_region32_intersect(&w->bounding_shape, &w->bounding_shape, &br);
|
pixman_region32_intersect(&w->bounding_shape, &w->bounding_shape, &br);
|
||||||
pixman_region32_fini(&br);
|
pixman_region32_fini(&br);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->bounding_shaped && ps->o.detect_rounded_corners)
|
if (w->bounding_shaped && ps->o.detect_rounded_corners)
|
||||||
win_rounded_corners(ps, w);
|
win_rounded_corners(ps, w);
|
||||||
|
|
||||||
// XXX Window shape changed, and if we didn't fill in the pixels
|
// Window shape changed, we should free old wpaint and shadow pict
|
||||||
// behind the window (not implemented yet), we should rebuild
|
free_wpaint(ps, w);
|
||||||
// the shadow_pict
|
free_paint(ps, &w->shadow_paint);
|
||||||
|
//printf_errf("(): free out dated pict");
|
||||||
|
|
||||||
win_on_factor_change(ps, w);
|
win_on_factor_change(ps, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/win.h
19
src/win.h
|
@ -70,16 +70,12 @@ void win_extents(win *w, region_t *res);
|
||||||
* @param w struct _win element representing the window
|
* @param w struct _win element representing the window
|
||||||
*/
|
*/
|
||||||
void add_damage_from_win(session_t *ps, win *w);
|
void add_damage_from_win(session_t *ps, win *w);
|
||||||
/**
|
|
||||||
* Get a rectangular region a window occupies, excluding shadow.
|
|
||||||
*
|
|
||||||
* global = use global coordinates
|
|
||||||
*/
|
|
||||||
void win_get_region(session_t *ps, win *w, bool global, region_t *);
|
|
||||||
/**
|
/**
|
||||||
* Get a rectangular region a window occupies, excluding frame and shadow.
|
* Get a rectangular region a window occupies, excluding frame and shadow.
|
||||||
|
*
|
||||||
|
* Return region in global coordinates.
|
||||||
*/
|
*/
|
||||||
void win_get_region_noframe(session_t *ps, win *w, bool global, region_t *);
|
void win_get_region_noframe_local(session_t *ps, win *w, region_t *);
|
||||||
/**
|
/**
|
||||||
* Retrieve frame extents from a window.
|
* Retrieve frame extents from a window.
|
||||||
*/
|
*/
|
||||||
|
@ -102,3 +98,12 @@ bool win_has_alpha(win *w);
|
||||||
|
|
||||||
/// check if reg_ignore_valid is true for all windows above us
|
/// check if reg_ignore_valid is true for all windows above us
|
||||||
bool win_is_region_ignore_valid(session_t *ps, win *w);
|
bool win_is_region_ignore_valid(session_t *ps, win *w);
|
||||||
|
|
||||||
|
static inline region_t
|
||||||
|
win_get_bounding_shape_global_by_val(win *w) {
|
||||||
|
region_t ret;
|
||||||
|
pixman_region32_init(&ret);
|
||||||
|
pixman_region32_copy(&ret, &w->bounding_shape);
|
||||||
|
pixman_region32_translate(&ret, w->g.x, w->g.y);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue