Feature #75: Invert window color

- Add window color inversion (--invert-color-include). It means 2-3
  times extra painting, so performance issues are likely to appear.  I
  hope I could find a faster way to invert colors.

- Rename some functions.

- Fix update of some window properties after window type/data change.
  Hopefully this will be helpful for #73.

- Split win_build_picture() from win_blur_background().

- Correct memory leak of ps->focus_blacklist during reinitialization.

- Add win_upd_t and win_upd_run(), to reduce duplicate window property
  updates. But is unused right now.

- Limited tests are done overall. Bugs to be expected.
This commit is contained in:
Richard Grenville 2013-01-12 22:21:35 +08:00
parent 57c5854fd0
commit 2165c42d27
3 changed files with 222 additions and 58 deletions

View File

@ -48,6 +48,7 @@ unredir-if-possible = false;
focus-exclude = [ ]; focus-exclude = [ ];
detect-transient = true; detect-transient = true;
detect-client-leader = true; detect-client-leader = true;
invert-color-include = [ ];
# Window type settings # Window type settings
wintypes: wintypes:

View File

@ -1242,7 +1242,7 @@ paint_preprocess(session_t *ps, win *list) {
if (to_paint) { if (to_paint) {
// If opacity changes // If opacity changes
if (w->opacity != opacity_old) { if (w->opacity != opacity_old) {
determine_mode(ps, w); win_determine_mode(ps, w);
add_damage_win(ps, w); add_damage_win(ps, w);
} }
@ -1430,6 +1430,38 @@ win_paint_shadow(session_t *ps, win *w, Picture tgt_buffer) {
w->shadow_width, w->shadow_height); w->shadow_width, w->shadow_height);
} }
/**
* Create an alternative picture for a window.
*/
static inline Picture
win_build_picture(session_t *ps, win *w, Visual *visual) {
const int wid = w->widthb;
const int hei = w->heightb;
int depth = 0;
XRenderPictFormat *pictformat = NULL;
if (visual && ps->vis != visual) {
pictformat = XRenderFindVisualFormat(ps->dpy, visual);
depth = pictformat->depth;
}
else {
pictformat = XRenderFindVisualFormat(ps->dpy, ps->vis);
}
if (!depth)
depth = ps->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,
pictformat, 0, 0);
free_pixmap(ps, &tmp_pixmap);
return tmp_picture;
}
/** /**
* Blur the background of a window. * Blur the background of a window.
*/ */
@ -1451,24 +1483,17 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
}; };
Pixmap tmp_pixmap = None; const int x = w->a.x;
Picture tmp_picture = None; const int y = w->a.y;
const int wid = w->widthb;
int x = w->a.x; const int hei = w->heightb;
int y = w->a.y;
int wid = w->widthb;
int hei = w->heightb;
// Directly copying from tgt_buffer does not work, so we create a // Directly copying from tgt_buffer does not work, so we create a
// Picture in the middle. // Picture in the middle.
tmp_pixmap = XCreatePixmap(ps->dpy, ps->root, wid, hei, ps->depth); Picture tmp_picture = win_build_picture(ps, w, NULL);
if (!tmp_pixmap)
goto win_blur_background_err;
tmp_picture = XRenderCreatePicture(ps->dpy, tmp_pixmap,
XRenderFindVisualFormat(ps->dpy, ps->vis), 0, 0);
if (!tmp_picture) if (!tmp_picture)
goto win_blur_background_err; return;
// Adjust blur strength according to window opacity, to make it appear // Adjust blur strength according to window opacity, to make it appear
// better during fading // better during fading
@ -1496,8 +1521,6 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
xrfilter_reset(ps, tgt_buffer); xrfilter_reset(ps, tgt_buffer);
XRenderComposite(ps->dpy, PictOpSrc, tmp_picture, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); XRenderComposite(ps->dpy, PictOpSrc, tmp_picture, None, tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
win_blur_background_err:
free_pixmap(ps, &tmp_pixmap);
free_picture(ps, &tmp_picture); free_picture(ps, &tmp_picture);
} }
@ -1513,9 +1536,27 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
Picture alpha_mask = (OPAQUE == w->opacity ? None: w->alpha_pict); Picture alpha_mask = (OPAQUE == w->opacity ? None: w->alpha_pict);
int op = (w->mode == WMODE_SOLID ? PictOpSrc: PictOpOver); int op = (w->mode == WMODE_SOLID ? PictOpSrc: PictOpOver);
Picture pict = w->picture;
// Invert window color, if required
if (w->invert_color) {
Picture newpict = win_build_picture(ps, w, w->a.visual);
if (newpict) {
XRenderComposite(ps->dpy, PictOpSrc, pict, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
XRenderComposite(ps->dpy, PictOpDifference, ps->white_picture, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
// We use an extra PictOpInReverse operation to get correct pixel
// alpha. There could be a better solution.
if (WMODE_ARGB == w->mode)
XRenderComposite(ps->dpy, PictOpInReverse, pict, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
pict = newpict;
}
}
if (!w->frame_opacity) { if (!w->frame_opacity) {
XRenderComposite(ps->dpy, op, w->picture, alpha_mask, XRenderComposite(ps->dpy, op, pict, alpha_mask,
tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
} }
else { else {
@ -1526,7 +1567,7 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
const int r = w->a.border_width + w->right_width; const int r = w->a.border_width + w->right_width;
#define COMP_BDR(cx, cy, cwid, chei) \ #define COMP_BDR(cx, cy, cwid, chei) \
XRenderComposite(ps->dpy, PictOpOver, w->picture, w->frame_alpha_pict, \ XRenderComposite(ps->dpy, PictOpOver, pict, w->frame_alpha_pict, \
tgt_buffer, (cx), (cy), 0, 0, x + (cx), y + (cy), (cwid), (chei)) tgt_buffer, (cx), (cy), 0, 0, x + (cx), y + (cy), (cwid), (chei))
// The following complicated logic is required because some broken // The following complicated logic is required because some broken
@ -1562,7 +1603,7 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
pwid = wid - l - pwid; pwid = wid - l - pwid;
if (pwid > 0) { if (pwid > 0) {
// body // body
XRenderComposite(ps->dpy, op, w->picture, alpha_mask, XRenderComposite(ps->dpy, op, pict, alpha_mask,
tgt_buffer, l, t, 0, 0, x + l, y + t, pwid, phei); tgt_buffer, l, t, 0, 0, x + l, y + t, pwid, phei);
} }
} }
@ -1572,6 +1613,9 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
#undef COMP_BDR #undef COMP_BDR
if (pict != w->picture)
free_picture(ps, &pict);
// Dimming the window if needed // Dimming the window if needed
if (w->dim && w->dim_alpha_pict != ps->alpha_picts[0]) { if (w->dim && w->dim_alpha_pict != ps->alpha_picts[0]) {
XRenderComposite(ps->dpy, PictOpOver, ps->black_picture, XRenderComposite(ps->dpy, PictOpOver, ps->black_picture,
@ -1919,7 +1963,7 @@ map_win(session_t *ps, Window id) {
win_update_prop_shadow_raw(ps, w); win_update_prop_shadow_raw(ps, w);
// Many things above could affect shadow // Many things above could affect shadow
determine_shadow(ps, w); win_determine_shadow(ps, w);
// Set fading state // Set fading state
if (ps->o.no_fading_openclose) { if (ps->o.no_fading_openclose) {
@ -1930,7 +1974,7 @@ map_win(session_t *ps, Window id) {
} }
else { else {
set_fade_callback(ps, w, NULL, true); set_fade_callback(ps, w, NULL, true);
determine_fade(ps, w); win_determine_fade(ps, w);
} }
w->damaged = true; w->damaged = true;
@ -1947,7 +1991,7 @@ map_win(session_t *ps, Window id) {
static void static void
finish_map_win(session_t *ps, win *w) { finish_map_win(session_t *ps, win *w) {
if (ps->o.no_fading_openclose) if (ps->o.no_fading_openclose)
determine_fade(ps, w); win_determine_fade(ps, w);
} }
static void static void
@ -2015,7 +2059,7 @@ get_opacity_percent(win *w) {
} }
static void static void
determine_mode(session_t *ps, win *w) { win_determine_mode(session_t *ps, win *w) {
winmode_t mode = WMODE_SOLID; winmode_t mode = WMODE_SOLID;
XRenderPictFormat *format; XRenderPictFormat *format;
@ -2109,7 +2153,7 @@ calc_dim(session_t *ps, win *w) {
* Determine if a window should fade on opacity change. * Determine if a window should fade on opacity change.
*/ */
static void static void
determine_fade(session_t *ps, win *w) { win_determine_fade(session_t *ps, win *w) {
w->fade = ps->o.wintype_fade[w->window_type]; w->fade = ps->o.wintype_fade[w->window_type];
} }
@ -2136,7 +2180,7 @@ win_update_shape(session_t *ps, win *w) {
win_update_shape_raw(ps, w); win_update_shape_raw(ps, w);
// Shadow state could be changed // Shadow state could be changed
determine_shadow(ps, w); win_determine_shadow(ps, w);
/* /*
// If clear_shadow state on the window possibly changed, destroy the old // If clear_shadow state on the window possibly changed, destroy the old
@ -2178,7 +2222,7 @@ win_update_prop_shadow(session_t *ps, win *w) {
win_update_prop_shadow_raw(ps, w); win_update_prop_shadow_raw(ps, w);
if (w->prop_shadow != attr_shadow_old) if (w->prop_shadow != attr_shadow_old)
determine_shadow(ps, w); win_determine_shadow(ps, w);
} }
/** /**
@ -2186,7 +2230,7 @@ win_update_prop_shadow(session_t *ps, win *w) {
* on shadow state. * on shadow state.
*/ */
static void static void
determine_shadow(session_t *ps, win *w) { win_determine_shadow(session_t *ps, win *w) {
bool shadow_old = w->shadow; bool shadow_old = w->shadow;
w->shadow = (UNSET == w->shadow_force ? w->shadow = (UNSET == w->shadow_force ?
@ -2215,10 +2259,73 @@ determine_shadow(session_t *ps, win *w) {
} }
} }
/**
* Determine if a window should have color inverted.
*/
static void
win_determine_invert_color(session_t *ps, win *w) {
bool invert_color_old = w->invert_color;
if (UNSET != w->invert_color_force)
w->invert_color = w->invert_color_force;
else
w->invert_color = win_match(w, ps->o.invert_color_list, &w->cache_ivclst);
if (w->invert_color != invert_color_old)
add_damage_win(ps, w);
}
/**
* Function to be called on window type changes.
*/
static void
win_on_wtype_change(session_t *ps, win *w) {
win_determine_shadow(ps, w);
win_determine_fade(ps, w);
win_update_focused(ps, w);
}
/**
* Function to be called on window data changes.
*/
static void
win_on_wdata_change(session_t *ps, win *w) {
if (ps->o.shadow_blacklist)
win_determine_shadow(ps, w);
if (ps->o.fade_blacklist)
win_determine_fade(ps, w);
if (ps->o.invert_color_list)
win_determine_invert_color(ps, w);
if (ps->o.focus_blacklist)
win_update_focused(ps, w);
}
/**
* Process needed window updates.
*/
static void
win_upd_run(session_t *ps, win *w, win_upd_t *pupd) {
if (pupd->shadow) {
win_determine_shadow(ps, w);
pupd->shadow = false;
}
if (pupd->fade) {
win_determine_fade(ps, w);
pupd->fade = false;
}
if (pupd->invert_color) {
win_determine_invert_color(ps, w);
pupd->invert_color = false;
}
if (pupd->focus) {
win_update_focused(ps, w);
pupd->focus = false;
}
}
/** /**
* Update cache data in struct _win that depends on window size. * Update cache data in struct _win that depends on window size.
*/ */
static void static void
calc_win_size(session_t *ps, win *w) { calc_win_size(session_t *ps, win *w) {
w->widthb = w->a.width + w->a.border_width * 2; w->widthb = w->a.width + w->a.border_width * 2;
@ -2254,7 +2361,8 @@ win_mark_client(session_t *ps, win *w, Window client) {
if (IsViewable != w->a.map_state) if (IsViewable != w->a.map_state)
return; return;
XSelectInput(ps->dpy, client, determine_evmask(ps, client, WIN_EVMODE_CLIENT)); XSelectInput(ps->dpy, client,
determine_evmask(ps, client, WIN_EVMODE_CLIENT));
// Make sure the XSelectInput() requests are sent // Make sure the XSelectInput() requests are sent
XSync(ps->dpy, False); XSync(ps->dpy, False);
@ -2264,6 +2372,9 @@ win_mark_client(session_t *ps, win *w, Window client) {
get_frame_extents(ps, w, client); get_frame_extents(ps, w, client);
} }
{
wintype_t wtype_old = w->window_type;
// Detect window type here // Detect window type here
if (WINTYPE_UNKNOWN == w->window_type) if (WINTYPE_UNKNOWN == w->window_type)
w->window_type = wid_get_prop_wintype(ps, w->client_win); w->window_type = wid_get_prop_wintype(ps, w->client_win);
@ -2279,6 +2390,10 @@ win_mark_client(session_t *ps, win *w, Window client) {
w->window_type = WINTYPE_DIALOG; w->window_type = WINTYPE_DIALOG;
} }
if (w->window_type != wtype_old)
win_on_wtype_change(ps, w);
}
// Get window group // Get window group
if (ps->o.track_leader) if (ps->o.track_leader)
win_update_leader(ps, w); win_update_leader(ps, w);
@ -2288,6 +2403,7 @@ win_mark_client(session_t *ps, win *w, Window client) {
win_get_name(ps, w); win_get_name(ps, w);
win_get_class(ps, w); win_get_class(ps, w);
win_get_role(ps, w); win_get_role(ps, w);
win_on_wdata_change(ps, w);
} }
// Update window focus state // Update window focus state
@ -2393,6 +2509,7 @@ add_win(session_t *ps, Window id, Window prev) {
.cache_sblst = NULL, .cache_sblst = NULL,
.cache_fblst = NULL, .cache_fblst = NULL,
.cache_fcblst = NULL, .cache_fcblst = NULL,
.cache_ivclst = NULL,
.opacity = 0, .opacity = 0,
.opacity_tgt = 0, .opacity_tgt = 0,
@ -2423,6 +2540,9 @@ add_win(session_t *ps, Window id, Window prev) {
.dim = false, .dim = false,
.dim_alpha_pict = None, .dim_alpha_pict = None,
.invert_color = false,
.invert_color_force = UNSET,
}; };
// Reject overlay window and already added windows // Reject overlay window and already added windows
@ -3480,8 +3600,7 @@ ev_property_notify(session_t *ps, XPropertyEvent *ev) {
&& (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) { && (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) {
win *w = find_toplevel(ps, ev->window); win *w = find_toplevel(ps, ev->window);
if (w && 1 == win_get_name(ps, w)) { if (w && 1 == win_get_name(ps, w)) {
determine_shadow(ps, w); win_on_wdata_change(ps, w);
win_update_focused(ps, w);
} }
} }
@ -3490,8 +3609,7 @@ ev_property_notify(session_t *ps, XPropertyEvent *ev) {
win *w = find_toplevel(ps, ev->window); win *w = find_toplevel(ps, ev->window);
if (w) { if (w) {
win_get_class(ps, w); win_get_class(ps, w);
determine_shadow(ps, w); win_on_wdata_change(ps, w);
win_update_focused(ps, w);
} }
} }
@ -3499,8 +3617,7 @@ ev_property_notify(session_t *ps, XPropertyEvent *ev) {
if (ps->o.track_wdata && ps->atom_role == ev->atom) { if (ps->o.track_wdata && ps->atom_role == ev->atom) {
win *w = find_toplevel(ps, ev->window); win *w = find_toplevel(ps, ev->window);
if (w && 1 == win_get_role(ps, w)) { if (w && 1 == win_get_role(ps, w)) {
determine_shadow(ps, w); win_on_wdata_change(ps, w);
win_update_focused(ps, w);
} }
} }
@ -3816,6 +3933,9 @@ usage(void) {
"--blur-background-fixed\n" "--blur-background-fixed\n"
" Use fixed blur strength instead of adjusting according to window\n" " Use fixed blur strength instead of adjusting according to window\n"
" opacity.\n" " opacity.\n"
"--invert-color-include condition\n"
" Specify a list of conditions of windows that should be painted with\n"
" inverted color. Resource-hogging, and is not well tested.\n"
"\n" "\n"
"Format of a condition:\n" "Format of a condition:\n"
"\n" "\n"
@ -4242,6 +4362,8 @@ parse_config(session_t *ps, char *cpath, struct options_tmp *pcfgtmp) {
parse_cfg_condlst(&cfg, &ps->o.shadow_blacklist, "shadow-exclude"); parse_cfg_condlst(&cfg, &ps->o.shadow_blacklist, "shadow-exclude");
// --focus-exclude // --focus-exclude
parse_cfg_condlst(&cfg, &ps->o.focus_blacklist, "focus-exclude"); parse_cfg_condlst(&cfg, &ps->o.focus_blacklist, "focus-exclude");
// --invert-color-include
parse_cfg_condlst(&cfg, &ps->o.invert_color_list, "invert-color-include");
// --blur-background // --blur-background
lcfg_lookup_bool(&cfg, "blur-background", &ps->o.blur_background); lcfg_lookup_bool(&cfg, "blur-background", &ps->o.blur_background);
// --blur-background-frame // --blur-background-frame
@ -4315,6 +4437,7 @@ get_cfg(session_t *ps, int argc, char *const *argv) {
{ "blur-background-fixed", no_argument, NULL, 285 }, { "blur-background-fixed", no_argument, NULL, 285 },
{ "dbus", no_argument, NULL, 286 }, { "dbus", no_argument, NULL, 286 },
{ "logpath", required_argument, NULL, 287 }, { "logpath", required_argument, NULL, 287 },
{ "invert-color-include", required_argument, NULL, 288 },
// Must terminate with a NULL entry // Must terminate with a NULL entry
{ NULL, 0, NULL, 0 }, { NULL, 0, NULL, 0 },
}; };
@ -4554,6 +4677,10 @@ get_cfg(session_t *ps, int argc, char *const *argv) {
// --logpath // --logpath
ps->o.logpath = mstrcpy(optarg); ps->o.logpath = mstrcpy(optarg);
break; break;
case 288:
// --invert-color-include
condlst_add(&ps->o.invert_color_list, optarg);
break;
default: default:
usage(); usage();
break; break;
@ -5291,12 +5418,14 @@ session_init(session_t *ps_old, int argc, char **argv) {
.inactive_opacity_override = false, .inactive_opacity_override = false,
.frame_opacity = 0.0, .frame_opacity = 0.0,
.detect_client_opacity = false, .detect_client_opacity = false,
.inactive_dim = 0.0,
.inactive_dim_fixed = false,
.alpha_step = 0.03, .alpha_step = 0.03,
.blur_background = false, .blur_background = false,
.blur_background_frame = false, .blur_background_frame = false,
.blur_background_fixed = false, .blur_background_fixed = false,
.inactive_dim = 0.0,
.inactive_dim_fixed = false,
.invert_color_list = NULL,
.wintype_focus = { false }, .wintype_focus = { false },
.use_ewmh_active_win = false, .use_ewmh_active_win = false,
@ -5337,6 +5466,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
.black_picture = None, .black_picture = None,
.cshadow_picture = None, .cshadow_picture = None,
.white_picture = None,
.gaussian_map = NULL, .gaussian_map = NULL,
.cgsize = 0, .cgsize = 0,
.shadow_corner = NULL, .shadow_corner = NULL,
@ -5555,6 +5685,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
init_filters(ps); init_filters(ps);
ps->black_picture = solid_picture(ps, true, 1, 0, 0, 0); ps->black_picture = solid_picture(ps, true, 1, 0, 0, 0);
ps->white_picture = solid_picture(ps, true, 1, 1, 1, 1);
// Generates another Picture for shadows if the color is modified by // Generates another Picture for shadows if the color is modified by
// user // user
@ -5658,6 +5789,8 @@ session_destroy(session_t *ps) {
// Free blacklists // Free blacklists
free_wincondlst(&ps->o.shadow_blacklist); free_wincondlst(&ps->o.shadow_blacklist);
free_wincondlst(&ps->o.fade_blacklist); free_wincondlst(&ps->o.fade_blacklist);
free_wincondlst(&ps->o.focus_blacklist);
free_wincondlst(&ps->o.invert_color_list);
// Free ignore linked list // Free ignore linked list
{ {
@ -5680,6 +5813,7 @@ session_destroy(session_t *ps) {
free_picture(ps, &ps->cshadow_picture); free_picture(ps, &ps->cshadow_picture);
free_picture(ps, &ps->black_picture); free_picture(ps, &ps->black_picture);
free_picture(ps, &ps->white_picture);
// Free tgt_{buffer,picture} and root_picture // Free tgt_{buffer,picture} and root_picture
if (ps->tgt_buffer == ps->tgt_picture) if (ps->tgt_buffer == ps->tgt_picture)

View File

@ -211,6 +211,14 @@ typedef enum {
WMODE_ARGB WMODE_ARGB
} winmode_t; } winmode_t;
/// Structure representing needed window updates.
typedef struct {
bool shadow : 1;
bool fade : 1;
bool focus : 1;
bool invert_color : 1;
} win_upd_t;
/// Structure representing Window property value. /// Structure representing Window property value.
typedef struct { typedef struct {
// All pointers have the same length, right? // All pointers have the same length, right?
@ -363,13 +371,10 @@ typedef struct {
/// Whether to detect _NET_WM_OPACITY on client windows. Used on window /// Whether to detect _NET_WM_OPACITY on client windows. Used on window
/// managers that don't pass _NET_WM_OPACITY to frame windows. /// managers that don't pass _NET_WM_OPACITY to frame windows.
bool detect_client_opacity; bool detect_client_opacity;
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
double inactive_dim;
/// Whether to use fixed inactive dim opacity, instead of deciding
/// based on window opacity.
bool inactive_dim_fixed;
/// Step for pregenerating alpha pictures. 0.01 - 1.0. /// Step for pregenerating alpha pictures. 0.01 - 1.0.
double alpha_step; double alpha_step;
// === Other window processing ===
/// Whether to blur background of semi-transparent / ARGB windows. /// Whether to blur background of semi-transparent / ARGB windows.
bool blur_background; bool blur_background;
/// Whether to blur background when the window frame is not opaque. /// Whether to blur background when the window frame is not opaque.
@ -378,6 +383,13 @@ typedef struct {
/// Whether to use fixed blur strength instead of adjusting according /// Whether to use fixed blur strength instead of adjusting according
/// to window opacity. /// to window opacity.
bool blur_background_fixed; bool blur_background_fixed;
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
double inactive_dim;
/// Whether to use fixed inactive dim opacity, instead of deciding
/// based on window opacity.
bool inactive_dim_fixed;
/// Conditions of windows to have inverted colors.
wincond_t *invert_color_list;
// === Focus related === // === Focus related ===
/// Consider windows of specific types to be always focused. /// Consider windows of specific types to be always focused.
@ -398,7 +410,6 @@ typedef struct {
bool track_wdata; bool track_wdata;
/// Whether compton needs to track window leaders. /// Whether compton needs to track window leaders.
bool track_leader; bool track_leader;
} options_t; } options_t;
/// Structure containing all necessary data for a compton session. /// Structure containing all necessary data for a compton session.
@ -505,6 +516,8 @@ typedef struct {
Picture black_picture; Picture black_picture;
/// 1x1 Picture of the shadow color. /// 1x1 Picture of the shadow color.
Picture cshadow_picture; Picture cshadow_picture;
/// 1x1 white Picture.
Picture white_picture;
/// Gaussian map of shadow. /// Gaussian map of shadow.
conv *gaussian_map; conv *gaussian_map;
// for shadow precomputation // for shadow precomputation
@ -699,6 +712,7 @@ typedef struct _win {
wincond_t *cache_sblst; wincond_t *cache_sblst;
wincond_t *cache_fblst; wincond_t *cache_fblst;
wincond_t *cache_fcblst; wincond_t *cache_fcblst;
wincond_t *cache_ivclst;
// Opacity-related members // Opacity-related members
/// Current window opacity. /// Current window opacity.
@ -758,6 +772,12 @@ typedef struct _win {
/// Picture for dimming. Affected by user-specified inactive dim /// Picture for dimming. Affected by user-specified inactive dim
/// opacity and window opacity. /// opacity and window opacity.
Picture dim_alpha_pict; Picture dim_alpha_pict;
/// Whether to invert window color.
bool invert_color;
/// Override value of window color inversion state. Set by D-Bus method
/// calls.
switch_t invert_color_force;
} win; } win;
/// Temporary structure used for communication between /// Temporary structure used for communication between
@ -1860,7 +1880,7 @@ static double
get_opacity_percent(win *w); get_opacity_percent(win *w);
static void static void
determine_mode(session_t *ps, win *w); win_determine_mode(session_t *ps, win *w);
static void static void
calc_opacity(session_t *ps, win *w); calc_opacity(session_t *ps, win *w);
@ -1902,7 +1922,7 @@ static inline void
win_set_focused(session_t *ps, win *w, bool focused); win_set_focused(session_t *ps, win *w, bool focused);
static void static void
determine_fade(session_t *ps, win *w); win_determine_fade(session_t *ps, win *w);
static void static void
win_update_shape_raw(session_t *ps, win *w); win_update_shape_raw(session_t *ps, win *w);
@ -1917,7 +1937,16 @@ static void
win_update_prop_shadow(session_t *ps, win *w); win_update_prop_shadow(session_t *ps, win *w);
static void static void
determine_shadow(session_t *ps, win *w); win_determine_shadow(session_t *ps, win *w);
static void
win_on_wtype_change(session_t *ps, win *w);
static void
win_on_wdata_change(session_t *ps, win *w);
static void
win_upd_run(session_t *ps, win *w, win_upd_t *pupd);
static void static void
calc_win_size(session_t *ps, win *w); calc_win_size(session_t *ps, win *w);