From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / zoom.c
index 2dd27538b56d19d5addb2716b2a57a3396aeadff..99a652a54cd5f5d9abc9842fbece4bc37904e4f0 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <math.h>
+#include <limits.h>
 #include "screenhack.h"
 
 #ifndef MIN
 #define MINX 0.0
 #define MINY 0.0
 /* This should be *way* slower than the spotlight hack was */
-#define X_PERIOD 45000.0
-#define Y_PERIOD 36000.0
+#define X_PERIOD (45000.0 * 3)
+#define Y_PERIOD (36000.0 * 3)
 
 struct state {
   Display *dpy;
   Window window;
+  Screen *screen;
 
   int sizex, sizey;
 
   int delay;
+  int duration;
   int pixwidth, pixheight, pixspacex, pixspacey, lensoffsetx, lensoffsety;
   Bool lenses;
 
@@ -46,6 +49,7 @@ struct state {
 
   int sinusoid_offset;
 
+  time_t start_time;
   async_load_state *img_loader;
 };
 
@@ -53,13 +57,15 @@ struct state {
 static long currentTimeInMs(struct state *st)
 { 
   struct timeval curTime;
+  unsigned long ret_unsigned;
 #ifdef GETTIMEOFDAY_TWO_ARGS
   struct timezone tz = {0,0};
   gettimeofday(&curTime, &tz);
 #else
   gettimeofday(&curTime);
 #endif
-  return curTime.tv_sec*1000 + curTime.tv_usec/1000.0;
+  ret_unsigned = curTime.tv_sec *1000U + curTime.tv_usec / 1000;
+  return (ret_unsigned <= LONG_MAX) ? ret_unsigned : -1 - (long)(ULONG_MAX - ret_unsigned);
 }
 
 static void *
@@ -69,22 +75,25 @@ zoom_init (Display *dpy, Window window)
   XGCValues gcv;
   XWindowAttributes xgwa;
   Colormap cmap;
-  unsigned long fg, bg;
+  unsigned long bg;
   long gcflags;
   int nblocksx, nblocksy;
 
   st->dpy = dpy;
   st->window = window;
   XGetWindowAttributes(st->dpy, st->window, &xgwa);
+  st->screen = xgwa.screen;
   st->sizex = xgwa.width;
   st->sizey = xgwa.height;
   cmap = xgwa.colormap;
-  fg = get_pixel_resource(st->dpy, cmap, "foreground", "Foreground");
   bg = get_pixel_resource(st->dpy, cmap, "background", "Background");
 
   st->delay = get_integer_resource(st->dpy, "delay", "Integer");
   if (st->delay < 1)
     st->delay = 1;
+  st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+  if (st->duration < 1)
+    st->duration = 1;
   st->pixwidth = get_integer_resource(st->dpy, "pixwidth", "Integer");
   if (st->pixwidth < 1)
     st->pixwidth = 1;
@@ -118,6 +127,7 @@ zoom_init (Display *dpy, Window window)
   XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey);
   XSetWindowBackground(st->dpy, st->window, bg);
 
+  st->start_time = time ((time_t *) 0);
   st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
                                             st->pm, 0, 0);
 
@@ -146,25 +156,35 @@ zoom_draw (Display *dpy, Window window, void *closure)
   unsigned x, y, i, j;
 
   long now;
+  unsigned long now_unsigned;
 
   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 */
         XClearWindow (st->dpy, st->window);
+        st->start_time = time ((time_t *) 0);
         if (!st->lenses) {
           st->orig_map = XGetImage(st->dpy, st->pm, 0, 0, st->sizex, st->sizey, ~0L, ZPixmap);
-          XFreePixmap(st->dpy, st->pm);
-          st->pm = 0;
+/*          XFreePixmap(st->dpy, st->pm);
+          st->pm = 0;*/
         }
       }
       return st->delay;
     }
 
+  if (!st->img_loader &&
+      st->start_time + st->duration < time ((time_t *) 0)) {
+    st->img_loader = load_image_async_simple (0, st->screen, st->window,
+                                              st->pm, 0, 0);
+    return st->delay;
+  }
+
 #define nrnd(x) (random() % (x))
 
   now = currentTimeInMs(st);
-  now += st->sinusoid_offset;  /* don't run multiple screens in lock-step */
+  now_unsigned = (unsigned long) now + st->sinusoid_offset;  /* don't run multiple screens in lock-step */
+  now = (now_unsigned <= LONG_MAX) ? now_unsigned : -1 - (long)(ULONG_MAX - now_unsigned);
 
   /* find new x,y */
   st->tlx = ((1. + sin(((double)now) / X_PERIOD * 2. * M_PI))/2.0)
@@ -203,6 +223,12 @@ zoom_reshape (Display *dpy, Window window, void *closure,
 static Bool
 zoom_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
+  struct state *st = (struct state *) closure;
+  if (screenhack_event_helper (dpy, window, event))
+    {
+      st->start_time = 0;
+      return True;
+    }
   return False;
 }
 
@@ -220,24 +246,32 @@ zoom_free (Display *dpy, Window window, void *closure)
 static const char *zoom_defaults[] = {
   "*dontClearRoot: True",
   ".foreground: white",
-  ".background: black",
+  ".background: #111111",
+  "*fpsSolid:  true",
 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
   "*visualID: Best",
 #endif
-  "*lenses:      false",
+  "*lenses:      true",
   "*delay:       10000",
-  "*pixwidth:    10",
-  "*pixheight:   10",
+  "*duration:    120",
+  "*pixwidth:    40",
+  "*pixheight:   40",
   "*pixspacex:   2",
   "*pixspacey:   2",
   "*lensoffsetx: 5",
   "*lensoffsety: 5",
+#ifdef HAVE_MOBILE
+  "*ignoreRotation: True",
+  "*rotateImages:   True",
+#endif
   0
 };
 
 static XrmOptionDescRec zoom_options[] = {
   { "-lenses", ".lenses", XrmoptionNoArg, "true" },
+  { "-no-lenses", ".lenses", XrmoptionNoArg, "false" },
   { "-delay", ".delay", XrmoptionSepArg, 0 },
+  { "-duration",  ".duration", XrmoptionSepArg, 0 },
   { "-pixwidth", ".pixwidth", XrmoptionSepArg, 0 },
   { "-pixheight", ".pixheight", XrmoptionSepArg, 0 },
   { "-pixspacex", ".pixspacex", XrmoptionSepArg, 0 },