Fix animation
authorH.G. Muller <h.g.muller@hccnet.nl>
Wed, 17 Oct 2012 17:41:11 +0000 (19:41 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Tue, 6 Nov 2012 13:13:55 +0000 (14:13 +0100)
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
draw.c
xboard.c
xoptions.c

diff --git a/board.c b/board.c
index 6abbabb..a0aa2fc 100644 (file)
--- 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 (file)
--- 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
index 032214d..a86877f 100644 (file)
--- 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);
 }
index 5616840..888fb65 100644 (file)
@@ -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)