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