From 053dc1f79f78ff5d5d4d0f625f68a7d8076a30a0 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Wed, 17 Oct 2012 19:41:11 +0200 Subject: [PATCH] Fix animation Because FrameDelay does block the event loop, even though it releaes the CPU, expose events start to lag behind the actual drawing. By combining expose events for overlapping squares, rather than decompose them into 3 rectangles, this problem seems to go away. But only if there is an extra exposure on the squares to be drawn also non-overlapping frames will be properly drawn (?!). --- board.c | 11 +++++++++-- draw.c | 4 ++-- xboard.c | 5 ++--- xoptions.c | 8 ++++++-- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/board.c b/board.c index 6abbabb..a0aa2fc 100644 --- a/board.c +++ b/board.c @@ -479,12 +479,12 @@ AnimationFrame (AnimNr anr, Pnt *frame, ChessSquare piece) MyRectangle updates[4]; MyRectangle overlap; Pnt pt; - int count, i; AnimState *anim = &anims[anr]; + int count, i, x, y, w, h; /* Save what we are about to draw into the new buffer */ CopyRectangle(anr, DISP, 0, - frame->x, frame->y, squareSize, squareSize, + x = frame->x, y = frame->y, w = squareSize, h = squareSize, 0, 0); /* Erase bits of the previous frame */ @@ -503,11 +503,17 @@ AnimationFrame (AnimNr anr, Pnt *frame, ChessSquare piece) updates[i].y - anim->prevFrame.y, updates[i].width, updates[i].height, updates[i].x, updates[i].y); + /* [HGM] correct expose rectangle to encompass both overlapping squares */ + if(x > anim->prevFrame.x) w += x - anim->prevFrame.x, x = anim->prevFrame.x; + else w += anim->prevFrame.x - x; + if(y > anim->prevFrame.y) h += y - anim->prevFrame.y, y = anim->prevFrame.y; + else h += anim->prevFrame.y - y; } else { /* Easy when no overlap */ CopyRectangle(anr, 2, DISP, 0, 0, squareSize, squareSize, anim->prevFrame.x, anim->prevFrame.y); + GraphExpose(currBoard, anim->prevFrame.x, anim->prevFrame.y, squareSize, squareSize); } /* Save this frame for next time round */ @@ -522,6 +528,7 @@ AnimationFrame (AnimNr anr, Pnt *frame, ChessSquare piece) CopyRectangle(anr, 0, DISP, 0, 0, squareSize, squareSize, frame->x, frame->y); + GraphExpose(currBoard, x, y, w, h); } static void diff --git a/draw.c b/draw.c index 02c2805..f7cbe1b 100644 --- a/draw.c +++ b/draw.c @@ -778,8 +778,8 @@ void CopyRectangle (AnimNr anr, int srcBuf, int destBuf, cairo_rectangle (cr, destX, destY, width, height); cairo_fill (cr); cairo_destroy (cr); - if(c_animBufs[anr+destBuf] == csBoardWindow) - GraphExpose(currBoard, destX, destY, squareSize, squareSize); + if(c_animBufs[anr+destBuf] == csBoardWindow) // suspect that GTK needs this! + GraphExpose(currBoard, destX, destY, width, height); } void diff --git a/xboard.c b/xboard.c index 032214d..a86877f 100644 --- a/xboard.c +++ b/xboard.c @@ -1717,10 +1717,7 @@ do_flash_delay (unsigned long msec) void FlashDelay (int flash_delay) { -#ifdef TODO_GTK - XSync(xDisplay, False); if(flash_delay) do_flash_delay(flash_delay); -#endif } double @@ -2492,6 +2489,8 @@ FrameDelay (int time) #ifdef TODO_GTK XSync(xDisplay, False); #endif +// gtk_main_iteration_do(False); + if (time > 0) usleep(time * 1000); } diff --git a/xoptions.c b/xoptions.c index 5616840..888fb65 100644 --- a/xoptions.c +++ b/xoptions.c @@ -864,11 +864,15 @@ GraphEventProc(GtkWidget *widget, GdkEvent *event, gpointer gdata) void GraphExpose (Option *opt, int x, int y, int w, int h) { +#if 0 + GdkRectangle r; + r.x = x; r.y = y; r.width = w; r.height = h; + gdk_window_invalidate_rect(((GtkWidget *)(opt->handle))->window, &r, FALSE); +#endif GdkEventExpose e; if(!opt->handle) return; e.area.x = x; e.area.y = y; e.area.width = w; e.area.height = h; e.count = -1; e.type = GDK_EXPOSE; // count = -1: kludge to suppress sizing - GraphEventProc(opt->handle, (GdkEvent// gtk_check_menu_item_set_active((GtkCheckMenuItem *) item->handle, state); - *) &e, (gpointer) opt); // fake expose event + GraphEventProc(opt->handle, (GdkEvent *) &e, (gpointer) opt); // fake expose event } void GenericCallback(GtkWidget *widget, gpointer gdata) -- 1.7.0.4