+#define MI_IS_MOUSE(MI) (False)
+
+/* Under xlockmore, MI_CLEARWINDOW runs immediately, and for animated clears
+ it delays execution while the animation runs. This doesn't work on
+ XScreenSaver, which has mandatory double-buffering on macOS/iOS/Android.
+
+ Tricky: As a result, MI_CLEARWINDOW doesn't clear the window until after
+ init_##() or draw_##() finishes.
+ */
+#ifdef USE_GL
+# define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi))
+#else
+# define MI_CLEARWINDOW(mi) ((mi)->needs_clear = True)
+#endif
+
+/* MI_INIT and MI_ABORT are XScreenSaver extensions. These exist primarily for
+ the sake of ports to macOS, iOS, and Android, all of which need to restart
+ individual screenhacks repeatedly in the same process. This requires
+ reusing MI_SCREEN() numbers; previously many xlockmore API hacks did not
+ support this the way they were supposed to.
+ */
+
+/* MI_INIT implements the following pattern, as seen in various forms at the
+ beginning of init_##():
+
+ if(!state_array) {
+ state_array = (state_t *)calloc(MI_NUM_SCREENS(mi), sizeof(state_t));
+ if(!state_array) {
+ fprintf(stderr, "%s: out of memory\n", progname);
+ return;
+ }
+ }
+ hack_free_state(mi);
+ memset(&state_array[MI_SCREEN(mi)], 0, sizeof(*state_array));
+
+ MI_INIT also assumes ownership of the state_array over to xlockmore.c,
+ which frees it after all screens (or "screens") are closed.
+ */