Bug fix: Fading blocks in rare circumstances

- In very rare circumstances, poll() to the X connection returns 1 but
  no events are read out, causing XNextEvent() in the main loop to wait
  infinitely until another event comes, typically affecting fading
  process only, causing fading to appear somehow stopped. This commit
  adds a (possible) fix.

- Listen to Expose events of the X Composite overlay window if we are
  painting to it, to avoid making some parts of the screen blank when
  switching out of X screen in --paint-on-overlay mode.

- Drop "fade_fin" member of struct _win, because it's pretty useless.

- Drop unused "root" parameter of expose_root(), move get_time_ms() to
  compton.h, etc.
This commit is contained in:
Richard Grenville 2012-10-29 22:00:11 +08:00
parent 9b61999cae
commit 853d20ef56
2 changed files with 34 additions and 39 deletions

View File

@ -219,21 +219,6 @@ static options_t opts = {
unsigned long fade_time = 0; unsigned long fade_time = 0;
/**
* Get current system clock in milliseconds.
*
* The return type must be unsigned long because so many milliseconds have
* passed since the epoch.
*/
static unsigned long
get_time_ms() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
/** /**
* Get the time left before next fading point. * Get the time left before next fading point.
* *
@ -256,10 +241,8 @@ fade_timeout(void) {
*/ */
static void static void
run_fade(Display *dpy, win *w, unsigned steps) { run_fade(Display *dpy, win *w, unsigned steps) {
// If we reach target opacity, set fade_fin so the callback gets // If we have reached target opacity, return
// executed
if (w->opacity == w->opacity_tgt) { if (w->opacity == w->opacity_tgt) {
w->fade_fin = True;
return; return;
} }
@ -278,15 +261,9 @@ run_fade(Display *dpy, win *w, unsigned steps) {
w->opacity_tgt, OPAQUE); w->opacity_tgt, OPAQUE);
} }
if (w->opacity == w->opacity_tgt) { if (w->opacity != w->opacity_tgt) {
w->fade_fin = True;
return;
}
else {
idling = False; idling = False;
} }
w->fade_fin = False;
} }
/** /**
@ -2331,7 +2308,6 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
new->opacity_prop_client = OPAQUE; new->opacity_prop_client = OPAQUE;
new->fade = False; new->fade = False;
new->fade_callback = NULL; new->fade_callback = NULL;
new->fade_fin = False;
new->alpha_pict = None; new->alpha_pict = None;
new->frame_opacity = 1.0; new->frame_opacity = 1.0;
new->frame_alpha_pict = None; new->frame_alpha_pict = None;
@ -2743,7 +2719,7 @@ error(Display *dpy, XErrorEvent *ev) {
} }
static void static void
expose_root(Display *dpy, Window root, XRectangle *rects, int nrects) { expose_root(Display *dpy, XRectangle *rects, int nrects) {
XserverRegion region = XFixesCreateRegion(dpy, rects, nrects); XserverRegion region = XFixesCreateRegion(dpy, rects, nrects);
add_damage(dpy, region); add_damage(dpy, region);
} }
@ -3050,7 +3026,7 @@ ev_circulate_notify(XCirculateEvent *ev) {
inline static void inline static void
ev_expose(XExposeEvent *ev) { ev_expose(XExposeEvent *ev) {
if (ev->window == root) { if (ev->window == root || (overlay && ev->window == overlay)) {
int more = ev->count + 1; int more = ev->count + 1;
if (n_expose == size_expose) { if (n_expose == size_expose) {
if (expose_rects) { if (expose_rects) {
@ -3070,7 +3046,7 @@ ev_expose(XExposeEvent *ev) {
n_expose++; n_expose++;
if (ev->count == 0) { if (ev->count == 0) {
expose_root(dpy, root, expose_rects, n_expose); expose_root(dpy, expose_rects, n_expose);
n_expose = 0; n_expose = 0;
} }
} }
@ -3195,6 +3171,8 @@ ev_handle(XEvent *ev) {
if (wid) { if (wid) {
if (root == wid) if (root == wid)
window_name = "(Root window)"; window_name = "(Root window)";
else if (overlay == wid)
window_name = "(Overlay)";
else { else {
win *w = find_win(dpy, wid); win *w = find_win(dpy, wid);
if (!w) if (!w)
@ -4359,6 +4337,9 @@ init_overlay(void) {
XFixesSetWindowShapeRegion(dpy, overlay, ShapeInput, 0, 0, region); XFixesSetWindowShapeRegion(dpy, overlay, ShapeInput, 0, 0, region);
XFixesDestroyRegion (dpy, region); XFixesDestroyRegion (dpy, region);
// Listen to Expose events on the overlay
XSelectInput(dpy, overlay, ExposureMask);
// Retrieve DamageNotify on root window if we are painting on an // Retrieve DamageNotify on root window if we are painting on an
// overlay // overlay
// root_damage = XDamageCreate(dpy, root, XDamageReportNonEmpty); // root_damage = XDamageCreate(dpy, root, XDamageReportNonEmpty);
@ -4580,12 +4561,17 @@ main(int argc, char **argv) {
while (1) { while (1) {
Bool ev_received = False; Bool ev_received = False;
while (QLength(dpy) while (XEventsQueued(dpy, QueuedAfterReading)
|| (evpoll(&ufd, || (evpoll(&ufd,
(ev_received ? 0: (idling ? -1: fade_timeout()))) > 0)) { (ev_received ? 0: (idling ? -1: fade_timeout()))) > 0)) {
XNextEvent(dpy, &ev); // Sometimes poll() returns 1 but no events are actually read, causing
ev_handle((XEvent *) &ev); // XNextEvent() to block, I have no idea what's wrong, so we check for the
ev_received = True; // number of events here
if (XEventsQueued(dpy, QueuedAfterReading)) {
XNextEvent(dpy, &ev);
ev_handle((XEvent *) &ev);
ev_received = True;
}
} }
// idling will be turned off during paint_preprocess() if needed // idling will be turned off during paint_preprocess() if needed

View File

@ -235,8 +235,6 @@ typedef struct _win {
Bool fade; Bool fade;
/// Callback to be called after fading completed. /// Callback to be called after fading completed.
void (*fade_callback) (Display *dpy, struct _win *w); void (*fade_callback) (Display *dpy, struct _win *w);
/// Whether fading is finished.
Bool fade_fin;
// Frame-opacity-related members // Frame-opacity-related members
/// Current window frame opacity. Affected by window opacity. /// Current window frame opacity. Affected by window opacity.
@ -696,8 +694,20 @@ free_damage(Display *dpy, Damage *p) {
} }
} }
/**
* Get current system clock in milliseconds.
*
* The return type must be unsigned long because so many milliseconds have
* passed since the epoch.
*/
static unsigned long static unsigned long
get_time_ms(void); get_time_ms(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
static int static int
fade_timeout(void); fade_timeout(void);
@ -714,8 +724,7 @@ set_fade_callback(Display *dpy, win *w,
*/ */
static inline void static inline void
check_fade_fin(Display *dpy, win *w) { check_fade_fin(Display *dpy, win *w) {
if (w->fade_fin) { if (w->fade_callback && w->opacity == w->opacity_tgt) {
w->fade_fin = False;
// Must be the last line as the callback could destroy w! // Must be the last line as the callback could destroy w!
set_fade_callback(dpy, w, NULL, True); set_fade_callback(dpy, w, NULL, True);
} }
@ -966,7 +975,7 @@ static int
error(Display *dpy, XErrorEvent *ev); error(Display *dpy, XErrorEvent *ev);
static void static void
expose_root(Display *dpy, Window root, XRectangle *rects, int nrects); expose_root(Display *dpy, XRectangle *rects, int nrects);
static Bool static Bool
wid_get_text_prop(Display *dpy, Window wid, Atom prop, wid_get_text_prop(Display *dpy, Window wid, Atom prop,