ftp://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/redhat/linux/enterprise/4/en/os...
[xscreensaver] / hacks / xlockmore.c
index f84f4919a6c3448734bea58c60348d5629bd430f..7624b4875c904a16b5c97a1ac554365f9959f9d4 100644 (file)
@@ -1,5 +1,6 @@
 /* xlockmore.c --- xscreensaver compatibility layer for xlockmore modules.
- * xscreensaver, Copyright (c) 1997, 1998 Jamie Zawinski <jwz@netscape.com>
+ * xscreensaver, Copyright (c) 1997, 1998, 2001, 2002, 2004
+ *  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
@@ -11,7 +12,7 @@
  *
  * This file, along with xlockmore.h, make it possible to compile an xlockmore
  * module into a standalone program, and thus use it with xscreensaver.
- * By Jamie Zawinski <jwz@netscape.com> on 10-May-97; based on the ideas
+ * By Jamie Zawinski <jwz@jwz.org> on 10-May-97; based on the ideas
  * in the older xlock.h by Charles Hannum <mycroft@ai.mit.edu>.  (I had
  * to redo it, since xlockmore has diverged so far from xlock...)
  */
 #include <stdio.h>
 #include <math.h>
 #include <string.h>
+#include <time.h>
+#include <sys/time.h>
 #include "screenhack.h"
 #include "xlockmoreI.h"
+#include <X11/Intrinsic.h>
 
 #define countof(x) (sizeof((x))/sizeof(*(x)))
 
+#define MAX_COLORS (1L<<13)
+
+extern XtAppContext app;
 extern ModeSpecOpt xlockmore_opts[];
 extern const char *app_defaults;
 
@@ -61,7 +68,8 @@ pre_merge_options (void)
   /* Add extra args, if they're mentioned in the defaults... */
   {
     char *args[] = { "-count", "-cycles", "-delay", "-ncolors",
-                    "-size", "-wireframe", "-use3d" };
+                    "-size", "-wireframe", "-use3d", "-useSHM",
+                     "-showFPS" };
     for (j = 0; j < countof(args); j++)
       if (strstr(app_defaults, args[j]+1))
        {
@@ -90,6 +98,28 @@ pre_merge_options (void)
              new->argKind = XrmoptionNoArg;
              new->value = "False";
            }
+         else if (!strcmp(new->option, "-useSHM"))
+           {
+             new->option = "-shm";
+             new->argKind = XrmoptionNoArg;
+             new->value = "True";
+             new = &options[i++];
+             new->option = "-no-shm";
+             new->specifier = options[i-2].specifier;
+             new->argKind = XrmoptionNoArg;
+             new->value = "False";
+           }
+         else if (!strcmp(new->option, "-showFPS"))
+           {
+             new->option = "-fps";
+             new->argKind = XrmoptionNoArg;
+             new->value = "True";
+             new = &options[i++];
+             new->option = "-no-fps";
+             new->specifier = options[i-2].specifier;
+             new->argKind = XrmoptionNoArg;
+             new->value = "False";
+           }
          else
            {
              new->argKind = XrmoptionSepArg;
@@ -129,8 +159,11 @@ pre_merge_options (void)
   for (j = 0; j < xlockmore_opts->numvarsdesc; j++)
     {
       const char *def = xlockmore_opts->vars[j].def;
-      if (!def) def = "False";
-      if (def == ((char*) 1)) def = "True";
+
+      if (!def) abort();
+      if (!*def) abort();
+      if (strlen(def) > 1000) abort();
+
       s = (char *) malloc (strlen (xlockmore_opts->vars[j].name) +
                           strlen (def) + 10);
       strcpy (s, "*");
@@ -181,6 +214,33 @@ xlockmore_read_resources (void)
 }
 
 
+static void
+xlockmore_handle_events (ModeInfo *mi, 
+                         void (*reshape) (ModeInfo *, int, int),
+                         Bool (*hook) (ModeInfo *, XEvent *))
+{
+  if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput))
+    XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput);
+
+  while (XPending (mi->dpy))
+    {
+      XEvent event;
+      XNextEvent (mi->dpy, &event);
+      if (reshape && event.xany.type == ConfigureNotify)
+        {
+          XGetWindowAttributes (mi->dpy, mi->window, &mi->xgwa);
+          reshape (mi, mi->xgwa.width, mi->xgwa.height);
+        }
+      else if (hook && hook (mi, &event))
+        {
+        }
+      else
+        {
+          screenhack_handle_event (mi->dpy, &event);
+        }
+    }
+}
+
 
 void 
 xlockmore_screenhack (Display *dpy, Window window,
@@ -188,8 +248,11 @@ xlockmore_screenhack (Display *dpy, Window window,
                      Bool want_uniform_colors,
                      Bool want_smooth_colors,
                      Bool want_bright_colors,
+                      unsigned long event_mask,
                      void (*hack_init) (ModeInfo *),
                      void (*hack_draw) (ModeInfo *),
+                     void (*hack_reshape) (ModeInfo *, int, int),
+                     Bool (*hack_handle_events) (ModeInfo *, XEvent *),
                      void (*hack_free) (ModeInfo *))
 {
   ModeInfo mi;
@@ -198,11 +261,22 @@ xlockmore_screenhack (Display *dpy, Window window,
   int i;
   time_t start, now;
   int orig_pause;
+  Bool root_p;
 
   memset(&mi, 0, sizeof(mi));
   mi.dpy = dpy;
   mi.window = window;
   XGetWindowAttributes (dpy, window, &mi.xgwa);
+  root_p = (window == RootWindowOfScreen (mi.xgwa.screen));
+
+  /* If this is the root window, don't allow ButtonPress to be selected.
+     Bad Things Happen. */
+  if (root_p)
+    event_mask &= (~(ButtonPressMask|ButtonReleaseMask));
+
+  /* If this hack wants additional events, select them. */
+  if (event_mask && ! (mi.xgwa.your_event_mask & event_mask))
+    XSelectInput (dpy, window, (mi.xgwa.your_event_mask | event_mask));
 
   color.flags = DoRed|DoGreen|DoBlue;
   color.red = color.green = color.blue = 0;
@@ -235,8 +309,8 @@ xlockmore_screenhack (Display *dpy, Window window,
       mi.npixels = get_integer_resource ("ncolors", "Integer");
       if (mi.npixels <= 0)
        mi.npixels = 64;
-      else if (mi.npixels > 256)
-       mi.npixels = 256;
+      else if (mi.npixels > MAX_COLORS)
+       mi.npixels = MAX_COLORS;
 
       mi.colors = (XColor *) calloc (mi.npixels, sizeof (*mi.colors));
 
@@ -260,7 +334,6 @@ xlockmore_screenhack (Display *dpy, Window window,
        goto MONO;
       else
        {
-         int i;
          mi.pixels = (unsigned long *)
            calloc (mi.npixels, sizeof (*mi.pixels));
          for (i = 0; i < mi.npixels; i++)
@@ -280,29 +353,6 @@ xlockmore_screenhack (Display *dpy, Window window,
   mi.batchcount = get_integer_resource ("count", "Int");
   mi.size      = get_integer_resource ("size", "Int");
 
-#if 0
-  decay = get_boolean_resource ("decay", "Boolean");
-  if (decay) mi.fullrandom = False;
-
-  trail = get_boolean_resource ("trail", "Boolean");
-  if (trail) mi.fullrandom = False;
-
-  grow = get_boolean_resource ("grow", "Boolean");
-  if (grow) mi.fullrandom = False;
-
-  liss = get_boolean_resource ("liss", "Boolean");
-  if (liss) mi.fullrandom = False;
-
-  ammann = get_boolean_resource ("ammann", "Boolean");
-  if (ammann) mi.fullrandom = False;
-
-  jong = get_boolean_resource ("jong", "Boolean");
-  if (jong) mi.fullrandom = False;
-
-  sine = get_boolean_resource ("sine", "Boolean");
-  if (sine) mi.fullrandom = False;
-#endif
-
   mi.threed = get_boolean_resource ("use3d", "Boolean");
   mi.threed_delta = get_float_resource ("delta3d", "Boolean");
   mi.threed_right_color = get_pixel_resource ("right3d", "Color", dpy,
@@ -315,8 +365,11 @@ xlockmore_screenhack (Display *dpy, Window window,
                                             mi.xgwa.colormap);
 
   mi.wireframe_p = get_boolean_resource ("wireframe", "Boolean");
-  mi.root_p = (window == RootWindowOfScreen (mi.xgwa.screen));
-
+  mi.root_p = root_p;
+  mi.fps_p = get_boolean_resource ("showFPS", "Boolean");
+#ifdef HAVE_XSHM_EXTENSION
+  mi.use_shm = get_boolean_resource ("useSHM", "Boolean");
+#endif /* !HAVE_XSHM_EXTENSION */
 
   if (mi.pause < 0)
     mi.pause = 0;
@@ -335,6 +388,7 @@ xlockmore_screenhack (Display *dpy, Window window,
   do {
     hack_draw (&mi);
     XSync(dpy, False);
+    xlockmore_handle_events (&mi, hack_reshape, hack_handle_events);
     if (mi.pause)
       usleep(mi.pause);
     mi.pause = orig_pause;