From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / xlockmore.h
index 1b19041dcc30a65c77ed3721fd59e19128864fb5..fe09961481869246ad0aea95c34c5233580d76c2 100644 (file)
@@ -1,5 +1,5 @@
 /* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules.
- * xscreensaver, Copyright (c) 1997, 1998, 2001 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1997-2012 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
  * to redo it, since xlockmore has diverged so far from xlock...)
  */
 
-#if !defined(PROGCLASS) || !defined(HACK_INIT) || !defined(HACK_DRAW)
-ERROR!  Define PROGCLASS, HACK_INIT, and HACK_DRAW before including xlockmore.h
-#endif
-
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif /* HAVE_CONFIG_H */
 
 #ifndef __STDC__
 ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
@@ -28,26 +26,18 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
      and cpp-based stringification of tokens.) */
 #endif
 
-#include <stdio.h>
-#include <math.h>
+#include "screenhackI.h"
 #include "xlockmoreI.h"
 
-#ifdef USE_GL
-# include <GL/glx.h>
-  extern GLXContext *init_GL (ModeInfo *);
-  extern void clear_gl_error (void);
-  extern void check_gl_error (const char *type);
-  extern void do_fps (ModeInfo *);
-# define FreeAllGL(dpy) /* */
-#endif /* !USE_GL */
+# define ENTRYPOINT static
 
 /* Accessor macros for the ModeInfo structure
  */
-
 #define MI_DISPLAY(MI)         ((MI)->dpy)
 #define MI_WINDOW(MI)          ((MI)->window)
-#define MI_NUM_SCREENS(MI)     (1)     /* Only manage one screen at a time; */
-#define MI_SCREEN(MI)          (0)     /*  this might be fragile... */
+#define MI_NUM_SCREENS(MI)     XLOCKMORE_NUM_SCREENS
+#define MI_SCREEN(MI)          ((MI)->screen_number)
+#define MI_SCREENPTR(MI)       ((MI)->xgwa.screen)
 #define MI_WIN_WHITE_PIXEL(MI) ((MI)->white)
 #define MI_WIN_BLACK_PIXEL(MI) ((MI)->black)
 #define MI_NPIXELS(MI)         ((MI)->npixels)
@@ -55,10 +45,12 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
 #define MI_WIN_WIDTH(MI)       ((MI)->xgwa.width)
 #define MI_WIN_HEIGHT(MI)      ((MI)->xgwa.height)
 #define MI_WIN_DEPTH(MI)       ((MI)->xgwa.depth)
+#define MI_DEPTH(MI)           ((MI)->xgwa.depth)
 #define MI_WIN_COLORMAP(MI)    ((MI)->xgwa.colormap)
 #define MI_VISUAL(MI)          ((MI)->xgwa.visual)
 #define MI_GC(MI)              ((MI)->gc)
 #define MI_PAUSE(MI)           ((MI)->pause)
+#define MI_DELAY(MI)           ((MI)->pause)
 #define MI_WIN_IS_FULLRANDOM(MI)((MI)->fullrandom)
 #define MI_WIN_IS_VERBOSE(MI)   (False)
 #define MI_WIN_IS_INSTALL(MI)   (True)
@@ -77,10 +69,11 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
 #define MI_BATCHCOUNT(MI)      ((MI)->batchcount)
 #define MI_SIZE(MI)            ((MI)->size)
 #define MI_IS_DRAWN(MI)                ((MI)->is_drawn)
-#define MI_IS_DRAWN(MI)                ((MI)->is_drawn)
+#define MI_IS_FPS(MI)          ((MI)->fps_p)
 #define MI_NCOLORS(MI)         ((MI)->npixels)
 #define MI_NAME(MI)            (progname)
 
+#define MI_COLORMAP(MI)                (MI_WIN_COLORMAP((MI)))
 #define MI_WIDTH(MI)           (MI_WIN_WIDTH((MI)))
 #define MI_HEIGHT(MI)          (MI_WIN_HEIGHT((MI)))
 #define MI_IS_ICONIC(MI)       (MI_WIN_IS_ICONIC((MI)))
@@ -97,6 +90,45 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
 
 #define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi))
 
+/* 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));
+
+   It also enables hack_free_state to run when a screen is no longer in use.
+   This is called at some point after the last call to draw_##, but before
+   release_##.
+ */
+
+#define MI_INIT(mi, state_array, hack_free_state) \
+  xlockmore_mi_init ((mi), sizeof(*(state_array)), (void **)&(state_array), \
+                     hack_free_state)
+
+/* Use MI_ABORT if an init_## or draw_## hook needs to shut everything down.
+   This replaces explicit calls to release_## hooks when things go wrong from
+   inside an xlockmore API screenhack.
+
+   At some point this may do something other than just abort().
+ */
+#define MI_ABORT(mi)           abort();
+
+#define FreeAllGL(dpy)         /* */
+
 /* Some other utility macros.
  */
 #define SINF(n)                        ((float)sin((double)(n)))
@@ -113,68 +145,92 @@ ERROR!  Sorry, xlockmore.h requires ANSI C (gcc, for example.)
 /* Maximum possible number of colors (*not* default number of colors.) */
 #define NUMCOLORS 256
 
-/* The globals that screenhack.c expects (initialized by xlockmore.c).
- */
-char *defaults[100];
-XrmOptionDescRec options[100];
 
-/* Prototypes for the actual drawing routines...
- */
-extern void HACK_INIT(ModeInfo *);
-extern void HACK_DRAW(ModeInfo *);
-
-#ifdef HACK_FREE
-  extern void HACK_FREE(ModeInfo *);
-#else
-# define HACK_FREE 0
-#endif
+/* In an Xlib world, we define two global symbols here:
+   a struct in `MODULENAME_xscreensaver_function_table',
+   and a pointer to that in `xscreensaver_function_table'.
 
-#ifdef HACK_RESHAPE
-  extern void HACK_RESHAPE(ModeInfo *, int width, int height);
+   In a Cocoa or Android world, we only define the prefixed symbol;
+   the un-prefixed symbol does not exist.
+ */
+#ifdef HAVE_MOBILE
+# define XSCREENSAVER_LINK(NAME)
 #else
-# define HACK_RESHAPE 0
+# define XSCREENSAVER_LINK(NAME) \
+   struct xscreensaver_function_table *xscreensaver_function_table = &NAME;
 #endif
 
 
-/* Emit code for the entrypoint used by screenhack.c, and pass control
-   down into xlockmore.c with the appropriate parameters.
- */
-
-char *progclass = PROGCLASS;
+# if !defined(USE_GL) || defined(HAVE_COCOA) || defined(HAVE_ANDROID)
+#  define xlockmore_pick_gl_visual 0
+#  define xlockmore_validate_gl_visual 0
+# endif  /* !USE_GL || HAVE_COCOA || HAVE_ANDROID */
 
-void screenhack (Display *dpy, Window window)
-{
-  xlockmore_screenhack (dpy, window,
+# ifdef USE_GL
+#  define XLOCKMORE_FPS xlockmore_gl_compute_fps
+# else
+#  define XLOCKMORE_FPS xlockmore_do_fps
+# endif
 
 #ifdef WRITABLE_COLORS
-                       True,
+# undef WRITABLE_COLORS
+# define WRITABLE_COLORS 1
 #else
-                       False,
+# define WRITABLE_COLORS 0
 #endif
 
-#ifdef UNIFORM_COLORS
-                       True,
+#if defined(UNIFORM_COLORS)
+# define XLOCKMORE_COLOR_SCHEME color_scheme_uniform
+#elif defined(SMOOTH_COLORS)
+# define XLOCKMORE_COLOR_SCHEME color_scheme_smooth
+#elif defined(BRIGHT_COLORS)
+# define XLOCKMORE_COLOR_SCHEME color_scheme_bright
 #else
-                       False,
+# define XLOCKMORE_COLOR_SCHEME color_scheme_default
 #endif
 
-#ifdef SMOOTH_COLORS
-                       True,
-#else
-                       False,
-#endif
-
-#ifdef BRIGHT_COLORS
-                       True,
-#else
-                       False,
-#endif
+/* This is the macro that links this program in with the rest of
+   xscreensaver.  For example:
 
-                       HACK_INIT,
-                       HACK_DRAW,
-                       HACK_RESHAPE,
-                       HACK_FREE);
-}
+     XSCREENSAVER_MODULE   ("Atlantis", atlantis)
+     XSCREENSAVER_MODULE_2 ("GLMatrix", glmatrix, matrix)
 
+   CLASS:   a string, the class name for resources.
+   NAME:    a token, the name of the executable.  Should be the same
+            as CLASS, but downcased.
+   PREFIX:  the symbol used in the function names, e.g., `draw_atlantis'.
 
-const char *app_defaults = DEFAULTS ;
+   NAME and PREFIX are usually the same.  If they are not, use
+   XSCREENSAVER_MODULE_2() instead of XSCREENSAVER_MODULE().
+ */
+#define XSCREENSAVER_MODULE_2(CLASS,NAME,PREFIX)                       \
+                                                                       \
+  static struct xlockmore_function_table                               \
+        NAME ## _xlockmore_function_table = {                  \
+          CLASS,                                                       \
+          DEFAULTS,                                                    \
+          WRITABLE_COLORS,                                             \
+          XLOCKMORE_COLOR_SCHEME,                                      \
+          init_    ## PREFIX,                                          \
+          draw_    ## PREFIX,                                          \
+          reshape_ ## PREFIX,                                          \
+          refresh_ ## PREFIX,                                          \
+          release_ ## PREFIX,                                          \
+          PREFIX   ## _handle_event,                                   \
+          & PREFIX ## _opts                                            \
+  };                                                                   \
+                                                                       \
+  struct xscreensaver_function_table                                   \
+        NAME ## _xscreensaver_function_table = {                       \
+          0, 0, 0,                                                     \
+          xlockmore_setup,                                             \
+          & NAME ## _xlockmore_function_table,                         \
+          0, 0, 0, 0, 0,                                               \
+           XLOCKMORE_FPS,                                              \
+           xlockmore_pick_gl_visual,                                   \
+          xlockmore_validate_gl_visual };                              \
+                                                                       \
+  XSCREENSAVER_LINK (NAME ## _xscreensaver_function_table)
+
+#define XSCREENSAVER_MODULE(CLASS,PREFIX)                              \
+      XSCREENSAVER_MODULE_2(CLASS,PREFIX,PREFIX)