1 /* xlockmore.c --- xscreensaver compatibility layer for xlockmore modules.
2 * xscreensaver, Copyright (c) 1997, 1998, 2001 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
12 * This file, along with xlockmore.h, make it possible to compile an xlockmore
13 * module into a standalone program, and thus use it with xscreensaver.
14 * By Jamie Zawinski <jwz@jwz.org> on 10-May-97; based on the ideas
15 * in the older xlock.h by Charles Hannum <mycroft@ai.mit.edu>. (I had
16 * to redo it, since xlockmore has diverged so far from xlock...)
24 #include "screenhack.h"
25 #include "xlockmoreI.h"
27 #define countof(x) (sizeof((x))/sizeof(*(x)))
29 #define MAX_COLORS (1L<<13)
31 extern ModeSpecOpt xlockmore_opts[];
32 extern const char *app_defaults;
35 pre_merge_options (void)
40 /* Translate the xlockmore `opts[]' argument to a form that
43 for (i = 0; i < xlockmore_opts->numopts; i++)
45 XrmOptionDescRec *old = &xlockmore_opts->opts[i];
46 XrmOptionDescRec *new = &options[i];
48 if (old->option[0] == '-')
49 new->option = old->option;
52 /* Convert "+foo" to "-no-foo". */
53 new->option = (char *) malloc (strlen(old->option) + 5);
54 strcpy (new->option, "-no-");
55 strcat (new->option, old->option + 1);
58 new->specifier = strrchr (old->specifier, '.');
59 if (!new->specifier) abort();
61 new->argKind = old->argKind;
62 new->value = old->value;
65 /* Add extra args, if they're mentioned in the defaults... */
67 char *args[] = { "-count", "-cycles", "-delay", "-ncolors",
68 "-size", "-wireframe", "-use3d", "-useSHM",
70 for (j = 0; j < countof(args); j++)
71 if (strstr(app_defaults, args[j]+1))
73 XrmOptionDescRec *new = &options[i++];
74 new->option = args[j];
75 new->specifier = strdup(args[j]);
76 new->specifier[0] = '.';
77 if (!strcmp(new->option, "-wireframe"))
79 new->argKind = XrmoptionNoArg;
82 new->option = "-no-wireframe";
83 new->specifier = options[i-2].specifier;
84 new->argKind = XrmoptionNoArg;
87 else if (!strcmp(new->option, "-use3d"))
90 new->argKind = XrmoptionNoArg;
93 new->option = "-no-3d";
94 new->specifier = options[i-2].specifier;
95 new->argKind = XrmoptionNoArg;
98 else if (!strcmp(new->option, "-useSHM"))
100 new->option = "-shm";
101 new->argKind = XrmoptionNoArg;
104 new->option = "-no-shm";
105 new->specifier = options[i-2].specifier;
106 new->argKind = XrmoptionNoArg;
107 new->value = "False";
109 else if (!strcmp(new->option, "-showFPS"))
111 new->option = "-fps";
112 new->argKind = XrmoptionNoArg;
115 new->option = "-no-fps";
116 new->specifier = options[i-2].specifier;
117 new->argKind = XrmoptionNoArg;
118 new->value = "False";
122 new->argKind = XrmoptionSepArg;
129 /* Construct the kind of `defaults' that screenhack.c expects from
130 the xlockmore `vars[]' argument.
134 /* Put on the PROGCLASS.background/foreground resources. */
135 s = (char *) malloc(50);
136 strcpy (s, progclass);
137 strcat (s, ".background: black");
140 s = (char *) malloc(50);
141 strcpy (s, progclass);
142 strcat (s, ".foreground: white");
145 /* Copy the lines out of the `app_defaults' var and into this array. */
146 s = strdup (app_defaults);
155 /* Copy the defaults out of the `xlockmore_opts->' variable. */
156 for (j = 0; j < xlockmore_opts->numvarsdesc; j++)
158 const char *def = xlockmore_opts->vars[j].def;
162 if (strlen(def) > 1000) abort();
164 s = (char *) malloc (strlen (xlockmore_opts->vars[j].name) +
167 strcat (s, xlockmore_opts->vars[j].name);
178 xlockmore_read_resources (void)
181 for (i = 0; i < xlockmore_opts->numvarsdesc; i++)
183 void *var = xlockmore_opts->vars[i].var;
184 Bool *var_b = (Bool *) var;
185 char **var_c = (char **) var;
186 int *var_i = (int *) var;
187 float *var_f = (float *) var;
189 switch (xlockmore_opts->vars[i].type)
192 *var_c = get_string_resource (xlockmore_opts->vars[i].name,
193 xlockmore_opts->vars[i].classname);
196 *var_f = get_float_resource (xlockmore_opts->vars[i].name,
197 xlockmore_opts->vars[i].classname);
200 *var_i = get_integer_resource (xlockmore_opts->vars[i].name,
201 xlockmore_opts->vars[i].classname);
204 *var_b = get_boolean_resource (xlockmore_opts->vars[i].name,
205 xlockmore_opts->vars[i].classname);
215 xlockmore_handle_events (ModeInfo *mi,
216 void (*reshape) (ModeInfo *, int, int))
218 while (XPending (mi->dpy))
221 XNextEvent (mi->dpy, &event);
222 if (reshape && event.xany.type == ConfigureNotify)
224 XGetWindowAttributes (mi->dpy, mi->window, &mi->xgwa);
225 reshape (mi, mi->xgwa.width, mi->xgwa.height);
229 screenhack_handle_event (mi->dpy, &event);
236 xlockmore_screenhack (Display *dpy, Window window,
237 Bool want_writable_colors,
238 Bool want_uniform_colors,
239 Bool want_smooth_colors,
240 Bool want_bright_colors,
241 void (*hack_init) (ModeInfo *),
242 void (*hack_draw) (ModeInfo *),
243 void (*hack_reshape) (ModeInfo *, int, int),
244 void (*hack_free) (ModeInfo *))
253 memset(&mi, 0, sizeof(mi));
256 XGetWindowAttributes (dpy, window, &mi.xgwa);
258 color.flags = DoRed|DoGreen|DoBlue;
259 color.red = color.green = color.blue = 0;
260 if (!XAllocColor(dpy, mi.xgwa.colormap, &color))
262 mi.black = color.pixel;
263 color.red = color.green = color.blue = 0xFFFF;
264 if (!XAllocColor(dpy, mi.xgwa.colormap, &color))
266 mi.white = color.pixel;
270 static unsigned long pixels[2];
271 static XColor colors[2];
276 pixels[0] = mi.black;
277 pixels[1] = mi.white;
278 colors[0].flags = DoRed|DoGreen|DoBlue;
279 colors[1].flags = DoRed|DoGreen|DoBlue;
280 colors[0].red = colors[0].green = colors[0].blue = 0;
281 colors[1].red = colors[1].green = colors[1].blue = 0xFFFF;
282 mi.writable_p = False;
286 mi.npixels = get_integer_resource ("ncolors", "Integer");
289 else if (mi.npixels > MAX_COLORS)
290 mi.npixels = MAX_COLORS;
292 mi.colors = (XColor *) calloc (mi.npixels, sizeof (*mi.colors));
294 mi.writable_p = want_writable_colors;
296 if (want_uniform_colors)
297 make_uniform_colormap (dpy, mi.xgwa.visual, mi.xgwa.colormap,
298 mi.colors, &mi.npixels,
299 True, &mi.writable_p, True);
300 else if (want_smooth_colors)
301 make_smooth_colormap (dpy, mi.xgwa.visual, mi.xgwa.colormap,
302 mi.colors, &mi.npixels,
303 True, &mi.writable_p, True);
305 make_random_colormap (dpy, mi.xgwa.visual, mi.xgwa.colormap,
306 mi.colors, &mi.npixels,
308 True, &mi.writable_p, True);
315 mi.pixels = (unsigned long *)
316 calloc (mi.npixels, sizeof (*mi.pixels));
317 for (i = 0; i < mi.npixels; i++)
318 mi.pixels[i] = mi.colors[i].pixel;
322 gcv.foreground = mi.white;
323 gcv.background = mi.black;
324 mi.gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
326 mi.fullrandom = True;
328 mi.pause = get_integer_resource ("delay", "Usecs");
330 mi.cycles = get_integer_resource ("cycles", "Int");
331 mi.batchcount = get_integer_resource ("count", "Int");
332 mi.size = get_integer_resource ("size", "Int");
334 mi.threed = get_boolean_resource ("use3d", "Boolean");
335 mi.threed_delta = get_float_resource ("delta3d", "Boolean");
336 mi.threed_right_color = get_pixel_resource ("right3d", "Color", dpy,
338 mi.threed_left_color = get_pixel_resource ("left3d", "Color", dpy,
340 mi.threed_both_color = get_pixel_resource ("both3d", "Color", dpy,
342 mi.threed_none_color = get_pixel_resource ("none3d", "Color", dpy,
345 mi.wireframe_p = get_boolean_resource ("wireframe", "Boolean");
346 mi.root_p = (window == RootWindowOfScreen (mi.xgwa.screen));
347 mi.fps_p = get_boolean_resource ("showFPS", "Boolean");
348 #ifdef HAVE_XSHM_EXTENSION
349 mi.use_shm = get_boolean_resource ("useSHM", "Boolean");
350 #endif /* !HAVE_XSHM_EXTENSION */
354 else if (mi.pause > 100000000)
355 mi.pause = 100000000;
356 orig_pause = mi.pause;
358 xlockmore_read_resources ();
360 XClearWindow (dpy, window);
363 start = time((time_t) 0);
369 xlockmore_handle_events (&mi, hack_reshape);
372 mi.pause = orig_pause;
376 if (i++ > (mi.batchcount / 4) &&
377 (start + 5) < (now = time((time_t) 0)))