Created
August 22, 2013 06:50
-
-
Save richardgv/6303981 to your computer and use it in GitHub Desktop.
chjj/compton #137: Untested --xinerama-shadow-crop patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Makefile b/Makefile | |
index 9acba9d..655c77d 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -17,6 +17,12 @@ OBJS = compton.o | |
# === Configuration flags === | |
CFG = -std=c99 | |
+# ==== Xinerama ==== | |
+ifeq "$(NO_XINERAMA)" "" | |
+ CFG += -DCONFIG_XINERAMA | |
+ PACKAGES += xinerama | |
+endif | |
+ | |
# ==== libconfig ==== | |
ifeq "$(NO_LIBCONFIG)" "" | |
CFG += -DCONFIG_LIBCONFIG | |
diff --git a/src/common.h b/src/common.h | |
index bf0b480..f90cba7 100644 | |
--- a/src/common.h | |
+++ b/src/common.h | |
@@ -85,6 +85,10 @@ | |
#include <X11/extensions/Xrandr.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, | |
// thanks to consolers for reporting | |
#ifndef PictOpDifference | |
@@ -506,6 +510,8 @@ typedef struct { | |
bool shadow_ignore_shaped; | |
/// Whether to respect _COMPTON_SHADOW. | |
bool respect_prop_shadow; | |
+ /// Whether to crop shadow to the very Xinerama screen. | |
+ bool xinerama_shadow_crop; | |
// === Fading === | |
/// Enable/disable fading for specific window types. | |
@@ -806,6 +812,16 @@ typedef struct { | |
#endif | |
/// Whether X DBE extension 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. | |
bool xrfilter_convolution_exists; | |
@@ -861,6 +877,10 @@ typedef struct _win { | |
Window id; | |
/// Window attributes. | |
XWindowAttributes a; | |
+#ifdef CONFIG_XINERAMA | |
+ /// Xinerama screen this window is on. | |
+ int xinerama_scr; | |
+#endif | |
/// Window visual pict format; | |
XRenderPictFormat *pictfmt; | |
/// Window painting mode. | |
@@ -1107,12 +1127,13 @@ XFixesDestroyRegion_(Display *dpy, XserverRegion reg, | |
/** | |
* @brief Quit if the passed-in pointer is empty. | |
*/ | |
-static inline void | |
+static inline void * | |
allocchk_(const char *func_name, void *ptr) { | |
if (!ptr) { | |
printf_err("%s(): Failed to allocate memory.", func_name); | |
exit(1); | |
} | |
+ return ptr; | |
} | |
/// @brief Wrapper of allocchk_(). | |
diff --git a/src/compton.c b/src/compton.c | |
index 474d2a2..eebe77d 100644 | |
--- a/src/compton.c | |
+++ b/src/compton.c | |
@@ -1817,6 +1817,12 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t | |
if (ps->o.clear_shadow && 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 | |
{ | |
reg_data_t cache_reg = REG_DATA_INIT; | |
@@ -2035,6 +2041,8 @@ map_win(session_t *ps, Window id) { | |
w->a.map_state = IsViewable; | |
+ cxinerama_win_upd_scr(ps, w); | |
+ | |
// Set focused to false | |
bool focused_real = false; | |
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, | |
.a = { }, | |
+#ifdef CONFIG_XINERAMA | |
+ .xinerama_scr = -1, | |
+#endif | |
.pictfmt = NULL, | |
.mode = WMODE_TRANS, | |
.damaged = false, | |
@@ -2960,6 +2971,7 @@ configure_win(session_t *ps, XConfigureEvent *ce) { | |
factor_change = true; | |
free_region(ps, &w->extents); | |
free_region(ps, &w->border_size); | |
+ cxinerama_win_upd_scr(ps, w); | |
} | |
w->a.x = ce->x; | |
@@ -4417,6 +4429,15 @@ usage(int ret) { | |
" 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" | |
" 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" | |
" Choose backend. Possible choices are xrender and glx" WARNING ".\n" | |
"--glx-no-stencil\n" | |
@@ -5245,6 +5266,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { | |
{ "opacity-rule", required_argument, NULL, 304 }, | |
{ "shadow-exclude-reg", required_argument, NULL, 305 }, | |
{ "paint-exclude", required_argument, NULL, 306 }, | |
+ { "xinerama-shadow-crop", no_argument, NULL, 307 }, | |
// Must terminate with a NULL entry | |
{ NULL, 0, NULL, 0 }, | |
}; | |
@@ -5492,6 +5514,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { | |
// --paint-exclude | |
condlst_add(ps, &ps->o.paint_blacklist, optarg); | |
break; | |
+ P_CASEBOOL(307, xinerama_shadow_crop); | |
default: | |
usage(1); | |
break; | |
@@ -6343,6 +6366,35 @@ mainloop(session_t *ps) { | |
return true; | |
} | |
+#ifdef CONFIG_XINERAMA | |
+static void | |
+cxinerama_upd_scrs(session_t *ps) { | |
+ 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. | |
* | |
@@ -6409,6 +6461,7 @@ session_init(session_t *ps_old, int argc, char **argv) { | |
.shadow_blacklist = NULL, | |
.shadow_ignore_shaped = false, | |
.respect_prop_shadow = false, | |
+ .xinerama_shadow_crop = false, | |
.wintype_fade = { false }, | |
.fade_in_step = 0.028 * OPAQUE, | |
@@ -6663,6 +6716,17 @@ session_init(session_t *ps_old, int argc, char **argv) { | |
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->o.xinerama_shadow_crop = false; | |
+#else | |
+ printf_errf("(): Xinerama support not compiled in."); | |
+#endif | |
+ } | |
+ | |
rebuild_screen_reg(ps); | |
// Overlay must be initialized before double buffer, and before creation | |
@@ -6923,6 +6987,7 @@ session_destroy(session_t *ps) { | |
free(ps->pfds_read); | |
free(ps->pfds_write); | |
free(ps->pfds_except); | |
+ free_xinerama_info(ps); | |
#ifdef CONFIG_VSYNC_OPENGL | |
glx_destroy(ps); | |
diff --git a/src/compton.h b/src/compton.h | |
index c0773db..f4a7ef9 100644 | |
--- a/src/compton.h | |
+++ b/src/compton.h | |
@@ -193,6 +193,23 @@ free_wincondlst(c2_lptr_t **pcondlst) { | |
} | |
/** | |
+ * 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. | |
*/ | |
static inline bool | |
@@ -1191,6 +1208,31 @@ timeout_clear(session_t *ps); | |
static bool | |
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 * | |
session_init(session_t *ps_old, int argc, char **argv); | |
diff --git a/src/dbus.c b/src/dbus.c | |
index 671ef8e..8f53eee 100644 | |
--- a/src/dbus.c | |
+++ b/src/dbus.c | |
@@ -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_opacity, cdbus_reply_double); | |
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_in_step, cdbus_reply_int32); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment