These changes fix flickering of selected pieces being dragged, using
the 2D board in GTK 3.
---
 export.c   |   3 +-
 gtkboard.c | 178 +++++++++++++++--------------------------------------
 render.c   |  39 +++++++++++-
 render.h   |   3 +-
 4 files changed, 89 insertions(+), 134 deletions(-)

diff --git a/export.c b/export.c
index ea452485..58df1e85 100644
--- a/export.c
+++ b/export.c
@@ -636,7 +636,8 @@ GenerateImage(renderimages * pri, renderdata * prd,
                   LogCube(nCube) + (doubled != 0),
                   nOrient,
                   anResignPosition, fResign, nResignOrientation,
-                  anArrowPosition, ms.gs != GAME_NONE, fMove == 1, 0, 0, 
BOARD_WIDTH * nSize, BOARD_HEIGHT * nSize);
+                  anArrowPosition, ms.gs != GAME_NONE, fMove == 1, 0, 0, 
BOARD_WIDTH * nSize, BOARD_HEIGHT * nSize,
+                  NULL);
 
     /* crop */
 
diff --git a/gtkboard.c b/gtkboard.c
index 6b5e1fbe..588c7d90 100644
--- a/gtkboard.c
+++ b/gtkboard.c
@@ -291,7 +291,8 @@ RenderArea(BoardData * bd, unsigned char *puch, int x, int 
y, int
                   anDice, anDicePosition, bd->colour == bd->turn,
                   anCubePosition, LogCube(bd->cube) + (bd->doubled != 0),
                   nOrient, anResignPosition,
-                  abs(bd->resigned), nResignOrientation, anArrowPosition, 
bd->playing, bd->turn == 1, x, y, cx, cy);
+                  abs(bd->resigned), nResignOrientation, anArrowPosition, 
bd->playing, bd->turn == 1, x, y, cx, cy,
+                  bd);
 }
 
 static void
@@ -314,6 +315,30 @@ board_draw_area(cairo_t * cr, gint x, gint y, gint cx, 
gint cy, BoardData * bd)
     RenderArea(bd, puch, x, y, cx, cy);
     draw_rgb_image(cr, puch, x, y, cx, cy);
     free(puch);
+
+#if defined(USE_BOARD3D)
+    if (bd && display_is_2d(bd->rd)) {
+#endif
+        if (bd && bd->DragTargetHelp) {
+            for (int i = 0; i <= 3; ++i) {
+                if (bd->iTargetHelpPoints[i] != -1) {
+                    int ptx, pty, ptcx, ptcy;
+                    point_area(bd, bd->iTargetHelpPoints[i], &ptx, &pty, 
&ptcx, &ptcy);
+                    cairo_save(cr);
+                    cairo_set_source_rgba(cr, 0, 1, 0, 1.0); // Opaque green
+                    cairo_set_line_width(cr, 2.0);
+                    cairo_rectangle(cr, ptx + 1, pty + 1, ptcx - 2, ptcy - 2);
+                    cairo_stroke(cr);
+                    cairo_restore(cr);
+                }
+            }
+#if !GTK_CHECK_VERSION(3,0,0)
+            gtk_widget_queue_draw(bd->drawing_area);
+#endif
+        }
+#if defined(USE_BOARD3D)
+    }
+#endif
 }
 
 #if GTK_CHECK_VERSION(3,0,0)
@@ -975,13 +1000,8 @@ static void
 board_drag(GtkWidget * UNUSED(widget), BoardData * bd, int x, int y)
 #endif
 {
-    cairo_t *cr;
-    unsigned char *puch, *puchNew, *puchChequer;
-    int s = bd->rd->nSize;
-    GdkWindow *window = gtk_widget_get_window(bd->drawing_area);
-#if GTK_CHECK_VERSION(3,22,0)
-    GdkDrawingContext *context;
-#endif
+    g_assert(bd != NULL);
+    g_assert(bd->drawing_area != NULL);
 
 #if defined(USE_BOARD3D)
     if (display_is_3d(bd->rd)) {
@@ -991,64 +1011,21 @@ board_drag(GtkWidget * UNUSED(widget), BoardData * bd, 
int x, int y)
     }
 #endif
 
-    // gdk_window_process_updates is deprecated since GTK
-    // 3.22, but necessary on the 2D board for smooth
-    // animation.
-    gdk_window_process_updates(window, FALSE);
-
-    if (s == 0)
-        return;
-
-    puch = g_alloca(6 * s * 6 * s * 3);
-    puchNew = g_alloca(6 * s * 6 * s * 3);
-    puchChequer = g_alloca(6 * s * 6 * s * 3);
-
-    RenderArea(bd, puch, bd->x_drag - 3 * s, bd->y_drag - 3 * s, 6 * s, 6 * s);
-    RenderArea(bd, puchNew, x - 3 * s, y - 3 * s, 6 * s, 6 * s);
-    RefractBlendClip(puchChequer, 6 * s * 3, 0, 0, 6 * s, 6 * s, puchNew,
-                     6 * s * 3, 0, 0,
-                     bd->ri.achChequer[bd->drag_colour > 0], 6 * s * 4, 0,
-                     0, bd->ri.asRefract[bd->drag_colour > 0], 6 * s, 6 * s, 6 
* s);
-
-    {
-        gtk_locdef_region *pr;
-        gtk_locdef_rectangle r;
-
-        r.x = bd->x_drag - 3 * s;
-        r.y = bd->y_drag - 3 * s;
-        r.width = 6 * s;
-        r.height = 6 * s;
-        pr = gtk_locdef_create_rectangle(&r);
-
-        r.x = x - 3 * s;
-        r.y = y - 3 * s;
-        gtk_locdef_union_rectangle(pr, &r);
-
-#if GTK_CHECK_VERSION(3,22,0)
-        context = gdk_window_begin_draw_frame(window, pr);
-#else
-        gdk_window_begin_paint_region(window, pr);
-#endif
-
-        gtk_locdef_region_destroy(pr);
-    }
-
-#if GTK_CHECK_VERSION(3,22,0)
-    cr = gdk_drawing_context_get_cairo_context(context);
-#else
-    cr = gdk_cairo_create(window);
-#endif
+    int chequer_w = CHEQUER_WIDTH * bd->rd->nSize;
+    int chequer_h = CHEQUER_HEIGHT * bd->rd->nSize;
+    int old_x = bd->x_drag;
+    int old_y = bd->y_drag;
 
-    draw_rgb_image(cr, puch, bd->x_drag - 3 * s, bd->y_drag - 3 * s, 6 * s, 6 
* s);
-    draw_rgb_image(cr, puchChequer, x - 3 * s, y - 3 * s, 6 * s, 6 * s);
+    // Invalidate (redraw) the old chequer area if it's valid
+    if (old_x >= 0 && old_y >= 0)
+        gtk_widget_queue_draw_area(bd->drawing_area,
+            old_x - chequer_w/2, old_y - chequer_h/2, chequer_w, chequer_h);
 
-#if GTK_CHECK_VERSION(3,22,0)
-    gdk_window_end_draw_frame(window, context);
-#else
-    cairo_destroy(cr);
-    gdk_window_end_paint(window);
-#endif
+    // Invalidate the new chequer area
+    gtk_widget_queue_draw_area(bd->drawing_area,
+        x - chequer_w/2, y - chequer_h/2, chequer_w, chequer_h);
 
+    // Update drag position
     bd->x_drag = x;
     bd->y_drag = y;
 }
@@ -1091,6 +1068,11 @@ board_end_drag(GtkWidget * UNUSED(widget), BoardData * 
bd)
 #else
     cairo_destroy(cr);
 #endif
+
+#if !GTK_CHECK_VERSION(3,0,0)
+    gtk_widget_queue_draw(bd->drawing_area);
+    gdk_window_process_updates(window, FALSE);
+#endif
 }
 
 /* This code is called on a button release event
@@ -2137,6 +2119,10 @@ board_button_release(GtkWidget * board, GdkEventButton * 
event, BoardData * bd)
     bd->DragTargetHelp = 0;
     bd->drag_point = -1;
 
+#if !GTK_CHECK_VERSION(3,0,0)
+    gtk_widget_queue_draw(bd->drawing_area);
+#endif
+
     return TRUE;
 }
 
@@ -2173,72 +2159,6 @@ board_motion_notify(GtkWidget * board, GdkEventMotion * 
event, BoardData * bd)
             bd->DragTargetHelp = legal_dest_points(bd, bd->iTargetHelpPoints);
         }
     }
-#if defined(USE_BOARD3D)
-    if (display_is_2d(bd->rd))
-#endif
-    {
-        if (bd->DragTargetHelp) {       /* Display 2d drag target help */
-            gint i, ptx, pty, ptcx, ptcy;
-            cairo_t *cr;
-            GdkWindow *window = gtk_widget_get_window(board);
-#if GTK_CHECK_VERSION(3,22,0)
-            cairo_region_t * cairoRegion = cairo_region_create();
-            GdkDrawingContext *context;
-#endif
-
-#if GTK_CHECK_VERSION(3,0,0)
-            GdkRGBA TargetHelpRGBA;
-
-            TargetHelpRGBA.red = 0.0;
-            TargetHelpRGBA.green = 1.0;
-            TargetHelpRGBA.blue = 0.0;
-            TargetHelpRGBA.alpha = 1.0;
-#else
-            GdkColor TargetHelpColor;
-
-            /* values of RGB components within GdkColor are
-             * taken from 0 to 65535, not 0 to 255. */
-            TargetHelpColor.red = 0 * (65535 / 255);
-            TargetHelpColor.green = 255 * (65535 / 255);
-            TargetHelpColor.blue = 0 * (65535 / 255);
-            TargetHelpColor.pixel = (guint32) (TargetHelpColor.red * 65536 +
-                                                TargetHelpColor.green * 256 + 
TargetHelpColor.blue);
-            /* get the closest color available in the colormap if no 24-bit */
-            gdk_colormap_alloc_color(gtk_widget_get_colormap(board), 
&TargetHelpColor, TRUE, TRUE);
-#endif
-
-#if GTK_CHECK_VERSION(3,22,0)
-            context = gdk_window_begin_draw_frame(window, cairoRegion);
-            cr = gdk_drawing_context_get_cairo_context(context);
-#else
-            cr = gdk_cairo_create(window);
-#endif
-
-#if GTK_CHECK_VERSION(3,0,0)
-            gdk_cairo_set_source_rgba(cr, &TargetHelpRGBA);
-#else
-            gdk_cairo_set_source_color(cr, &TargetHelpColor);
-#endif
-
-            /* draw help rectangles around target points */
-            for (i = 0; i <= 3; ++i) {
-                if (bd->iTargetHelpPoints[i] != -1) {
-                    /* calculate region coordinates for point */
-                    point_area(bd, bd->iTargetHelpPoints[i], &ptx, &pty, 
&ptcx, &ptcy);
-                    cairo_rectangle(cr, ptx + 1, pty + 1, ptcx - 2, ptcy - 2);
-                    cairo_set_line_width(cr, 1);
-                    cairo_stroke(cr);
-                }
-            }
-
-#if GTK_CHECK_VERSION(3,22,0)
-            gdk_window_end_draw_frame(window, context);
-            cairo_region_destroy(cairoRegion);
-#else
-            cairo_destroy(cr);
-#endif
-        }
-    }
 
     return TRUE;
 }
diff --git a/render.c b/render.c
index 2ec78b7d..5e3afc58 100644
--- a/render.c
+++ b/render.c
@@ -2388,6 +2388,29 @@ DrawChequers(renderdata * prd, unsigned char *puch, int 
nStride,
                      0, 4 * prd->nSize * (n - 4), 4 * prd->nSize, 4 * 
prd->nSize);
 }
 
+void DrawSingleChequer(renderdata *prd, unsigned char *puch, int nStride, 
renderimages *pri,
+                      int px, int py, int colour, int x, int y, int cx, int 
cy) {
+    int chequer_w = CHEQUER_WIDTH * prd->nSize;
+    int chequer_h = CHEQUER_HEIGHT * prd->nSize;
+    int colidx = (colour > 0) ? 1 : 0;
+
+    if (!pri || !pri->achChequer[colidx] || !pri->asRefract[colidx])
+        return;
+
+    RefractBlendClip(
+        puch, nStride,
+        px - x - chequer_w / 2, py - y - chequer_h / 2,
+        cx, cy,
+        puch, nStride,
+        px - x - chequer_w / 2, py - y - chequer_h / 2,
+        pri->achChequer[colidx],
+        chequer_w * 4,
+        0, 0,
+        pri->asRefract[colidx],
+        chequer_w, chequer_w, chequer_h
+    );
+}
+
 extern void
 CalculateArea(renderdata * prd, unsigned char *puch, int nStride,
               renderimages * pri, TanBoard anBoard,
@@ -2397,11 +2420,13 @@ CalculateArea(renderdata * prd, unsigned char *puch, 
int nStride,
               int nLogCube, int nCubeOrientation,
               const int anResignPosition[2],
               int fResign, int nResignOrientation,
-              int anArrowPosition[2], int UNUSED(fPlaying), int nPlayer, int 
x, int y, int cx, int cy)
+              int anArrowPosition[2], int UNUSED(fPlaying), int nPlayer, int 
x, int y, int cx, int cy,
+              void * board_data)
 {
 
     int i, xPoint, yPoint, cxPoint, cyPoint, nc;
     int anOffCalc[2];
+    BoardData *bd = (BoardData *)board_data;
 
     if (x < 0) {
         puch -= x * 3;
@@ -2490,11 +2515,19 @@ CalculateArea(renderdata * prd, unsigned char *puch, 
int nStride,
                 nc = anBoard[1][i - 1] - anBoard[0][24 - i];
                 break;
             }
-            if (nc)
-                DrawChequers(prd, puch, nStride, pri, i, abs(nc), nc > 0, x, 
y, cx, cy);
+            if (nc) {
+                int n = abs(nc);
+
+                if (n > 0)
+                    DrawChequers(prd, puch, nStride, pri, i, n, nc > 0, x, y, 
cx, cy);
+            }
         }
     }
 
+    if (bd && bd->drag_point >= 0) {
+        DrawSingleChequer(prd, puch, nStride, pri, bd->x_drag, bd->y_drag, 
bd->drag_colour, x, y, cx, cy);
+    }
+
     /* draw dice */
     for (i = 0; i < 2; i++)
         if (anDice[i] && intersects(x, y, cx, cy, anDicePosition[i][0] * 
prd->nSize,
diff --git a/render.h b/render.h
index 9839226a..f605dafa 100644
--- a/render.h
+++ b/render.h
@@ -161,7 +161,8 @@ extern void CalculateArea(renderdata * prd, unsigned char 
*puch, int nStride,
                           int nLogCube, int nCubeOrientation,
                           const int anResignPosition[2],
                           int fResign, int fResignOrientation,
-                          int anArrowPosition[2], int fPlaying, int nPlayer, 
int x, int y, int cx, int cy);
+                          int anArrowPosition[2], int fPlaying, int nPlayer, 
int x, int y, int cx, int cy,
+                          void *board_data);
 
 #if defined(USE_BOARD3D)
 extern gboolean widget3dValid;
-- 
2.43.0


Reply via email to