source: trunk/third/xscreensaver/hacks/xlockmore.c @ 20148

Revision 20148, 11.0 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* xlockmore.c --- xscreensaver compatibility layer for xlockmore modules.
2 * xscreensaver, Copyright (c) 1997, 1998, 2001, 2002
3 *  Jamie Zawinski <jwz@jwz.org>
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation.  No representations are made about the suitability of this
10 * software for any purpose.  It is provided "as is" without express or
11 * implied warranty.
12 *
13 * This file, along with xlockmore.h, make it possible to compile an xlockmore
14 * module into a standalone program, and thus use it with xscreensaver.
15 * By Jamie Zawinski <jwz@jwz.org> on 10-May-97; based on the ideas
16 * in the older xlock.h by Charles Hannum <mycroft@ai.mit.edu>.  (I had
17 * to redo it, since xlockmore has diverged so far from xlock...)
18 */
19
20#include <stdio.h>
21#include <math.h>
22#include <string.h>
23#include <time.h>
24#include <sys/time.h>
25#include "screenhack.h"
26#include "xlockmoreI.h"
27
28#define countof(x) (sizeof((x))/sizeof(*(x)))
29
30#define MAX_COLORS (1L<<13)
31
32extern ModeSpecOpt xlockmore_opts[];
33extern const char *app_defaults;
34
35void
36pre_merge_options (void)
37{
38  int i, j;
39  char *s;
40
41  /* Translate the xlockmore `opts[]' argument to a form that
42     screenhack.c expects.
43   */
44  for (i = 0; i < xlockmore_opts->numopts; i++)
45    {
46      XrmOptionDescRec *old = &xlockmore_opts->opts[i];
47      XrmOptionDescRec *new = &options[i];
48
49      if (old->option[0] == '-')
50        new->option = old->option;
51      else
52        {
53          /* Convert "+foo" to "-no-foo". */
54          new->option = (char *) malloc (strlen(old->option) + 5);
55          strcpy (new->option, "-no-");
56          strcat (new->option, old->option + 1);
57        }
58
59      new->specifier = strrchr (old->specifier, '.');
60      if (!new->specifier) abort();
61
62      new->argKind = old->argKind;
63      new->value = old->value;
64    }
65
66  /* Add extra args, if they're mentioned in the defaults... */
67  {
68    char *args[] = { "-count", "-cycles", "-delay", "-ncolors",
69                     "-size", "-wireframe", "-use3d", "-useSHM",
70                     "-showFPS" };
71    for (j = 0; j < countof(args); j++)
72      if (strstr(app_defaults, args[j]+1))
73        {
74          XrmOptionDescRec *new = &options[i++];
75          new->option = args[j];
76          new->specifier = strdup(args[j]);
77          new->specifier[0] = '.';
78          if (!strcmp(new->option, "-wireframe"))
79            {
80              new->argKind = XrmoptionNoArg;
81              new->value = "True";
82              new = &options[i++];
83              new->option = "-no-wireframe";
84              new->specifier = options[i-2].specifier;
85              new->argKind = XrmoptionNoArg;
86              new->value = "False";
87            }
88          else if (!strcmp(new->option, "-use3d"))
89            {
90              new->option = "-3d";
91              new->argKind = XrmoptionNoArg;
92              new->value = "True";
93              new = &options[i++];
94              new->option = "-no-3d";
95              new->specifier = options[i-2].specifier;
96              new->argKind = XrmoptionNoArg;
97              new->value = "False";
98            }
99          else if (!strcmp(new->option, "-useSHM"))
100            {
101              new->option = "-shm";
102              new->argKind = XrmoptionNoArg;
103              new->value = "True";
104              new = &options[i++];
105              new->option = "-no-shm";
106              new->specifier = options[i-2].specifier;
107              new->argKind = XrmoptionNoArg;
108              new->value = "False";
109            }
110          else if (!strcmp(new->option, "-showFPS"))
111            {
112              new->option = "-fps";
113              new->argKind = XrmoptionNoArg;
114              new->value = "True";
115              new = &options[i++];
116              new->option = "-no-fps";
117              new->specifier = options[i-2].specifier;
118              new->argKind = XrmoptionNoArg;
119              new->value = "False";
120            }
121          else
122            {
123              new->argKind = XrmoptionSepArg;
124              new->value = 0;
125            }
126        }
127  }
128
129
130  /* Construct the kind of `defaults' that screenhack.c expects from
131     the xlockmore `vars[]' argument.
132   */
133  i = 0;
134
135  /* Put on the PROGCLASS.background/foreground resources. */
136  s = (char *) malloc(50);
137  strcpy (s, progclass);
138  strcat (s, ".background: black");
139  defaults [i++] = s;
140
141  s = (char *) malloc(50);
142  strcpy (s, progclass);
143  strcat (s, ".foreground: white");
144  defaults [i++] = s;
145
146  /* Copy the lines out of the `app_defaults' var and into this array. */
147  s = strdup (app_defaults);
148  while (s && *s)
149    {
150      defaults [i++] = s;
151      s = strchr(s, '\n');
152      if (s)
153        *s++ = 0;
154    }
155
156  /* Copy the defaults out of the `xlockmore_opts->' variable. */
157  for (j = 0; j < xlockmore_opts->numvarsdesc; j++)
158    {
159      const char *def = xlockmore_opts->vars[j].def;
160
161      if (!def) abort();
162      if (!*def) abort();
163      if (strlen(def) > 1000) abort();
164
165      s = (char *) malloc (strlen (xlockmore_opts->vars[j].name) +
166                           strlen (def) + 10);
167      strcpy (s, "*");
168      strcat (s, xlockmore_opts->vars[j].name);
169      strcat (s, ": ");
170      strcat (s, def);
171      defaults [i++] = s;
172    }
173
174  defaults [i] = 0;
175}
176
177
178static void
179xlockmore_read_resources (void)
180{
181  int i;
182  for (i = 0; i < xlockmore_opts->numvarsdesc; i++)
183    {
184      void  *var   = xlockmore_opts->vars[i].var;
185      Bool  *var_b = (Bool *)  var;
186      char **var_c = (char **) var;
187      int   *var_i = (int *) var;
188      float *var_f = (float *) var;
189
190      switch (xlockmore_opts->vars[i].type)
191        {
192        case t_String:
193          *var_c = get_string_resource (xlockmore_opts->vars[i].name,
194                                        xlockmore_opts->vars[i].classname);
195          break;
196        case t_Float:
197          *var_f = get_float_resource (xlockmore_opts->vars[i].name,
198                                       xlockmore_opts->vars[i].classname);
199          break;
200        case t_Int:
201          *var_i = get_integer_resource (xlockmore_opts->vars[i].name,
202                                         xlockmore_opts->vars[i].classname);
203          break;
204        case t_Bool:
205          *var_b = get_boolean_resource (xlockmore_opts->vars[i].name,
206                                         xlockmore_opts->vars[i].classname);
207          break;
208        default:
209          abort ();
210        }
211    }
212}
213
214
215static void
216xlockmore_handle_events (ModeInfo *mi,
217                         void (*reshape) (ModeInfo *, int, int),
218                         Bool (*hook) (ModeInfo *, XEvent *))
219{
220  while (XPending (mi->dpy))
221    {
222      XEvent event;
223      XNextEvent (mi->dpy, &event);
224      if (reshape && event.xany.type == ConfigureNotify)
225        {
226          XGetWindowAttributes (mi->dpy, mi->window, &mi->xgwa);
227          reshape (mi, mi->xgwa.width, mi->xgwa.height);
228        }
229      else if (hook && hook (mi, &event))
230        {
231        }
232      else
233        {
234          screenhack_handle_event (mi->dpy, &event);
235        }
236    }
237}
238
239
240void
241xlockmore_screenhack (Display *dpy, Window window,
242                      Bool want_writable_colors,
243                      Bool want_uniform_colors,
244                      Bool want_smooth_colors,
245                      Bool want_bright_colors,
246                      unsigned long event_mask,
247                      void (*hack_init) (ModeInfo *),
248                      void (*hack_draw) (ModeInfo *),
249                      void (*hack_reshape) (ModeInfo *, int, int),
250                      Bool (*hack_handle_events) (ModeInfo *, XEvent *),
251                      void (*hack_free) (ModeInfo *))
252{
253  ModeInfo mi;
254  XGCValues gcv;
255  XColor color;
256  int i;
257  time_t start, now;
258  int orig_pause;
259  Bool root_p;
260
261  memset(&mi, 0, sizeof(mi));
262  mi.dpy = dpy;
263  mi.window = window;
264  XGetWindowAttributes (dpy, window, &mi.xgwa);
265  root_p = (window == RootWindowOfScreen (mi.xgwa.screen));
266
267  /* If this is the root window, don't allow ButtonPress to be selected.
268     Bad Things Happen. */
269  if (root_p)
270    event_mask &= (~(ButtonPressMask|ButtonReleaseMask));
271
272  /* If this hack wants additional events, select them. */
273  if (event_mask && ! (mi.xgwa.your_event_mask & event_mask))
274    XSelectInput (dpy, window, (mi.xgwa.your_event_mask | event_mask));
275
276  color.flags = DoRed|DoGreen|DoBlue;
277  color.red = color.green = color.blue = 0;
278  if (!XAllocColor(dpy, mi.xgwa.colormap, &color))
279    abort();
280  mi.black = color.pixel;
281  color.red = color.green = color.blue = 0xFFFF;
282  if (!XAllocColor(dpy, mi.xgwa.colormap, &color))
283    abort();
284  mi.white = color.pixel;
285
286  if (mono_p)
287    {
288      static unsigned long pixels[2];
289      static XColor colors[2];
290    MONO:
291      mi.npixels = 2;
292      mi.pixels = pixels;
293      mi.colors = colors;
294      pixels[0] = mi.black;
295      pixels[1] = mi.white;
296      colors[0].flags = DoRed|DoGreen|DoBlue;
297      colors[1].flags = DoRed|DoGreen|DoBlue;
298      colors[0].red = colors[0].green = colors[0].blue = 0;
299      colors[1].red = colors[1].green = colors[1].blue = 0xFFFF;
300      mi.writable_p = False;
301    }
302  else
303    {
304      mi.npixels = get_integer_resource ("ncolors", "Integer");
305      if (mi.npixels <= 0)
306        mi.npixels = 64;
307      else if (mi.npixels > MAX_COLORS)
308        mi.npixels = MAX_COLORS;
309
310      mi.colors = (XColor *) calloc (mi.npixels, sizeof (*mi.colors));
311
312      mi.writable_p = want_writable_colors;
313
314      if (want_uniform_colors)
315        make_uniform_colormap (dpy, mi.xgwa.visual, mi.xgwa.colormap,
316                               mi.colors, &mi.npixels,
317                               True, &mi.writable_p, True);
318      else if (want_smooth_colors)
319        make_smooth_colormap (dpy, mi.xgwa.visual, mi.xgwa.colormap,
320                              mi.colors, &mi.npixels,
321                              True, &mi.writable_p, True);
322      else
323        make_random_colormap (dpy, mi.xgwa.visual, mi.xgwa.colormap,
324                              mi.colors, &mi.npixels,
325                              want_bright_colors,
326                              True, &mi.writable_p, True);
327
328      if (mi.npixels <= 2)
329        goto MONO;
330      else
331        {
332          mi.pixels = (unsigned long *)
333            calloc (mi.npixels, sizeof (*mi.pixels));
334          for (i = 0; i < mi.npixels; i++)
335            mi.pixels[i] = mi.colors[i].pixel;
336        }
337    }
338
339  gcv.foreground = mi.white;
340  gcv.background = mi.black;
341  mi.gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
342
343  mi.fullrandom = True;
344
345  mi.pause      = get_integer_resource ("delay", "Usecs");
346
347  mi.cycles     = get_integer_resource ("cycles", "Int");
348  mi.batchcount = get_integer_resource ("count", "Int");
349  mi.size       = get_integer_resource ("size", "Int");
350
351  mi.threed = get_boolean_resource ("use3d", "Boolean");
352  mi.threed_delta = get_float_resource ("delta3d", "Boolean");
353  mi.threed_right_color = get_pixel_resource ("right3d", "Color", dpy,
354                                              mi.xgwa.colormap);
355  mi.threed_left_color = get_pixel_resource ("left3d", "Color", dpy,
356                                             mi.xgwa.colormap);
357  mi.threed_both_color = get_pixel_resource ("both3d", "Color", dpy,
358                                             mi.xgwa.colormap);
359  mi.threed_none_color = get_pixel_resource ("none3d", "Color", dpy,
360                                             mi.xgwa.colormap);
361
362  mi.wireframe_p = get_boolean_resource ("wireframe", "Boolean");
363  mi.root_p = root_p;
364  mi.fps_p = get_boolean_resource ("showFPS", "Boolean");
365#ifdef HAVE_XSHM_EXTENSION
366  mi.use_shm = get_boolean_resource ("useSHM", "Boolean");
367#endif /* !HAVE_XSHM_EXTENSION */
368
369  if (mi.pause < 0)
370    mi.pause = 0;
371  else if (mi.pause > 100000000)
372    mi.pause = 100000000;
373  orig_pause = mi.pause;
374
375  xlockmore_read_resources ();
376
377  XClearWindow (dpy, window);
378
379  i = 0;
380  start = time((time_t) 0);
381
382  hack_init (&mi);
383  do {
384    hack_draw (&mi);
385    XSync(dpy, False);
386    xlockmore_handle_events (&mi, hack_reshape, hack_handle_events);
387    if (mi.pause)
388      usleep(mi.pause);
389    mi.pause = orig_pause;
390
391    if (hack_free)
392      {
393        if (i++ > (mi.batchcount / 4) &&
394            (start + 5) < (now = time((time_t) 0)))
395          {
396            i = 0;
397            start = now;
398            hack_free (&mi);
399            hack_init (&mi);
400            XSync(dpy, False);
401          }
402      }
403
404  } while (1);
405}
Note: See TracBrowser for help on using the repository browser.