diff --git a/src/c2.c b/src/c2.c index 948bbe6..0fe1c6e 100644 --- a/src/c2.c +++ b/src/c2.c @@ -26,6 +26,7 @@ #endif #include "common.h" +#include "win.h" #include "c2.h" #define C2_MAX_LEVELS 10 @@ -1398,7 +1399,7 @@ c2_match_once_leaf(session_t *ps, win *w, const c2_l_t *pleaf, 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; + case C2_L_PARGB: tgt = win_has_alpha(w); break; case C2_L_PFOCUSED: tgt = win_is_focused_real(ps, w); break; case C2_L_PWMWIN: tgt = w->wmwin; break; case C2_L_PBSHAPED: tgt = w->bounding_shaped; break; diff --git a/src/common.h b/src/common.h index 6f1c6c8..6842c38 100644 --- a/src/common.h +++ b/src/common.h @@ -273,9 +273,9 @@ typedef struct { /// Enumeration type of window painting mode. typedef enum { - WMODE_TRANS, - WMODE_SOLID, - WMODE_ARGB + WMODE_TRANS, // The window body is (potentially) transparent + WMODE_FRAME_TRANS, // The window body is opaque, but the frame is not + WMODE_SOLID, // The window is opaque including the frame } winmode_t; /// Structure representing needed window updates. diff --git a/src/compton.c b/src/compton.c index be62eb5..1e08a50 100644 --- a/src/compton.c +++ b/src/compton.c @@ -1511,7 +1511,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, 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) + if (win_has_alpha(w)) xcb_render_composite(c, XCB_RENDER_PICT_OP_IN_REVERSE, pict, None, newpict, 0, 0, 0, 0, 0, 0, wid, hei); pict = newpict; diff --git a/src/compton.h b/src/compton.h index bb755c6..3afd29a 100644 --- a/src/compton.h +++ b/src/compton.h @@ -497,13 +497,14 @@ find_win_all(session_t *ps, const Window wid) { render_(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict, ptex, reg_paint, pcache_reg) #endif +bool win_has_alpha(win *); 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, xcb_render_picture_t pict) { 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 argb = (w && (win_has_alpha(w) || ps->o.force_win_blend)); const bool neg = (w && w->invert_color); render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, diff --git a/src/win.c b/src/win.c index af7ac92..ff912f0 100644 --- a/src/win.c +++ b/src/win.c @@ -281,19 +281,21 @@ bool wid_get_opacity_prop(session_t *ps, Window wid, opacity_t def, return ret; } +// XXX should distinguish between frame has alpha and window body has alpha +bool win_has_alpha(win *w) { + return w->pictfmt && + w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT && + w->pictfmt->direct.alpha_mask; +} + void win_determine_mode(session_t *ps, win *w) { - winmode_t mode = WMODE_SOLID; - - if (w->pictfmt && w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT && - w->pictfmt->direct.alpha_mask) { - mode = WMODE_ARGB; - } else if (w->opacity != OPAQUE) { - mode = WMODE_TRANS; + if (win_has_alpha(w) || w->opacity != OPAQUE) { + w->mode = WMODE_TRANS; + } else if (w->frame_opacity) { + w->mode = WMODE_FRAME_TRANS; } else { - mode = WMODE_SOLID; + w->mode = WMODE_SOLID; } - - w->mode = mode; } /** @@ -375,7 +377,7 @@ void win_determine_fade(session_t *ps, win *w) { else if (ps->o.no_fading_openclose && w->in_openclose) w->fade_last = w->fade = false; else if (ps->o.no_fading_destroyed_argb && w->destroyed && - WMODE_ARGB == w->mode && w->client_win && w->client_win != w->id) { + win_has_alpha(w) && w->client_win && w->client_win != w->id) { w->fade_last = w->fade = false; } // Ignore other possible causes of fading state changes after window diff --git a/src/win.h b/src/win.h index 5aad0f2..55969d6 100644 --- a/src/win.h +++ b/src/win.h @@ -95,3 +95,6 @@ static inline Window win_get_leader(session_t *ps, win *w) { return win_get_leader_raw(ps, w, 0); } + +/// check if window has ARGB visual +bool win_has_alpha(win *w); diff --git a/src/x.c b/src/x.c index 0b8cd30..a678892 100644 --- a/src/x.c +++ b/src/x.c @@ -1,3 +1,5 @@ +#include + #include #include @@ -96,16 +98,18 @@ bool wid_get_text_prop(session_t *ps, Window wid, Atom prop, } 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(); - } + if (ps->pictfmts) + return; + 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) { @@ -116,8 +120,9 @@ xcb_render_pictforminfo_t *x_get_pictform_for_visual(session_t *ps, xcb_visualid 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) + if (i.data->id == pv->format) { return i.data; + } } return NULL; } diff --git a/src/x.h b/src/x.h index 101c50d..cc2734a 100644 --- a/src/x.h +++ b/src/x.h @@ -64,5 +64,5 @@ __attribute__((nonnull(1))); */ 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); + xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr);