X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fxlockmore.h;h=6b604c5f8219277d2debdd13fc888236281229d0;hb=39809ded547bdbb08207d3e514950425215b4410;hp=9ad4e98e34bd5aaedddb5c3b2ba40853ee8ab3ff;hpb=df053bcb240bd8d82e3bebf48a9766a8728bca4b;p=xscreensaver diff --git a/hacks/xlockmore.h b/hacks/xlockmore.h index 9ad4e98e..6b604c5f 100644 --- a/hacks/xlockmore.h +++ b/hacks/xlockmore.h @@ -1,5 +1,5 @@ /* xlockmore.h --- xscreensaver compatibility layer for xlockmore modules. - * xscreensaver, Copyright (c) 1997, 1998 Jamie Zawinski + * xscreensaver, Copyright (c) 1997-2017 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -11,16 +11,14 @@ * * The definitions in this file make it possible to compile an xlockmore * module into a standalone program, and thus use it with xscreensaver. - * By Jamie Zawinski on 10-May-97; based on the ideas + * By Jamie Zawinski on 10-May-97; based on the ideas * in the older xlock.h by Charles Hannum . (I had * 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,23 +26,18 @@ ERROR! Sorry, xlockmore.h requires ANSI C (gcc, for example.) and cpp-based stringification of tokens.) */ #endif -#include -#include +#include "screenhackI.h" #include "xlockmoreI.h" -#ifdef USE_GL -# include - extern GLXContext *init_GL (ModeInfo *); -# define FreeAllGL(dpy) /* */ -#endif +# 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) @@ -52,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) @@ -73,7 +68,12 @@ ERROR! Sorry, xlockmore.h requires ANSI C (gcc, for example.) #define MI_CYCLES(MI) ((MI)->cycles) #define MI_BATCHCOUNT(MI) ((MI)->batchcount) #define MI_SIZE(MI) ((MI)->size) +#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))) @@ -82,8 +82,61 @@ ERROR! Sorry, xlockmore.h requires ANSI C (gcc, for example.) #define MI_COUNT(MI) (MI_BATCHCOUNT((MI))) #define MI_BLACK_PIXEL(MI) (MI_WIN_BLACK_PIXEL(MI)) #define MI_WHITE_PIXEL(MI) (MI_WIN_WHITE_PIXEL(MI)) +#define MI_IS_FULLRANDOM(MI) (MI_WIN_IS_FULLRANDOM(MI)) +#define MI_IS_VERBOSE(MI) (MI_WIN_IS_VERBOSE(MI)) +#define MI_IS_INSTALL(MI) (MI_WIN_IS_INSTALL(MI)) +#define MI_IS_DEBUG(MI) (False) +#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. + */ + +#define MI_INIT(mi, state_array) \ + xlockmore_mi_init ((mi), sizeof(*(state_array)), (void **)&(state_array)) -#define MI_CLEARWINDOW(mi) XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi)) +/* 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. */ @@ -101,61 +154,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 *); +/* 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_FREE - extern void HACK_FREE(ModeInfo *); + 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_FREE 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 +/* This is the macro that links this program in with the rest of + xscreensaver. For example: -#ifdef BRIGHT_COLORS - True, -#else - False, -#endif - - HACK_INIT, - HACK_DRAW, - 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, \ + release_ ## PREFIX, \ + free_ ## 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)