summaryrefslogtreecommitdiffstats
path: root/twin/compton-tde/compton.c
diff options
context:
space:
mode:
Diffstat (limited to 'twin/compton-tde/compton.c')
-rw-r--r--twin/compton-tde/compton.c156
1 files changed, 154 insertions, 2 deletions
diff --git a/twin/compton-tde/compton.c b/twin/compton-tde/compton.c
index dea363f60..d2095123f 100644
--- a/twin/compton-tde/compton.c
+++ b/twin/compton-tde/compton.c
@@ -944,6 +944,9 @@ static Bool
determine_window_transparency_filter_greyscale(const session_t *ps, Window w);
static Bool
+determine_window_transparency_filter_greyscale_blended(const session_t *ps, Window w);
+
+static Bool
determine_window_transparent_to_black(const session_t *ps, Window w);
static Bool
@@ -1590,6 +1593,7 @@ xr_greyscale_dst(session_t *ps, Picture tgt_buffer,
XRenderComposite(ps->dpy, PictOpSrc, ps->black_picture, None,
tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei);
+
XRenderComposite(ps->dpy, PictOpHSLLuminosity, tgt_buffer, None,
tmp_picture, x, y, 0, 0, 0, 0, wid, hei);
@@ -1723,7 +1727,7 @@ win_greyscale_background(session_t *ps, win *w, Picture tgt_buffer,
#ifdef CONFIG_VSYNC_OPENGL_GLSL
case BKEND_GLX:
glx_greyscale_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5,
- reg_paint, pcache_reg, &w->glx_greyscale_cache);
+ NULL, reg_paint, pcache_reg, &w->glx_greyscale_cache);
break;
#endif
default:
@@ -1821,6 +1825,71 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
Picture pict = w->paint.pict;
+ if (w->greyscale_blended_background) {
+ // Set window background to greyscale
+ switch (ps->o.backend) {
+ case BKEND_XRENDER:
+ case BKEND_XR_GLX_HYBRID:
+ {
+ // Blend here such that 0 window alpha is fully colored and 100 window alpha is fully greyscale
+ // PictOpInReverse is used to copy alpha from the source to the destination while preserving destination color
+ // provided that the source has alpha set to 1 (equivalent of CAIRO_OPERATOR_DEST_IN)
+ const int x = w->a.x;
+ const int y = w->a.y;
+ const int wid = w->widthb;
+ const int hei = w->heightb;
+ XserverRegion reg_clip = reg_paint;
+ Picture tgt_buffer = ps->tgt_buffer.pict;
+
+ // Apply clipping region to save some CPU
+ if (reg_paint) {
+ XserverRegion reg = copy_region(ps, reg_paint);
+ XFixesTranslateRegion(ps->dpy, reg, -x, -y);
+ XFixesSetPictureClipRegion(ps->dpy, pict, 0, 0, reg);
+ free_region(ps, &reg);
+ }
+
+ // Create greyscale version of background
+ Picture greyscale_picture = xr_build_picture(ps, wid, hei, w->pictfmt);
+ XRenderComposite(ps->dpy, PictOpSrc, tgt_buffer, None,
+ greyscale_picture, x, y, 0, 0, 0, 0, wid, hei);
+ win_greyscale_background(ps, w, greyscale_picture, reg_paint, pcache_reg);
+
+ Picture tmp_picture = xr_build_picture(ps, wid, hei, w->pictfmt);
+
+ if (!tmp_picture) {
+ printf_errf("(): Failed to build intermediate Picture.");
+ }
+ else {
+ if (reg_clip && tmp_picture)
+ XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_clip, 0, 0);
+
+ // Transfer greyscale picture to temporary picture
+ XRenderComposite(ps->dpy, PictOpSrc, greyscale_picture, None,
+ tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei);
+
+ // Transfer alpha of window to temporary picture
+ XRenderComposite(ps->dpy, PictOpInReverse, pict, None,
+ tmp_picture, 0, 0, 0, 0, 0, 0, wid, hei);
+
+ // Blend greyscale picture over main color buffer
+ XRenderComposite(ps->dpy, PictOpOver, tmp_picture, None, tgt_buffer,
+ 0, 0, 0, 0, x, y, wid, hei);
+
+ free_picture(ps, &tmp_picture);
+ free_picture(ps, &greyscale_picture);
+ }
+ }
+ break;
+#ifdef CONFIG_VSYNC_OPENGL
+ case BKEND_GLX:
+ glx_greyscale_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5,
+ w->paint.ptex, reg_paint, pcache_reg, &w->glx_greyscale_cache);
+ break;
+#endif
+ }
+ }
+
// Invert window color, if required
if (bkend_use_xrender(ps) && w->invert_color) {
Picture newpict = xr_build_picture(ps, wid, hei, w->pictfmt);
@@ -1846,7 +1915,12 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
}
}
- const double dopacity = get_opacity_percent(w);
+ double dopacity = get_opacity_percent(w);
+
+ if (w->greyscale_blended_background) {
+ double scaling_factor = (1.0 / w->greyscale_blended_background_alpha_divisor);
+ dopacity = dopacity * scaling_factor;
+ }
if (!w->frame_opacity) {
win_render(ps, w, 0, 0, wid, hei, dopacity, reg_paint, pcache_reg, pict);
@@ -2439,6 +2513,7 @@ map_win(session_t *ps, Window id) {
/* This needs to be here since we don't get PropertyNotify when unmapped */
w->opacity = wid_get_opacity_prop(ps, w->id, OPAQUE);
w->greyscale_background = determine_window_transparency_filter_greyscale(ps, id);
+ w->greyscale_blended_background = determine_window_transparency_filter_greyscale_blended(ps, id);
w->show_root_tile = determine_window_transparent_to_desktop(ps, id);
w->show_black_background = determine_window_transparent_to_black(ps, id);
@@ -2632,6 +2707,28 @@ get_window_transparency_filter_greyscale(const session_t *ps, Window w)
}
static Bool
+get_window_transparency_filter_greyscale_blended(const session_t *ps, Window w)
+{
+ Atom actual;
+ int format;
+ unsigned long n, left;
+
+ unsigned char *data;
+ int result = XGetWindowProperty (ps->dpy, w, ps->atom_win_type_tde_transparency_filter_greyscale_blend, 0L, 1L, False,
+ XA_ATOM, &actual, &format,
+ &n, &left, &data);
+
+ if (result == Success && data != None && format == 32 )
+ {
+ Atom a;
+ a = *(long*)data;
+ XFree ( (void *) data);
+ return True;
+ }
+ return False;
+}
+
+static Bool
get_window_transparent_to_desktop(const session_t *ps, Window w)
{
Atom actual;
@@ -2711,6 +2808,41 @@ determine_window_transparency_filter_greyscale (const session_t *ps, Window w)
}
static Bool
+determine_window_transparency_filter_greyscale_blended (const session_t *ps, Window w)
+{
+ Window root_return, parent_return;
+ Window *children = NULL;
+ unsigned int nchildren, i;
+ Bool type;
+
+ type = get_window_transparency_filter_greyscale_blended (ps, w);
+ if (type == True) {
+ return True;
+ }
+
+ if (!XQueryTree (ps->dpy, w, &root_return, &parent_return, &children,
+ &nchildren))
+ {
+ /* XQueryTree failed. */
+ if (children)
+ XFree ((void *)children);
+ return False;
+ }
+
+ for (i = 0;i < nchildren;i++)
+ {
+ type = determine_window_transparency_filter_greyscale_blended (ps, children[i]);
+ if (type == True)
+ return True;
+ }
+
+ if (children)
+ XFree ((void *)children);
+
+ return False;
+}
+
+static Bool
determine_window_transparent_to_desktop (const session_t *ps, Window w)
{
Window root_return, parent_return;
@@ -3449,6 +3581,8 @@ add_win(session_t *ps, Window id, Window prev) {
.blur_background = false,
.greyscale_background = false,
+ .greyscale_blended_background = false,
+ .greyscale_blended_background_alpha_divisor = 2,
.show_black_background = false,
.show_root_tile = false,
@@ -6696,6 +6830,7 @@ init_atoms(session_t *ps) {
ps->atom_win_type_tde_transparent_to_black = get_atom(ps, "_TDE_TRANSPARENT_TO_BLACK");
ps->atom_win_type_tde_transparent_to_desktop = get_atom(ps, "_TDE_TRANSPARENT_TO_DESKTOP");
ps->atom_win_type_tde_transparency_filter_greyscale = get_atom(ps, "_TDE_TRANSPARENCY_FILTER_GREYSCALE");
+ ps->atom_win_type_tde_transparency_filter_greyscale_blend = get_atom(ps, "_TDE_TRANSPARENCY_FILTER_GREYSCALE_BLEND");
}
#ifdef CONFIG_XRANDR
@@ -7136,6 +7271,22 @@ init_filters(session_t *ps) {
}
}
+ // Greyscale filter
+ switch (ps->o.backend) {
+ case BKEND_XRENDER:
+ case BKEND_XR_GLX_HYBRID:
+ {
+ break;
+ }
+#ifdef CONFIG_VSYNC_OPENGL
+ case BKEND_GLX:
+ {
+ if (!glx_init_greyscale(ps))
+ return false;
+ }
+#endif
+ }
+
return true;
}
@@ -7666,6 +7817,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
.atom_win_type_tde_transparent_to_black = None,
.atom_win_type_tde_transparent_to_desktop = None,
.atom_win_type_tde_transparency_filter_greyscale = None,
+ .atom_win_type_tde_transparency_filter_greyscale_blend = None,
.atoms_wintypes = { 0 },
.track_atom_lst = NULL,