Improvement #137: --xinerama-shadow-crop
Add --xinerama-shadow-crop to crop shadow to current Xinerama screen. Thanks to Feltzer for suggestion.
This commit is contained in:
parent
806f09dc3b
commit
3e71f8fa25
6
Makefile
6
Makefile
|
@ -17,6 +17,12 @@ OBJS = compton.o
|
||||||
# === Configuration flags ===
|
# === Configuration flags ===
|
||||||
CFG = -std=c99
|
CFG = -std=c99
|
||||||
|
|
||||||
|
# ==== Xinerama ====
|
||||||
|
ifeq "$(NO_XINERAMA)" ""
|
||||||
|
CFG += -DCONFIG_XINERAMA
|
||||||
|
PACKAGES += xinerama
|
||||||
|
endif
|
||||||
|
|
||||||
# ==== libconfig ====
|
# ==== libconfig ====
|
||||||
ifeq "$(NO_LIBCONFIG)" ""
|
ifeq "$(NO_LIBCONFIG)" ""
|
||||||
CFG += -DCONFIG_LIBCONFIG
|
CFG += -DCONFIG_LIBCONFIG
|
||||||
|
|
23
src/common.h
23
src/common.h
|
@ -85,6 +85,10 @@
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include <X11/extensions/Xdbe.h>
|
#include <X11/extensions/Xdbe.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Workarounds for missing definitions in very old versions of X headers,
|
// Workarounds for missing definitions in very old versions of X headers,
|
||||||
// thanks to consolers for reporting
|
// thanks to consolers for reporting
|
||||||
#ifndef PictOpDifference
|
#ifndef PictOpDifference
|
||||||
|
@ -506,6 +510,8 @@ typedef struct {
|
||||||
bool shadow_ignore_shaped;
|
bool shadow_ignore_shaped;
|
||||||
/// Whether to respect _COMPTON_SHADOW.
|
/// Whether to respect _COMPTON_SHADOW.
|
||||||
bool respect_prop_shadow;
|
bool respect_prop_shadow;
|
||||||
|
/// Whether to crop shadow to the very Xinerama screen.
|
||||||
|
bool xinerama_shadow_crop;
|
||||||
|
|
||||||
// === Fading ===
|
// === Fading ===
|
||||||
/// Enable/disable fading for specific window types.
|
/// Enable/disable fading for specific window types.
|
||||||
|
@ -806,6 +812,16 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
/// Whether X DBE extension exists.
|
/// Whether X DBE extension exists.
|
||||||
bool dbe_exists;
|
bool dbe_exists;
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
/// Whether X Xinerama extension exists.
|
||||||
|
bool xinerama_exists;
|
||||||
|
/// Xinerama screen info.
|
||||||
|
XineramaScreenInfo *xinerama_scrs;
|
||||||
|
/// Xinerama screen regions.
|
||||||
|
XserverRegion *xinerama_scr_regs;
|
||||||
|
/// Number of Xinerama screens.
|
||||||
|
int xinerama_nscrs;
|
||||||
|
#endif
|
||||||
/// Whether X Render convolution filter exists.
|
/// Whether X Render convolution filter exists.
|
||||||
bool xrfilter_convolution_exists;
|
bool xrfilter_convolution_exists;
|
||||||
|
|
||||||
|
@ -861,6 +877,10 @@ typedef struct _win {
|
||||||
Window id;
|
Window id;
|
||||||
/// Window attributes.
|
/// Window attributes.
|
||||||
XWindowAttributes a;
|
XWindowAttributes a;
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
/// Xinerama screen this window is on.
|
||||||
|
int xinerama_scr;
|
||||||
|
#endif
|
||||||
/// Window visual pict format;
|
/// Window visual pict format;
|
||||||
XRenderPictFormat *pictfmt;
|
XRenderPictFormat *pictfmt;
|
||||||
/// Window painting mode.
|
/// Window painting mode.
|
||||||
|
@ -1107,12 +1127,13 @@ XFixesDestroyRegion_(Display *dpy, XserverRegion reg,
|
||||||
/**
|
/**
|
||||||
* @brief Quit if the passed-in pointer is empty.
|
* @brief Quit if the passed-in pointer is empty.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void *
|
||||||
allocchk_(const char *func_name, void *ptr) {
|
allocchk_(const char *func_name, void *ptr) {
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
printf_err("%s(): Failed to allocate memory.", func_name);
|
printf_err("%s(): Failed to allocate memory.", func_name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Wrapper of allocchk_().
|
/// @brief Wrapper of allocchk_().
|
||||||
|
|
|
@ -1817,6 +1817,12 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
|
||||||
if (ps->o.clear_shadow && w->border_size)
|
if (ps->o.clear_shadow && w->border_size)
|
||||||
XFixesSubtractRegion(ps->dpy, reg_paint, reg_paint, w->border_size);
|
XFixesSubtractRegion(ps->dpy, reg_paint, reg_paint, w->border_size);
|
||||||
|
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0)
|
||||||
|
XFixesIntersectRegion(ps->dpy, reg_paint, reg_paint,
|
||||||
|
ps->xinerama_scr_regs[w->xinerama_scr]);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Detect if the region is empty before painting
|
// Detect if the region is empty before painting
|
||||||
{
|
{
|
||||||
reg_data_t cache_reg = REG_DATA_INIT;
|
reg_data_t cache_reg = REG_DATA_INIT;
|
||||||
|
@ -2035,6 +2041,8 @@ map_win(session_t *ps, Window id) {
|
||||||
|
|
||||||
w->a.map_state = IsViewable;
|
w->a.map_state = IsViewable;
|
||||||
|
|
||||||
|
cxinerama_win_upd_scr(ps, w);
|
||||||
|
|
||||||
// Set focused to false
|
// Set focused to false
|
||||||
bool focused_real = false;
|
bool focused_real = false;
|
||||||
if (ps->o.track_focus && ps->o.use_ewmh_active_win
|
if (ps->o.track_focus && ps->o.use_ewmh_active_win
|
||||||
|
@ -2677,6 +2685,9 @@ add_win(session_t *ps, Window id, Window prev) {
|
||||||
|
|
||||||
.id = None,
|
.id = None,
|
||||||
.a = { },
|
.a = { },
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
.xinerama_scr = -1,
|
||||||
|
#endif
|
||||||
.pictfmt = NULL,
|
.pictfmt = NULL,
|
||||||
.mode = WMODE_TRANS,
|
.mode = WMODE_TRANS,
|
||||||
.damaged = false,
|
.damaged = false,
|
||||||
|
@ -2989,8 +3000,10 @@ configure_win(session_t *ps, XConfigureEvent *ce) {
|
||||||
add_damage(ps, damage);
|
add_damage(ps, damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (factor_change)
|
if (factor_change) {
|
||||||
|
cxinerama_win_upd_scr(ps, w);
|
||||||
win_on_factor_change(ps, w);
|
win_on_factor_change(ps, w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// override_redirect flag cannot be changed after window creation, as far
|
// override_redirect flag cannot be changed after window creation, as far
|
||||||
|
@ -4417,6 +4430,15 @@ usage(int ret) {
|
||||||
" should not be painted in, such as a dock window region.\n"
|
" should not be painted in, such as a dock window region.\n"
|
||||||
" Use --shadow-exclude-reg \'x10+0-0\', for example, if the 10 pixels\n"
|
" Use --shadow-exclude-reg \'x10+0-0\', for example, if the 10 pixels\n"
|
||||||
" on the bottom of the screen should not have shadows painted on.\n"
|
" on the bottom of the screen should not have shadows painted on.\n"
|
||||||
|
#undef WARNING
|
||||||
|
#ifndef CONFIG_XINERAMA
|
||||||
|
#define WARNING WARNING_DISABLED
|
||||||
|
#else
|
||||||
|
#define WARNING
|
||||||
|
#endif
|
||||||
|
"--xinerama-shadow-crop\n"
|
||||||
|
" Crop shadow of a window fully on a particular Xinerama screen to the\n"
|
||||||
|
" screen." WARNING "\n"
|
||||||
"--backend backend\n"
|
"--backend backend\n"
|
||||||
" Choose backend. Possible choices are xrender and glx" WARNING ".\n"
|
" Choose backend. Possible choices are xrender and glx" WARNING ".\n"
|
||||||
"--glx-no-stencil\n"
|
"--glx-no-stencil\n"
|
||||||
|
@ -5245,6 +5267,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
{ "opacity-rule", required_argument, NULL, 304 },
|
{ "opacity-rule", required_argument, NULL, 304 },
|
||||||
{ "shadow-exclude-reg", required_argument, NULL, 305 },
|
{ "shadow-exclude-reg", required_argument, NULL, 305 },
|
||||||
{ "paint-exclude", required_argument, NULL, 306 },
|
{ "paint-exclude", required_argument, NULL, 306 },
|
||||||
|
{ "xinerama-shadow-crop", no_argument, NULL, 307 },
|
||||||
// Must terminate with a NULL entry
|
// Must terminate with a NULL entry
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
@ -5492,6 +5515,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
|
||||||
// --paint-exclude
|
// --paint-exclude
|
||||||
condlst_add(ps, &ps->o.paint_blacklist, optarg);
|
condlst_add(ps, &ps->o.paint_blacklist, optarg);
|
||||||
break;
|
break;
|
||||||
|
P_CASEBOOL(307, xinerama_shadow_crop);
|
||||||
default:
|
default:
|
||||||
usage(1);
|
usage(1);
|
||||||
break;
|
break;
|
||||||
|
@ -6343,6 +6367,35 @@ mainloop(session_t *ps) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cxinerama_upd_scrs(session_t *ps) {
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
free_xinerama_info(ps);
|
||||||
|
|
||||||
|
if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return;
|
||||||
|
|
||||||
|
if (!XineramaIsActive(ps->dpy)) return;
|
||||||
|
|
||||||
|
ps->xinerama_scrs = XineramaQueryScreens(ps->dpy, &ps->xinerama_nscrs);
|
||||||
|
|
||||||
|
// Just in case the shit hits the fan...
|
||||||
|
if (!ps->xinerama_nscrs) {
|
||||||
|
cxfree(ps->xinerama_scrs);
|
||||||
|
ps->xinerama_scrs = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ps->xinerama_scr_regs = allocchk(malloc(sizeof(XserverRegion *)
|
||||||
|
* ps->xinerama_nscrs));
|
||||||
|
for (int i = 0; i < ps->xinerama_nscrs; ++i) {
|
||||||
|
const XineramaScreenInfo * const s = &ps->xinerama_scrs[i];
|
||||||
|
XRectangle r = { .x = s->x_org, .y = s->y_org,
|
||||||
|
.width = s->width, .height = s->height };
|
||||||
|
ps->xinerama_scr_regs[i] = XFixesCreateRegion(ps->dpy, &r, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a session.
|
* Initialize a session.
|
||||||
*
|
*
|
||||||
|
@ -6409,6 +6462,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
.shadow_blacklist = NULL,
|
.shadow_blacklist = NULL,
|
||||||
.shadow_ignore_shaped = false,
|
.shadow_ignore_shaped = false,
|
||||||
.respect_prop_shadow = false,
|
.respect_prop_shadow = false,
|
||||||
|
.xinerama_shadow_crop = false,
|
||||||
|
|
||||||
.wintype_fade = { false },
|
.wintype_fade = { false },
|
||||||
.fade_in_step = 0.028 * OPAQUE,
|
.fade_in_step = 0.028 * OPAQUE,
|
||||||
|
@ -6663,6 +6717,17 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
ps->o.dbe = false;
|
ps->o.dbe = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Query X Xinerama extension
|
||||||
|
if (ps->o.xinerama_shadow_crop) {
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
int xinerama_event = 0, xinerama_error = 0;
|
||||||
|
if (XineramaQueryExtension(ps->dpy, &xinerama_event, &xinerama_error))
|
||||||
|
ps->xinerama_exists = true;
|
||||||
|
#else
|
||||||
|
printf_errf("(): Xinerama support not compiled in.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
rebuild_screen_reg(ps);
|
rebuild_screen_reg(ps);
|
||||||
|
|
||||||
// Overlay must be initialized before double buffer, and before creation
|
// Overlay must be initialized before double buffer, and before creation
|
||||||
|
@ -6697,6 +6762,8 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
if (!vsync_init(ps))
|
if (!vsync_init(ps))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
|
cxinerama_upd_scrs(ps);
|
||||||
|
|
||||||
// Create registration window
|
// Create registration window
|
||||||
if (!ps->reg_win && !register_cm(ps))
|
if (!ps->reg_win && !register_cm(ps))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -6923,6 +6990,7 @@ session_destroy(session_t *ps) {
|
||||||
free(ps->pfds_read);
|
free(ps->pfds_read);
|
||||||
free(ps->pfds_write);
|
free(ps->pfds_write);
|
||||||
free(ps->pfds_except);
|
free(ps->pfds_except);
|
||||||
|
free_xinerama_info(ps);
|
||||||
|
|
||||||
#ifdef CONFIG_VSYNC_OPENGL
|
#ifdef CONFIG_VSYNC_OPENGL
|
||||||
glx_destroy(ps);
|
glx_destroy(ps);
|
||||||
|
|
|
@ -192,6 +192,23 @@ free_wincondlst(c2_lptr_t **pcondlst) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free Xinerama screen info.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
free_xinerama_info(session_t *ps) {
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
if (ps->xinerama_scr_regs) {
|
||||||
|
for (int i = 0; i < ps->xinerama_nscrs; ++i)
|
||||||
|
free_region(ps, &ps->xinerama_scr_regs[i]);
|
||||||
|
free(ps->xinerama_scr_regs);
|
||||||
|
}
|
||||||
|
cxfree(ps->xinerama_scrs);
|
||||||
|
ps->xinerama_scrs = NULL;
|
||||||
|
ps->xinerama_nscrs = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether a paint_t contains enough data.
|
* Check whether a paint_t contains enough data.
|
||||||
*/
|
*/
|
||||||
|
@ -1191,6 +1208,31 @@ timeout_clear(session_t *ps);
|
||||||
static bool
|
static bool
|
||||||
mainloop(session_t *ps);
|
mainloop(session_t *ps);
|
||||||
|
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
static void
|
||||||
|
cxinerama_upd_scrs(session_t *ps);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Xinerama screen a window is on.
|
||||||
|
*
|
||||||
|
* Return an index >= 0, or -1 if not found.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
cxinerama_win_upd_scr(session_t *ps, win *w) {
|
||||||
|
#ifdef CONFIG_XINERAMA
|
||||||
|
w->xinerama_scr = -1;
|
||||||
|
for (XineramaScreenInfo *s = ps->xinerama_scrs;
|
||||||
|
s < ps->xinerama_scrs + ps->xinerama_nscrs; ++s)
|
||||||
|
if (s->x_org <= w->a.x && s->y_org <= w->a.y
|
||||||
|
&& s->x_org + s->width >= w->a.x + w->widthb
|
||||||
|
&& s->y_org + s->height >= w->a.y + w->heightb) {
|
||||||
|
w->xinerama_scr = s - ps->xinerama_scrs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static session_t *
|
static session_t *
|
||||||
session_init(session_t *ps_old, int argc, char **argv);
|
session_init(session_t *ps_old, int argc, char **argv);
|
||||||
|
|
||||||
|
|
|
@ -926,6 +926,7 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_m_opts_get_do(shadow_offset_y, cdbus_reply_int32);
|
cdbus_m_opts_get_do(shadow_offset_y, cdbus_reply_int32);
|
||||||
cdbus_m_opts_get_do(shadow_opacity, cdbus_reply_double);
|
cdbus_m_opts_get_do(shadow_opacity, cdbus_reply_double);
|
||||||
cdbus_m_opts_get_do(clear_shadow, cdbus_reply_bool);
|
cdbus_m_opts_get_do(clear_shadow, cdbus_reply_bool);
|
||||||
|
cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool);
|
||||||
|
|
||||||
cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32);
|
cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32);
|
||||||
cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32);
|
cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32);
|
||||||
|
|
Loading…
Reference in New Issue