summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2012-11-01 10:43:15 +0800
committerRichard Grenville <[email protected]>2012-11-01 11:44:38 +0800
commit987c43bbd37cd654bb183807c2ee2dde6eed018e (patch)
tree6ac983836d9cacfaa6696d61f29783b7915f9de6
parent47f54a1cb78bb53552ea0a0277b1604d1eaad482 (diff)
downloadtdebase-987c43bbd37cd654bb183807c2ee2dde6eed018e.tar.gz
tdebase-987c43bbd37cd654bb183807c2ee2dde6eed018e.zip
Improvement: border_size & ConfigureNotify & VSync changes
- Run XSync() before the final paint to catch VBlank better. Stolen from Xfwm4 VSync patch. - Add --vsync-aggressive that sends out the final painting request earlier, simulating xfwm4 VSync patch. But this thing does have the possibility of breaking VSync, I think... - Change handling of ConfigureNotify to avoid freeing w->extents and w->border_size if possible. - Change logic in paint_prepreprocess() to use win_get_region() for border_size generation instead of border_size() if the window is not shaped to try to avoid some BadRegion error messages when a window loses its border_size then is unmapped, about which Adys complained in #25. - Detect if w->border_size is None before using it in various places. Practically the effect is pretty limited because XFixesCreateRegionFromWindow() usually returns an invalid X ID instead of None on error. - Fix a bug that rounded corner detection could fail if the window size is changed by a ConfigureNotify immediately.
-rw-r--r--compton.c72
-rw-r--r--compton.h6
2 files changed, 63 insertions, 15 deletions
diff --git a/compton.c b/compton.c
index 3a1810f8f..2e9ce2ef4 100644
--- a/compton.c
+++ b/compton.c
@@ -181,6 +181,7 @@ static options_t opts = {
.sw_opti = False,
.vsync = VSYNC_NONE,
.dbe = False,
+ .vsync_aggressive = False,
.wintype_shadow = { False },
.shadow_red = 0.0,
@@ -1413,11 +1414,20 @@ paint_preprocess(Display *dpy, win *list) {
dpy, draw, format, CPSubwindowMode, &pa);
}
- // Fetch bounding region and extents if needed
+ // Fetch bounding region
if (!w->border_size) {
- w->border_size = border_size(dpy, w);
+ // Build a border_size ourselves if window is not shaped, to avoid
+ // getting an invalid border_size region from X if the window is
+ // unmapped/destroyed
+ if (!w->bounding_shaped) {
+ w->border_size = win_get_region(dpy, w);
+ }
+ else if (IsUnmapped != w->a.map_state) {
+ w->border_size = border_size(dpy, w);
+ }
}
+ // Fetch window extents
if (!w->extents) {
w->extents = win_extents(dpy, w);
// If w->extents does not exist, the previous add_damage_win()
@@ -1479,8 +1489,9 @@ paint_preprocess(Display *dpy, win *list) {
else
w->reg_ignore = win_get_region_noframe(dpy, w);
- XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
- w->border_size);
+ if (w->border_size)
+ XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
+ w->border_size);
if (last_reg_ignore)
XFixesUnionRegion(dpy, w->reg_ignore, w->reg_ignore,
@@ -1674,7 +1685,7 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
}
// Clear the shadow here instead of in make_shadow() for saving GPU
// power and handling shaped windows
- if (opts.clear_shadow)
+ if (opts.clear_shadow && w->border_size)
XFixesSubtractRegion(dpy, reg_paint, reg_paint, w->border_size);
// Detect if the region is empty before painting
@@ -1694,10 +1705,15 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
// Copy the subtracted region to be used for shadow painting in next
// cycle
XFixesCopyRegion(dpy, reg_tmp2, reg_paint);
- XFixesIntersectRegion(dpy, reg_paint, reg_paint, w->border_size);
+
+ if (w->border_size)
+ XFixesIntersectRegion(dpy, reg_paint, reg_paint, w->border_size);
}
else {
- XFixesIntersectRegion(dpy, reg_paint, region, w->border_size);
+ if (w->border_size)
+ XFixesIntersectRegion(dpy, reg_paint, region, w->border_size);
+ else
+ reg_paint = region;
}
if (!is_region_empty(dpy, reg_paint)) {
@@ -1719,8 +1735,17 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
if (!opts.dbe)
XFixesSetPictureClipRegion(dpy, tgt_buffer, 0, 0, None);
- // Wait for VBlank
- vsync_wait();
+ if (VSYNC_NONE != opts.vsync) {
+ // Make sure all previous requests are processed to achieve best
+ // effect
+ XSync(dpy, False);
+ }
+
+ // Wait for VBlank. We could do it aggressively (send the painting
+ // request and XFlush() on VBlank) or conservatively (send the request
+ // only on VBlank).
+ if (!opts.vsync_aggressive)
+ vsync_wait();
// DBE painting mode, only need to swap the buffer
if (opts.dbe) {
@@ -1739,6 +1764,9 @@ paint_all(Display *dpy, XserverRegion region, win *t) {
0, 0, root_width, root_height);
}
+ if (opts.vsync_aggressive)
+ vsync_wait();
+
XFlush(dpy);
#ifdef DEBUG_REPAINT
@@ -2127,7 +2155,7 @@ determine_fade(Display *dpy, win *w) {
*/
static void
win_update_shape(Display *dpy, win *w) {
- if (shape_exists && (opts.shadow_ignore_shaped /* || opts.clear_shadow */)) {
+ if (shape_exists) {
// Bool bounding_shaped_old = w->bounding_shaped;
w->bounding_shaped = wid_bounding_shaped(dpy, w->id);
@@ -2436,6 +2464,13 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
XFixesCopyRegion(dpy, damage, w->extents);
}
+ // If window geometry did not change, don't free extents here
+ if (w->a.x != ce->x || w->a.y != ce->y
+ || w->a.width != ce->width || w->a.height != ce->height) {
+ free_region(dpy, &w->extents);
+ free_region(dpy, &w->border_size);
+ }
+
w->a.x = ce->x;
w->a.y = ce->y;
@@ -2450,6 +2485,11 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
w->a.height = ce->height;
w->a.border_width = ce->border_width;
calc_win_size(dpy, w);
+
+ // Rounded corner detection is affected by window size
+ if (shape_exists && opts.shadow_ignore_shaped
+ && opts.detect_rounded_corners && w->bounding_shaped)
+ win_update_shape(dpy, w);
}
if (w->a.map_state != IsUnmapped && damage) {
@@ -2458,10 +2498,6 @@ configure_win(Display *dpy, XConfigureEvent *ce) {
XFixesDestroyRegion(dpy, extents);
add_damage(dpy, damage);
}
-
- // Window extents and border_size may have changed
- free_region(dpy, &w->extents);
- free_region(dpy, &w->border_size);
}
w->a.override_redirect = ce->override_redirect;
@@ -3307,6 +3343,9 @@ usage(void) {
"--sw-opti\n"
" Limit compton to repaint at most once every 1 / refresh_rate\n"
" second to boost performance. Experimental.\n"
+ "--vsync-aggressive\n"
+ " Attempt to send painting request before VBlank and do XFlush()\n"
+ " during VBlank. This switch may be lifted out at any moment.\n"
"\n"
"Format of a condition:\n"
"\n"
@@ -3727,6 +3766,7 @@ get_cfg(int argc, char *const *argv) {
{ "dbe", no_argument, NULL, 272 },
{ "paint-on-overlay", no_argument, NULL, 273 },
{ "sw-opti", no_argument, NULL, 274 },
+ { "vsync-aggressive", no_argument, NULL, 275 },
// Must terminate with a NULL entry
{ NULL, 0, NULL, 0 },
};
@@ -3909,6 +3949,10 @@ get_cfg(int argc, char *const *argv) {
// --sw-opti
opts.sw_opti = True;
break;
+ case 275:
+ // --vsync-aggressive
+ opts.vsync_aggressive = True;
+ break;
default:
usage();
break;
diff --git a/compton.h b/compton.h
index 8d17dbacf..9ec61fcbb 100644
--- a/compton.h
+++ b/compton.h
@@ -115,6 +115,8 @@ extern struct timeval time_start;
// Window size is changed
#define WFLAG_SIZE_CHANGE 0x0001
+// Window size/position is changed
+#define WFLAG_POS_CHANGE 0x0002
/**
* Types
@@ -280,7 +282,7 @@ typedef struct _win {
struct _win *prev_trans;
} win;
-typedef enum _vsync_t {
+typedef enum {
VSYNC_NONE,
VSYNC_DRM,
VSYNC_OPENGL,
@@ -317,6 +319,8 @@ typedef struct _options {
vsync_t vsync;
/// Whether to enable double buffer.
Bool dbe;
+ /// Whether to do VSync aggressively.
+ Bool vsync_aggressive;
// Shadow
Bool wintype_shadow[NUM_WINTYPES];