Improvement: Support reading _NET_WM_OPACITY from client windows
- Some WMs don't respect Keith Packard's proposal of _NET_WM_WINDOW_OPACITY, and do not copy _NET_WM_OPACITY attribute of a client window to its frame windows, thus cause opacity set by non-override-redirect windows to have no effect. This commit adds support for reading _NET_WM_OPACITY from client windows if running with --detect-client-opacity. Thanks to pvanek for reporting. - Change Makefile logic to determine options from 3 variables (NO_LIBCONFIG, NO_REGEX_PCRE, NO_REGEX_PCRE_JIT) instead of CFG to ensure compatibility when we add new options. CFG variable is no longer been respected.
This commit is contained in:
parent
b8f3d22a32
commit
1306b1591f
40
Makefile
40
Makefile
|
@ -4,20 +4,38 @@ PREFIX ?= /usr
|
|||
BINDIR ?= $(PREFIX)/bin
|
||||
MANDIR ?= $(PREFIX)/share/man/man1
|
||||
|
||||
PACKAGES = x11 xcomposite xfixes xdamage xrender xext libconfig
|
||||
LIBS = $(shell pkg-config --libs $(PACKAGES)) -lm
|
||||
LIBS += $(shell pcre-config --libs)
|
||||
INCS = $(shell pkg-config --cflags $(PACKAGES))
|
||||
INCS += $(shell pcre-config --cflags)
|
||||
PACKAGES = x11 xcomposite xfixes xdamage xrender xext
|
||||
LIBS = -lm
|
||||
INCS =
|
||||
|
||||
# Parse configuration flags
|
||||
CFG =
|
||||
|
||||
ifeq "$(NO_LIBCONFIG)" ""
|
||||
CFG += -DCONFIG_LIBCONFIG
|
||||
PACKAGES += libconfig
|
||||
|
||||
# libconfig-1.3* does not define LIBCONFIG_VER* macros, so we use
|
||||
# pkg-config to determine its version here
|
||||
CFG += $(shell pkg-config --atleast-version=1.4 libconfig || echo '-DCONFIG_LIBCONFIG_LEGACY')
|
||||
endif
|
||||
|
||||
ifeq "$(NO_REGEX_PCRE)" ""
|
||||
CFG += -DCONFIG_REGEX_PCRE
|
||||
LIBS += $(shell pcre-config --libs)
|
||||
INCS += $(shell pcre-config --cflags)
|
||||
ifeq "$(NO_REGEX_PCRE_JIT)" ""
|
||||
CFG += -DCONFIG_REGEX_PCRE_JIT
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += $(CFG)
|
||||
|
||||
LIBS += $(shell pkg-config --libs $(PACKAGES))
|
||||
INCS += $(shell pkg-config --cflags $(PACKAGES))
|
||||
CFLAGS += -Wall -std=c99
|
||||
OBJS = compton.o
|
||||
|
||||
CFG ?= -DCONFIG_LIBCONFIG -DCONFIG_REGEX_PCRE -DCONFIG_REGEX_PCRE_JIT
|
||||
# libconfig-1.3* does not define LIBCONFIG_VER* macros, so we use pkg-config
|
||||
# to determine its version here
|
||||
CFG += $(shell pkg-config --atleast-version=1.4 libconfig || echo '-DCONFIG_LIBCONFIG_LEGACY')
|
||||
CFLAGS += $(CFG)
|
||||
|
||||
%.o: src/%.c src/%.h
|
||||
$(CC) $(CFLAGS) $(INCS) -c src/$*.c
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ shadow-ignore-shaped = true;
|
|||
menu-opacity = 0.8;
|
||||
inactive-opacity = 0.8;
|
||||
frame-opacity = 0.7;
|
||||
inactive-opacity-override = true;
|
||||
inactive-opacity-override = false;
|
||||
|
||||
# Fading
|
||||
fading = true;
|
||||
|
@ -31,6 +31,7 @@ fade-out-step = 0.03;
|
|||
mark-wmwin-focused = true;
|
||||
mark-ovredir-focused = true;
|
||||
detect-rounded-corners = true;
|
||||
detect-client-opacity = false;
|
||||
|
||||
# Window type settings
|
||||
wintypes:
|
||||
|
|
|
@ -142,6 +142,7 @@ static options_t opts = {
|
|||
.inactive_opacity = 0,
|
||||
.inactive_opacity_override = False,
|
||||
.frame_opacity = 0.0,
|
||||
.detect_client_opacity = False,
|
||||
.inactive_dim = 0.0,
|
||||
|
||||
.track_focus = False,
|
||||
|
@ -942,7 +943,8 @@ determine_evmask(Display *dpy, Window wid, win_evmode_t mode) {
|
|||
}
|
||||
|
||||
if (WIN_EVMODE_CLIENT == mode || find_toplevel(dpy, wid)) {
|
||||
if (opts.frame_opacity || opts.track_wdata)
|
||||
if (opts.frame_opacity || opts.track_wdata
|
||||
|| opts.detect_client_opacity)
|
||||
evmask |= PropertyChangeMask;
|
||||
}
|
||||
|
||||
|
@ -1757,14 +1759,14 @@ unmap_win(Display *dpy, Window id, Bool fade) {
|
|||
}
|
||||
|
||||
static opacity_t
|
||||
get_opacity_prop(Display *dpy, win *w, opacity_t def) {
|
||||
wid_get_opacity_prop(Display *dpy, Window wid, opacity_t def) {
|
||||
Atom actual;
|
||||
int format;
|
||||
unsigned long n, left;
|
||||
|
||||
unsigned char *data;
|
||||
int result = XGetWindowProperty(
|
||||
dpy, w->id, opacity_atom, 0L, 1L, False,
|
||||
dpy, wid, opacity_atom, 0L, 1L, False,
|
||||
XA_CARDINAL, &actual, &format, &n, &left, &data);
|
||||
|
||||
if (result == Success && data != NULL) {
|
||||
|
@ -1838,13 +1840,18 @@ calc_opacity(Display *dpy, win *w, Bool refetch_prop) {
|
|||
// Do not refetch the opacity window attribute unless necessary, this
|
||||
// is probably an expensive operation in some cases
|
||||
if (refetch_prop) {
|
||||
w->opacity_prop = get_opacity_prop(dpy, w, OPAQUE);
|
||||
w->opacity_prop = wid_get_opacity_prop(dpy, w->id, OPAQUE);
|
||||
if (!opts.detect_client_opacity || !w->client_win
|
||||
|| w->id == w->client_win)
|
||||
w->opacity_prop_client = OPAQUE;
|
||||
else
|
||||
w->opacity_prop_client = wid_get_opacity_prop(dpy, w->client_win,
|
||||
OPAQUE);
|
||||
}
|
||||
|
||||
if (OPAQUE == (opacity = w->opacity_prop)) {
|
||||
if (1.0 != opts.wintype_opacity[w->window_type]) {
|
||||
opacity = opts.wintype_opacity[w->window_type] * OPAQUE;
|
||||
}
|
||||
if (OPAQUE == (opacity = w->opacity_prop)
|
||||
&& OPAQUE == (opacity = w->opacity_prop_client)) {
|
||||
opacity = opts.wintype_opacity[w->window_type] * OPAQUE;
|
||||
}
|
||||
|
||||
// Respect inactive_opacity in some cases
|
||||
|
@ -1945,12 +1952,13 @@ static void
|
|||
mark_client_win(Display *dpy, win *w, Window client) {
|
||||
w->client_win = client;
|
||||
|
||||
XSelectInput(dpy, client, determine_evmask(dpy, client, WIN_EVMODE_CLIENT));
|
||||
|
||||
// Get the frame width and monitor further frame width changes on client
|
||||
// window if necessary
|
||||
if (opts.frame_opacity) {
|
||||
get_frame_extents(dpy, w, client);
|
||||
}
|
||||
XSelectInput(dpy, client, determine_evmask(dpy, client, WIN_EVMODE_CLIENT));
|
||||
|
||||
// Detect window type here
|
||||
if (WINTYPE_UNKNOWN == w->window_type)
|
||||
|
@ -2037,6 +2045,7 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
|||
new->opacity_tgt = 0;
|
||||
new->opacity_cur = OPAQUE;
|
||||
new->opacity_prop = OPAQUE;
|
||||
new->opacity_prop_client = OPAQUE;
|
||||
new->fade = False;
|
||||
new->fade_callback = NULL;
|
||||
new->fade_fin = False;
|
||||
|
@ -2777,12 +2786,17 @@ ev_property_notify(XPropertyEvent *ev) {
|
|||
}
|
||||
}
|
||||
|
||||
/* check if Trans property was changed */
|
||||
// If _NET_WM_OPACITY changes
|
||||
if (ev->atom == opacity_atom) {
|
||||
/* reset mode and redraw window */
|
||||
win *w = find_win(dpy, ev->window);
|
||||
win *w = NULL;
|
||||
if ((w = find_win(dpy, ev->window)))
|
||||
w->opacity_prop = wid_get_opacity_prop(dpy, w->id, OPAQUE);
|
||||
else if (opts.detect_client_opacity
|
||||
&& (w = find_toplevel(dpy, ev->window)))
|
||||
w->opacity_prop_client = wid_get_opacity_prop(dpy, w->client_win,
|
||||
OPAQUE);
|
||||
if (w) {
|
||||
calc_opacity(dpy, w, True);
|
||||
calc_opacity(dpy, w, False);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3007,6 +3021,10 @@ usage(void) {
|
|||
"--detect-rounded-corners\n"
|
||||
" Try to detect windows with rounded corners and don't consider\n"
|
||||
" them shaped windows.\n"
|
||||
"--detect-client-opacity\n"
|
||||
" Detect _NET_WM_OPACITY on client windows, useful for window\n"
|
||||
" managers not passing _NET_WM_OPACITY of client windows to frame\n"
|
||||
" windows.\n"
|
||||
"\n"
|
||||
"Format of a condition:\n"
|
||||
"\n"
|
||||
|
@ -3267,6 +3285,9 @@ parse_config(char *cpath, struct options_tmp *pcfgtmp) {
|
|||
// --detect-rounded-corners
|
||||
lcfg_lookup_bool(&cfg, "detect-rounded-corners",
|
||||
&opts.detect_rounded_corners);
|
||||
// --detect-client-opacity
|
||||
lcfg_lookup_bool(&cfg, "detect-client-opacity",
|
||||
&opts.detect_client_opacity);
|
||||
// --shadow-exclude
|
||||
{
|
||||
config_setting_t *setting =
|
||||
|
@ -3329,6 +3350,7 @@ get_cfg(int argc, char *const *argv) {
|
|||
{ "no-fading-openclose", no_argument, NULL, 265 },
|
||||
{ "shadow-ignore-shaped", no_argument, NULL, 266 },
|
||||
{ "detect-rounded-corners", no_argument, NULL, 267 },
|
||||
{ "detect-client-opacity", no_argument, NULL, 268 },
|
||||
// Must terminate with a NULL entry
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
@ -3483,6 +3505,10 @@ get_cfg(int argc, char *const *argv) {
|
|||
// --detect-rounded-corners
|
||||
opts.detect_rounded_corners = True;
|
||||
break;
|
||||
case 268:
|
||||
// --detect-client-opacity
|
||||
opts.detect_client_opacity = True;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
|
|
|
@ -198,6 +198,10 @@ typedef struct _win {
|
|||
opacity_t opacity_cur;
|
||||
/// Cached value of opacity window attribute.
|
||||
opacity_t opacity_prop;
|
||||
/// Cached value of opacity window attribute on client window. For
|
||||
/// broken window managers not transferring client window's
|
||||
/// _NET_WM_OPACITY value
|
||||
opacity_t opacity_prop_client;
|
||||
/// Alpha mask Picture to render window with opacity.
|
||||
Picture alpha_pict;
|
||||
|
||||
|
@ -302,7 +306,12 @@ typedef struct _options {
|
|||
/// Whether inactive_opacity overrides the opacity set by window
|
||||
/// attributes.
|
||||
Bool inactive_opacity_override;
|
||||
/// Frame opacity. Relative to window opacity, also affects shadow
|
||||
/// opacity.
|
||||
double frame_opacity;
|
||||
/// Whether to detect _NET_WM_OPACITY on client windows. Used on window
|
||||
/// managers that don't pass _NET_WM_OPACITY to frame windows.
|
||||
Bool detect_client_opacity;
|
||||
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
|
||||
double inactive_dim;
|
||||
|
||||
|
@ -780,7 +789,7 @@ static void
|
|||
unmap_win(Display *dpy, Window id, Bool fade);
|
||||
|
||||
static opacity_t
|
||||
get_opacity_prop(Display *dpy, win *w, opacity_t def);
|
||||
wid_get_opacity_prop(Display *dpy, Window wid, opacity_t def);
|
||||
|
||||
static double
|
||||
get_opacity_percent(Display *dpy, win *w);
|
||||
|
|
Loading…
Reference in New Issue