]> git.draconx.ca Git - rrace.git/blobdiff - src/x11.c
x11: Fix redraw on window resize.
[rrace.git] / src / x11.c
index 874bfdc57399c4cf6ecf5b7ae2c2d5f2981501ef..6954f06a15a5a30345ce43be670b5227d411bc0f 100644 (file)
--- a/src/x11.c
+++ b/src/x11.c
@@ -361,3 +361,56 @@ void x11_redraw_game(struct app_state *state, uint_fast32_t mask)
                mask >>= 1;
        }
 }
+
+/*
+ * Deferred redraw of tiles after resize/expose to avoid redundant drawing.
+ *
+ * Record any tiles that need to be redrawn due to resizes or expose events,
+ * then, after a short delay, perform all the accumulated redraws at once.
+ *
+ * This is implemented using both a work proc and a timeout, because it seems
+ * that rendering directly inside the timeout callback gives poor results:
+ * possibly redrawing outdated intermediate positions during "fast" resizes
+ * long after the resizing has stopped.  This does not happen when drawing
+ * from a work proc.
+ */
+static Boolean do_render(void *data)
+{
+       struct app_state *state = data;
+
+       x11_redraw_goal(state, state->render_goal_mask);
+       x11_redraw_game(state, state->render_game_mask);
+
+       state->render_goal_mask = state->render_game_mask = 0;
+       state->render_proc = 0;
+       state->render_tick = 0;
+       return True;
+}
+
+static void start_render(void *data, XtIntervalId *id)
+{
+       struct app_state *state = data;
+       XtAppContext app;
+
+       if (state->render_proc)
+               return;
+
+       app = XtWidgetToApplicationContext(state->game);
+       state->render_proc = XtAppAddWorkProc(app, do_render, state);
+}
+
+void x11_queue_render(struct app_state *state, uint_fast32_t game_mask,
+                                               uint_fast16_t goal_mask)
+{
+       uint_fast32_t changed = 0;
+       XtAppContext app;
+
+       changed |= state->render_game_mask |= game_mask;
+       changed |= state->render_goal_mask |= goal_mask;
+
+       if (state->render_tick || !changed)
+               return;
+
+       app = XtWidgetToApplicationContext(state->game);
+       state->render_tick = XtAppAddTimeOut(app, 3, start_render, state);
+}