http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / decayscreen.c
index d4b95f1c1b1d300625bcf9fb1a1d99f9a2f73ca2..855d80a5e45dc819445d4219d838619fd7d18602 100644 (file)
@@ -1,5 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997, 2005 
- * Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2006 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
 
 #include "screenhack.h"
 
-static int sizex, sizey;
-static int delay;
-static GC gc;
-static int mode;
-static int iterations=100;
-
-#define SHUFFLE 0
-#define UP 1
-#define LEFT 2
-#define RIGHT 3
-#define DOWN 4
-#define UPLEFT 5
-#define DOWNLEFT 6
-#define UPRIGHT 7
-#define DOWNRIGHT 8
-#define IN 9
-#define OUT 10
-#define MELT 11
-#define STRETCH 12
-#define FUZZ 13
+struct state {
+  Display *dpy;
+  Window window;
 
-static void
-init_decay (Display *dpy, Window window)
+  int sizex, sizey;
+  int delay;
+  GC gc;
+  int mode;
+  int iterations;
+
+  int fuzz_toggle;
+  const int *current_bias;
+
+  async_load_state *img_loader;
+};
+
+
+#define SHUFFLE                0
+#define UP             1
+#define LEFT           2
+#define RIGHT          3
+#define DOWN           4
+#define UPLEFT         5
+#define DOWNLEFT       6
+#define UPRIGHT                7
+#define DOWNRIGHT      8
+#define IN             9
+#define OUT            10
+#define MELT           11
+#define STRETCH                12
+#define FUZZ           13
+
+static void *
+decayscreen_init (Display *dpy, Window window)
 {
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   XGCValues gcv;
   XWindowAttributes xgwa;
   long gcflags;
   unsigned long bg;
-
-  char *s = get_string_resource("mode", "Mode");
-  if      (s && !strcmp(s, "shuffle")) mode = SHUFFLE;
-  else if (s && !strcmp(s, "up")) mode = UP;
-  else if (s && !strcmp(s, "left")) mode = LEFT;
-  else if (s && !strcmp(s, "right")) mode = RIGHT;
-  else if (s && !strcmp(s, "down")) mode = DOWN;
-  else if (s && !strcmp(s, "upleft")) mode = UPLEFT;
-  else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT;
-  else if (s && !strcmp(s, "upright")) mode = UPRIGHT;
-  else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT;
-  else if (s && !strcmp(s, "in")) mode = IN;
-  else if (s && !strcmp(s, "out")) mode = OUT;
-  else if (s && !strcmp(s, "melt")) mode = MELT;
-  else if (s && !strcmp(s, "stretch")) mode = STRETCH;
-  else if (s && !strcmp(s, "fuzz")) mode = FUZZ;
+  char *s;
+
+  st->dpy = dpy;
+  st->window = window;
+
+  s = get_string_resource(st->dpy, "mode", "Mode");
+  if      (s && !strcmp(s, "shuffle")) st->mode = SHUFFLE;
+  else if (s && !strcmp(s, "up")) st->mode = UP;
+  else if (s && !strcmp(s, "left")) st->mode = LEFT;
+  else if (s && !strcmp(s, "right")) st->mode = RIGHT;
+  else if (s && !strcmp(s, "down")) st->mode = DOWN;
+  else if (s && !strcmp(s, "upleft")) st->mode = UPLEFT;
+  else if (s && !strcmp(s, "downleft")) st->mode = DOWNLEFT;
+  else if (s && !strcmp(s, "upright")) st->mode = UPRIGHT;
+  else if (s && !strcmp(s, "downright")) st->mode = DOWNRIGHT;
+  else if (s && !strcmp(s, "in")) st->mode = IN;
+  else if (s && !strcmp(s, "out")) st->mode = OUT;
+  else if (s && !strcmp(s, "melt")) st->mode = MELT;
+  else if (s && !strcmp(s, "stretch")) st->mode = STRETCH;
+  else if (s && !strcmp(s, "fuzz")) st->mode = FUZZ;
   else {
     if (s && *s && !!strcmp(s, "random"))
       fprintf(stderr, "%s: unknown mode %s\n", progname, s);
-    mode = random() % (FUZZ+1);
+    st->mode = random() % (FUZZ+1);
   }
 
-  delay = get_integer_resource ("delay", "Integer");
+  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
 
-  if (delay < 0) delay = 0;
+  if (st->delay < 0) st->delay = 0;
 
-  XGetWindowAttributes (dpy, window, &xgwa);
+  XGetWindowAttributes (st->dpy, st->window, &xgwa);
 
   gcv.function = GXcopy;
   gcv.subwindow_mode = IncludeInferiors;
+  bg = get_pixel_resource (st->dpy, xgwa.colormap, "background", "Background");
+  gcv.foreground = bg;
 
-  if (mode == MELT || mode == STRETCH) {
-    bg = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
-    gcv.foreground = bg;
-  }
-
-  gcflags = GCForeground |GCFunction;
-  if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
+  gcflags = GCForeground | GCFunction;
+  if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */
     gcflags |= GCSubwindowMode;
-  gc = XCreateGC (dpy, window, gcflags, &gcv);
+  st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
 
-  sizex = xgwa.width;
-  sizey = xgwa.height;
+  st->sizex = xgwa.width;
+  st->sizey = xgwa.height;
 
-  load_random_image (xgwa.screen, window, window, NULL, NULL);
-  
-  if (mode == MELT || mode == STRETCH) {
-    /* make sure screen eventually turns background color */
-    XDrawLine(dpy, window, gc, 0, 0, sizex, 0); 
+  if (st->mode == MELT || st->mode == STRETCH)
+    st->iterations = 1;    /* slow down for smoother melting */
 
-    /* slow down for smoother melting*/
-    iterations = 1;
-  }
+  st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+                                            st->window, 0, 0);
 
+  return st;
 }
 
 
 /*
  * perform one iteration of decay
  */
-static void
-decay1 (Display *dpy, Window window)
+static unsigned long
+decayscreen_draw (Display *dpy, Window window, void *closure)
 {
+    struct state *st = (struct state *) closure;
     int left, top, width, height, toleft, totop;
 
 #define L 101
 #define R 102
 #define U 103
 #define D 104
-    static int no_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
-    static int up_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
-    static int down_bias[]      = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
-    static int left_bias[]      = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
-    static int right_bias[]     = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
-
-    static int upleft_bias[]    = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
-    static int downleft_bias[]  = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
-    static int upright_bias[]   = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
-    static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
-    static int *bias;
-
-    switch (mode) {
-      case SHUFFLE:    bias = no_bias; break;
-      case UP:         bias = up_bias; break;
-      case LEFT:       bias = left_bias; break;
-      case RIGHT:      bias = right_bias; break;
-      case DOWN:       bias = down_bias; break;
-      case UPLEFT:     bias = upleft_bias; break;
-      case DOWNLEFT:   bias = downleft_bias; break;
-      case UPRIGHT:    bias = upright_bias; break;
-      case DOWNRIGHT:  bias = downright_bias; break;
-      case IN:         bias = no_bias; break;
-      case OUT:                bias = no_bias; break;
-      case MELT:       bias = no_bias; break;
-      case STRETCH:    bias = no_bias; break;
-      case FUZZ:       bias = no_bias; break;
+    static const int no_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
+    static const int up_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
+    static const int down_bias[]      = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
+    static const int left_bias[]      = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
+    static const int right_bias[]     = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
+
+    static const int upleft_bias[]    = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
+    static const int downleft_bias[]  = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
+    static const int upright_bias[]   = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
+    static const int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
+
+    if (st->img_loader)   /* still loading */
+      {
+        st->img_loader = load_image_async_simple (st->img_loader, 
+                                                  0, 0, 0, 0, 0);
+        if (! st->img_loader) {  /* just finished */
+          if (st->mode == MELT || st->mode == STRETCH)
+            /* make sure screen eventually turns background color */
+            XDrawLine (st->dpy, st->window, st->gc, 0, 0, st->sizex, 0); 
+        }
+      return st->delay;
+    }
+
+    switch (st->mode) {
+      case SHUFFLE:    st->current_bias = no_bias; break;
+      case UP:         st->current_bias = up_bias; break;
+      case LEFT:       st->current_bias = left_bias; break;
+      case RIGHT:      st->current_bias = right_bias; break;
+      case DOWN:       st->current_bias = down_bias; break;
+      case UPLEFT:     st->current_bias = upleft_bias; break;
+      case DOWNLEFT:   st->current_bias = downleft_bias; break;
+      case UPRIGHT:    st->current_bias = upright_bias; break;
+      case DOWNRIGHT:  st->current_bias = downright_bias; break;
+      case IN:         st->current_bias = no_bias; break;
+      case OUT:                st->current_bias = no_bias; break;
+      case MELT:       st->current_bias = no_bias; break;
+      case STRETCH:    st->current_bias = no_bias; break;
+      case FUZZ:       st->current_bias = no_bias; break;
      default: abort();
     }
 
 #define nrnd(x) (random() % (x))
 
-    if (mode == MELT || mode == STRETCH) {
-      left = nrnd(sizex/2);
-      top = nrnd(sizey);
-      width = nrnd( sizex/2 ) + sizex/2 - left;
-      height = nrnd(sizey - top);
+    if (st->mode == MELT || st->mode == STRETCH) {
+      left = nrnd(st->sizex/2);
+      top = nrnd(st->sizey);
+      width = nrnd( st->sizex/2 ) + st->sizex/2 - left;
+      height = nrnd(st->sizey - top);
       toleft = left;
       totop = top+1;
 
-    } else if (mode == FUZZ) {  /* By Vince Levey <vincel@vincel.org>;
+    } else if (st->mode == FUZZ) {  /* By Vince Levey <vincel@vincel.org>;
                                    inspired by the "melt" mode of the
                                    "scrhack" IrisGL program by Paul Haeberli
                                    circa 1991. */
-      static int toggle = 0;
-
-      left = nrnd(sizex - 1);
-      top  = nrnd(sizey - 1);
-      toggle = !toggle;
-      if (toggle)
+      left = nrnd(st->sizex - 1);
+      top  = nrnd(st->sizey - 1);
+      st->fuzz_toggle = !st->fuzz_toggle;
+      if (st->fuzz_toggle)
         {
           totop = top;
           height = 1;
-          toleft = nrnd(sizex - 1);
+          toleft = nrnd(st->sizex - 1);
           if (toleft > left)
             {
               width = toleft-left;
@@ -206,7 +225,7 @@ decay1 (Display *dpy, Window window)
         {
           toleft = left;
           width = 1;
-          totop  = nrnd(sizey - 1);
+          totop  = nrnd(st->sizey - 1);
           if (totop > top)
             {
               height = totop-top;
@@ -223,32 +242,32 @@ decay1 (Display *dpy, Window window)
 
     } else {
 
-      left = nrnd(sizex - 1);
-      top = nrnd(sizey);
-      width = nrnd(sizex - left);
-      height = nrnd(sizey - top);
+      left = nrnd(st->sizex - 1);
+      top = nrnd(st->sizey);
+      width = nrnd(st->sizex - left);
+      height = nrnd(st->sizey - top);
       
       toleft = left;
       totop = top;
-      if (mode == IN || mode == OUT) {
+      if (st->mode == IN || st->mode == OUT) {
        int x = left+(width/2);
        int y = top+(height/2);
-       int cx = sizex/2;
-       int cy = sizey/2;
-       if (mode == IN) {
-         if      (x > cx && y > cy)   bias = upleft_bias;
-         else if (x < cx && y > cy)   bias = upright_bias;
-         else if (x < cx && y < cy)   bias = downright_bias;
-         else /* (x > cx && y < cy)*/ bias = downleft_bias;
+       int cx = st->sizex/2;
+       int cy = st->sizey/2;
+       if (st->mode == IN) {
+         if      (x > cx && y > cy)   st->current_bias = upleft_bias;
+         else if (x < cx && y > cy)   st->current_bias = upright_bias;
+         else if (x < cx && y < cy)   st->current_bias = downright_bias;
+         else /* (x > cx && y < cy)*/ st->current_bias = downleft_bias;
        } else {
-         if      (x > cx && y > cy)   bias = downright_bias;
-         else if (x < cx && y > cy)   bias = downleft_bias;
-         else if (x < cx && y < cy)   bias = upleft_bias;
-         else /* (x > cx && y < cy)*/ bias = upright_bias;
+         if      (x > cx && y > cy)   st->current_bias = downright_bias;
+         else if (x < cx && y > cy)   st->current_bias = downleft_bias;
+         else if (x < cx && y < cy)   st->current_bias = upleft_bias;
+         else /* (x > cx && y < cy)*/ st->current_bias = upright_bias;
        }
       }
       
-      switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
+      switch (st->current_bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
       case L: toleft = left-1; break;
       case R: toleft = left+1; break;
       case U: totop = top-1; break;
@@ -257,21 +276,46 @@ decay1 (Display *dpy, Window window)
       }
     }
     
-    if (mode == STRETCH) {
-      XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1, 
-                0, sizey-top-1); 
+    if (st->mode == STRETCH) {
+      XCopyArea (st->dpy, st->window, st->window, st->gc, 0, st->sizey-top-2, st->sizex, top+1, 
+                0, st->sizey-top-1); 
     } else {
-      XCopyArea (dpy, window, window, gc, left, top, width, height,
+      XCopyArea (st->dpy, st->window, st->window, st->gc, left, top, width, height,
                 toleft, totop);
     }
 
 #undef nrnd
+
+    return st->delay;
+}
+
+static void
+decayscreen_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  st->sizex = w;
+  st->sizey = h;
+}
+
+static Bool
+decayscreen_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
+}
+
+static void
+decayscreen_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  free (st);
 }
 
 \f
-char *progclass = "DecayScreen";
 
-char *defaults [] = {
+static const char *decayscreen_defaults [] = {
+  ".background:                        Black",
+  ".foreground:                        Yellow",
   "*dontClearRoot:             True",
 
 #ifdef __sgi   /* really, HAVE_READ_DISPLAY_EXTENSION */
@@ -283,22 +327,11 @@ char *defaults [] = {
   0
 };
 
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec decayscreen_options [] = {
   { "-delay",          ".delay",               XrmoptionSepArg, 0 },
   { "-mode",           ".mode",                XrmoptionSepArg, 0 },
   { 0, 0, 0, 0 }
 };
 
-void
-screenhack (Display *dpy, Window window)
-{
-    init_decay (dpy, window);
-    while (1) {
-      int i;
-      for (i = 0; i < iterations; i++)
-       decay1 (dpy, window);
-      XSync(dpy, False);
-      screenhack_handle_events (dpy);
-      if (delay) usleep (delay);
-    }
-}
+
+XSCREENSAVER_MODULE ("DecayScreen", decayscreen)