Created
September 11, 2013 15:00
-
-
Save richardgv/6524881 to your computer and use it in GitHub Desktop.
chjj/compton #140: Possible fix
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/src/compton.c b/src/compton.c | |
index b8f1fc6..92378b0 100644 | |
--- a/src/compton.c | |
+++ b/src/compton.c | |
@@ -1102,9 +1102,16 @@ paint_preprocess(session_t *ps, win *list) { | |
next = w->next; | |
opacity_t opacity_old = w->opacity; | |
- // Destroy reg_ignore on all windows if they should expire | |
- if (ps->reg_ignore_expire) | |
- free_region(ps, &w->reg_ignore); | |
+ // Data expiration | |
+ { | |
+ // Remove built shadow if needed | |
+ if (w->flags & WFLAG_SIZE_CHANGE) | |
+ free_paint(ps, &w->shadow_paint); | |
+ | |
+ // Destroy reg_ignore on all windows if they should expire | |
+ if (ps->reg_ignore_expire) | |
+ free_region(ps, &w->reg_ignore); | |
+ } | |
// Update window opacity target and dim state if asked | |
if (WFLAG_OPCT_CHANGE & w->flags) { | |
@@ -1115,43 +1122,33 @@ paint_preprocess(session_t *ps, win *list) { | |
// Run fading | |
run_fade(ps, w, steps); | |
+ // Opacity will not change, from now on. | |
+ | |
// Give up if it's not damaged or invisible, or it's unmapped and its | |
- // pixmap is gone (for example due to a ConfigureNotify) | |
+ // pixmap is gone (for example due to a ConfigureNotify), or when it's | |
+ // excluded | |
if (!w->damaged | |
|| w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 | |
|| w->a.x >= ps->root_width || w->a.y >= ps->root_height | |
- || ((IsUnmapped == w->a.map_state || w->destroyed) | |
- && !w->paint.pixmap)) { | |
+ || ((IsUnmapped == w->a.map_state || w->destroyed) && !w->paint.pixmap) | |
+ || get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0] | |
+ || w->paint_excluded) | |
to_paint = false; | |
- } | |
- to_paint = to_paint && !w->paint_excluded; | |
+ // to_paint will never change afterward | |
- if (to_paint) { | |
- // If opacity changes | |
- if (w->opacity != opacity_old) { | |
- win_determine_mode(ps, w); | |
- add_damage_win(ps, w); | |
- } | |
- | |
- if (get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0]) | |
- to_paint = false; | |
- } | |
+ // Determine mode as early as possible | |
+ if (to_paint && (!w->to_paint || w->opacity != opacity_old)) | |
+ win_determine_mode(ps, w); | |
if (to_paint) { | |
// Fetch bounding region | |
- if (!w->border_size) { | |
+ if (!w->border_size) | |
w->border_size = border_size(ps, w, true); | |
- } | |
// Fetch window extents | |
- if (!w->extents) { | |
+ if (!w->extents) | |
w->extents = win_extents(ps, w); | |
- // If w->extents does not exist, the previous add_damage_win() | |
- // call when opacity changes has no effect, so redo it here. | |
- if (w->opacity != opacity_old) | |
- add_damage_win(ps, w); | |
- } | |
// Calculate frame_opacity | |
{ | |
@@ -1164,6 +1161,8 @@ paint_preprocess(session_t *ps, win *list) { | |
else | |
w->frame_opacity = 0.0; | |
+ // Destroy all reg_ignore above when frame opaque state changes on | |
+ // SOLID mode | |
if (w->to_paint && WMODE_SOLID == mode_old | |
&& (0.0 == frame_opacity_old) != (0.0 == w->frame_opacity)) | |
ps->reg_ignore_expire = true; | |
@@ -1174,24 +1173,18 @@ paint_preprocess(session_t *ps, win *list) { | |
w->shadow_opacity = ps->o.shadow_opacity * w->frame_opacity; | |
else | |
w->shadow_opacity = ps->o.shadow_opacity * get_opacity_percent(w); | |
- | |
- // Rebuild shadow if necessary | |
- if (w->flags & WFLAG_SIZE_CHANGE) { | |
- free_paint(ps, &w->shadow_paint); | |
- } | |
- | |
- if (w->shadow && !paint_isvalid(ps, &w->shadow_paint)) | |
- win_build_shadow(ps, w, 1); | |
} | |
+ // Add window to damaged area if its painting status changes | |
+ // or opacity changes | |
+ if (to_paint != w->to_paint || w->opacity != opacity_old) | |
+ add_damage_win(ps, w); | |
+ | |
+ // Destroy all reg_ignore above when window mode changes | |
if ((to_paint && WMODE_SOLID == w->mode) | |
!= (w->to_paint && WMODE_SOLID == mode_old)) | |
ps->reg_ignore_expire = true; | |
- // Add window to damaged area if its painting status changes | |
- if (to_paint != w->to_paint) | |
- add_damage_win(ps, w); | |
- | |
if (to_paint) { | |
// Generate ignore region for painting to reduce GPU load | |
if (ps->reg_ignore_expire || !w->to_paint) { | |
@@ -1264,6 +1257,10 @@ paint_preprocess(session_t *ps, win *list) { | |
if (UNSET != ps->o.redirected_force) | |
unredir_possible = !ps->o.redirected_force; | |
+ // If there's no window to paint, and the screen isn't redirected, | |
+ // don't redirect it. | |
+ if (ps->o.unredir_if_possible && is_highest && !ps->redirected) | |
+ unredir_possible = true; | |
if (unredir_possible) { | |
if (ps->redirected) { | |
if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit) | |
@@ -1785,6 +1782,10 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t | |
for (win *w = t; w; w = w->prev_trans) { | |
// Painting shadow | |
if (w->shadow) { | |
+ // Lazy shadow building | |
+ if (!paint_isvalid(ps, &w->shadow_paint)) | |
+ win_build_shadow(ps, w, 1); | |
+ | |
// Shadow is to be painted based on the ignore region of current | |
// window | |
if (w->reg_ignore) { | |
@@ -2050,6 +2051,13 @@ wid_get_prop_wintype(session_t *ps, Window wid) { | |
static void | |
map_win(session_t *ps, Window id) { | |
+ // Unmap overlay window if it got mapped but we are currently not | |
+ // in redirected state. | |
+ if (ps->overlay && id == ps->overlay && !ps->redirected) { | |
+ XUnmapWindow(ps->dpy, ps->overlay); | |
+ XFlush(ps->dpy); | |
+ } | |
+ | |
win *w = find_win(ps, id); | |
// Don't care about window mapping if it's an InputOnly window | |
@@ -2831,14 +2839,13 @@ add_win(session_t *ps, Window id, Window prev) { | |
assert(IsViewable == map_state || IsUnmapped == map_state); | |
new->a.map_state = IsUnmapped; | |
- // Get window picture format | |
- if (InputOutput == new->a.class) | |
+ if (InputOutput == new->a.class) { | |
+ // Get window picture format | |
new->pictfmt = XRenderFindVisualFormat(ps->dpy, new->a.visual); | |
- // Create Damage for window | |
- if (InputOutput == new->a.class) { | |
- set_ignore_next(ps); | |
- new->damage = XDamageCreate(ps->dpy, id, XDamageReportNonEmpty); | |
+ // Create Damage for window | |
+ set_ignore_next(ps); | |
+ new->damage = XDamageCreate(ps->dpy, id, XDamageReportNonEmpty); | |
} | |
calc_win_size(ps, new); | |
@@ -6097,6 +6104,11 @@ init_overlay(session_t *ps) { | |
// Retrieve DamageNotify on root window if we are painting on an | |
// overlay | |
// root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty); | |
+ | |
+ // Unmap overlay, firstly. But this typically does not work because | |
+ // the window isn't created yet. | |
+ // XUnmapWindow(ps->dpy, ps->overlay); | |
+ // XFlush(ps->dpy); | |
} | |
else { | |
fprintf(stderr, "Cannot get X Composite overlay window. Falling " | |
@@ -6371,6 +6383,9 @@ tmout_unredir_callback(session_t *ps, timeout_t *tmout) { | |
*/ | |
static bool | |
mainloop(session_t *ps) { | |
+ // Don't miss timeouts even when we have a LOT of other events! | |
+ timeout_run(ps); | |
+ | |
// Process existing events | |
// Sometimes poll() returns 1 but no events are actually read, | |
// causing XNextEvent() to block, I have no idea what's wrong, so we | |
@@ -6444,8 +6459,6 @@ mainloop(session_t *ps) { | |
free(ptv); | |
ptv = NULL; | |
- timeout_run(ps); | |
- | |
return true; | |
} | |
@@ -6732,6 +6745,7 @@ session_init(session_t *ps_old, int argc, char **argv) { | |
| ExposureMask | |
| StructureNotifyMask | |
| PropertyChangeMask); | |
+ XFlush(ps->dpy); | |
ps->root_width = DisplayWidth(ps->dpy, ps->scr); | |
ps->root_height = DisplayHeight(ps->dpy, ps->scr); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment