summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c2.c16
-rw-r--r--c2.h2
-rw-r--r--common.h17
-rw-r--r--compton.c76
-rw-r--r--compton.h11
5 files changed, 115 insertions, 7 deletions
diff --git a/c2.c b/c2.c
index 13c194050..bd286278a 100644
--- a/c2.c
+++ b/c2.c
@@ -14,7 +14,8 @@
* Parse a condition string.
*/
c2_lptr_t *
-c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern) {
+c2_parsed(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
+ void *data) {
if (!pattern)
return NULL;
@@ -41,6 +42,7 @@ c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern) {
" list element.");
memcpy(plptr, &lptr_def, sizeof(c2_lptr_t));
plptr->ptr = result;
+ plptr->data = data;
if (pcondlst) {
plptr->next = *pcondlst;
*pcondlst = plptr;
@@ -1274,20 +1276,26 @@ c2_match_once(session_t *ps, win *w, const c2_ptr_t cond) {
* Match a window against a condition linked list.
*
* @param cache a place to cache the last matched condition
+ * @param pdata a place to return the data
* @return true if matched, false otherwise.
*/
bool
-c2_match(session_t *ps, win *w, const c2_lptr_t *condlst,
- const c2_lptr_t **cache) {
+c2_matchd(session_t *ps, win *w, const c2_lptr_t *condlst,
+ const c2_lptr_t **cache, void **pdata) {
// Check if the cached entry matches firstly
- if (cache && *cache && c2_match_once(ps, w, (*cache)->ptr))
+ if (cache && *cache && c2_match_once(ps, w, (*cache)->ptr)) {
+ if (pdata)
+ *pdata = (*cache)->data;
return true;
+ }
// Then go through the whole linked list
for (; condlst; condlst = condlst->next) {
if (c2_match_once(ps, w, condlst->ptr)) {
if (cache)
*cache = condlst;
+ if (pdata)
+ *pdata = condlst->data;
return true;
}
}
diff --git a/c2.h b/c2.h
index c794da1c0..b26a687de 100644
--- a/c2.h
+++ b/c2.h
@@ -156,12 +156,14 @@ const static c2_l_t leaf_def = C2_L_INIT;
/// Linked list type of conditions.
struct _c2_lptr {
c2_ptr_t ptr;
+ void *data;
struct _c2_lptr *next;
};
/// Initializer for c2_lptr_t.
#define C2_LPTR_INIT { \
.ptr = C2_PTR_INIT, \
+ .data = NULL, \
.next = NULL, \
}
diff --git a/common.h b/common.h
index cab29f76a..0b97d5009 100644
--- a/common.h
+++ b/common.h
@@ -546,6 +546,8 @@ typedef struct {
bool inactive_dim_fixed;
/// Conditions of windows to have inverted colors.
c2_lptr_t *invert_color_list;
+ /// Rules to change window opacity.
+ c2_lptr_t *opacity_rules;
// === Focus related ===
/// Consider windows of specific types to be always focused.
@@ -921,6 +923,7 @@ typedef struct _win {
const c2_lptr_t *cache_fcblst;
const c2_lptr_t *cache_ivclst;
const c2_lptr_t *cache_bbblst;
+ const c2_lptr_t *cache_oparule;
// Opacity-related members
/// Current window opacity.
@@ -933,6 +936,8 @@ typedef struct _win {
/// broken window managers not transferring client window's
/// _NET_WM_OPACITY value
opacity_t opacity_prop_client;
+ /// Last window opacity value we set.
+ long opacity_set;
// Fading-related members
/// Do not fade if it's false. Change on window type change.
@@ -2027,14 +2032,20 @@ opts_set_no_fading_openclose(session_t *ps, bool newval);
///@{
c2_lptr_t *
-c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern);
+c2_parsed(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
+ void *data);
+
+#define c2_parse(ps, pcondlst, pattern) c2_parsed((ps), (pcondlst), (pattern), NULL)
c2_lptr_t *
c2_free_lptr(c2_lptr_t *lp);
bool
-c2_match(session_t *ps, win *w, const c2_lptr_t *condlst,
- const c2_lptr_t **cache);
+c2_matchd(session_t *ps, win *w, const c2_lptr_t *condlst,
+ const c2_lptr_t **cache, void **pdata);
+
+#define c2_match(ps, w, condlst, cache) c2_matchd((ps), (w), (condlst), \
+ (cache), NULL)
#endif
///@}
diff --git a/compton.c b/compton.c
index f058bf927..c55d045d8 100644
--- a/compton.c
+++ b/compton.c
@@ -2427,6 +2427,28 @@ win_determine_blur_background(session_t *ps, win *w) {
}
/**
+ * Update window opacity according to opacity rules.
+ */
+static void
+win_update_opacity_rule(session_t *ps, win *w) {
+ // If long is 32-bit, unfortunately there's no way could we express "unset",
+ // so we just entirely don't distinguish "unset" and OPAQUE
+ long opacity = OPAQUE;
+ void *val = NULL;
+ if (c2_matchd(ps, w, ps->o.opacity_rules, &w->cache_oparule, &val))
+ opacity = ((double) (long) val) / 100.0 * OPAQUE;
+
+ if (opacity == w->opacity_set)
+ return;
+
+ if (OPAQUE != opacity)
+ wid_set_opacity_prop(ps, w->id, opacity);
+ else if (OPAQUE != w->opacity_set)
+ wid_rm_opacity_prop(ps, w->id);
+ w->opacity_set = opacity;
+}
+
+/**
* Function to be called on window type changes.
*/
static void
@@ -2436,6 +2458,8 @@ win_on_wtype_change(session_t *ps, win *w) {
win_update_focused(ps, w);
if (ps->o.invert_color_list)
win_determine_invert_color(ps, w);
+ if (ps->o.opacity_rules)
+ win_update_opacity_rule(ps, w);
}
/**
@@ -2453,6 +2477,8 @@ win_on_factor_change(session_t *ps, win *w) {
win_update_focused(ps, w);
if (ps->o.blur_background_blacklist)
win_determine_blur_background(ps, w);
+ if (ps->o.opacity_rules)
+ win_update_opacity_rule(ps, w);
}
/**
@@ -2670,11 +2696,13 @@ add_win(session_t *ps, Window id, Window prev) {
.cache_fcblst = NULL,
.cache_ivclst = NULL,
.cache_bbblst = NULL,
+ .cache_oparule = NULL,
.opacity = 0,
.opacity_tgt = 0,
.opacity_prop = OPAQUE,
.opacity_prop_client = OPAQUE,
+ .opacity_set = OPAQUE,
.fade = false,
.fade_force = UNSET,
@@ -4351,6 +4379,12 @@ usage(int ret) {
"--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"
+ "--opacity-rule opacity:condition\n"
+ " Specify a list of opacity rules, in the format \"PERCENT:PATTERN\",\n"
+ " like \'50:name *= \"Firefox\"'. compton-trans is recommended over\n"
+ " this. Note we do not distinguish 100% and unset, and we don't make\n"
+ " any guarantee about possible conflicts with other programs that set\n"
+ " _NET_WM_WINDOW_OPACITY on frame or client windows.\n"
"--backend backend\n"
" Choose backend. Possible choices are xrender and glx" WARNING ".\n"
"--glx-no-stencil\n"
@@ -4638,6 +4672,9 @@ parse_conv_kern(session_t *ps, const char *src, const char **endptr) {
return parse_matrix(ps, src, endptr);
}
+/**
+ * Parse a list of convolution kernels.
+ */
static bool
parse_conv_kern_lst(session_t *ps, const char *src, XFixed **dest, int max) {
static const struct {
@@ -4682,6 +4719,37 @@ parse_conv_kern_lst(session_t *ps, const char *src, XFixed **dest, int max) {
return true;
}
+/**
+ * Parse a list of opacity rules.
+ */
+static inline bool
+parse_rule_opacity(session_t *ps, const char *src) {
+ // Find opacity value
+ char *endptr = NULL;
+ long val = strtol(src, &endptr, 0);
+ if (!endptr || endptr == src) {
+ printf_errf("(\"%s\"): No opacity specified?", src);
+ return false;
+ }
+ if (val > 100 || val < 0) {
+ printf_errf("(\"%s\"): Opacity %ld invalid.", src, val);
+ return false;
+ }
+
+ // Skip over spaces
+ while (*endptr && isspace(*endptr))
+ ++endptr;
+ if (':' != *endptr) {
+ printf_errf("(\"%s\"): Opacity terminator not found.", src);
+ return false;
+ }
+ ++endptr;
+
+ // Parse pattern
+ // I hope 1-100 is acceptable for (void *)
+ return c2_parsed(ps, &ps->o.opacity_rules, endptr, (void *) val);
+}
+
#ifdef CONFIG_LIBCONFIG
/**
* Get a file stream of the configuration file to read.
@@ -5049,6 +5117,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
{ "blur-kern", required_argument, NULL, 301 },
{ "resize-damage", required_argument, NULL, 302 },
{ "glx-use-gpushader4", no_argument, NULL, 303 },
+ { "opacity-rule", required_argument, NULL, 304 },
// Must terminate with a NULL entry
{ NULL, 0, NULL, 0 },
};
@@ -5282,6 +5351,11 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
ps->o.resize_damage = atoi(optarg);
break;
P_CASEBOOL(303, glx_use_gpushader4);
+ case 304:
+ // --opacity-rule
+ if (!parse_rule_opacity(ps, optarg))
+ exit(1);
+ break;
default:
usage(1);
break;
@@ -6216,6 +6290,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
.inactive_dim = 0.0,
.inactive_dim_fixed = false,
.invert_color_list = NULL,
+ .opacity_rules = NULL,
.wintype_focus = { false },
.use_ewmh_active_win = false,
@@ -6635,6 +6710,7 @@ session_destroy(session_t *ps) {
free_wincondlst(&ps->o.focus_blacklist);
free_wincondlst(&ps->o.invert_color_list);
free_wincondlst(&ps->o.blur_background_blacklist);
+ free_wincondlst(&ps->o.opacity_rules);
#endif
// Free tracked atom list
diff --git a/compton.h b/compton.h
index b3695af29..334e7372a 100644
--- a/compton.h
+++ b/compton.h
@@ -415,6 +415,17 @@ win_has_frame(const win *w) {
|| w->top_width || w->left_width || w->right_width || w->bottom_width;
}
+static inline void
+wid_set_opacity_prop(session_t *ps, Window wid, long val) {
+ XChangeProperty(ps->dpy, wid, ps->atom_opacity, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *) &val, 1);
+}
+
+static inline void
+wid_rm_opacity_prop(session_t *ps, Window wid) {
+ XDeleteProperty(ps->dpy, wid, ps->atom_opacity);
+}
+
/**
* Dump an drawable's info.
*/