From http://www.jwz.org/xscreensaver/xscreensaver-5.39.tar.gz
[xscreensaver] / hacks / spotlight.c
index 19663c01a13689d10f1563a40f1980f7e1ab678b..73858991a749dbe77600370d4c088f185a0a8d8e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * spotlight - an xscreensaver module
- * Copyright (c) 1999, 2001 Rick Schultz <rick@skapunx.net>
+ * Copyright (c) 1999, 2001 Rick Schultz <rick.schultz@gmail.com>
  *
  * loosely based on the BackSpace module "StefView" by Darcy Brockbank
  */
 
 /* #define DEBUG */
 #include <math.h>
+#include <limits.h>
 #include "screenhack.h"
 
-#define MINX 0.0
-#define MINY 0.0
 #define X_PERIOD 15000.0
 #define Y_PERIOD 12000.0
 
@@ -38,7 +37,7 @@ struct state {
   int delay;
   int duration;
   time_t start_time;
-
+  int first_time;
   GC window_gc;
 #ifdef DEBUG
   GC white_gc;
@@ -64,6 +63,7 @@ struct state {
 
   Bool first_p;
   async_load_state *img_loader;
+  XRectangle geom;
 };
 
 
@@ -73,13 +73,15 @@ 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);
 }
 
 
@@ -91,7 +93,7 @@ spotlight_init (Display *dpy, Window window)
   XWindowAttributes xgwa;
   long gcflags;
   Colormap cmap;
-  unsigned long fg, bg;
+  unsigned long bg;
   GC clip_gc;
   Pixmap clip_pm;
 
@@ -104,7 +106,6 @@ spotlight_init (Display *dpy, Window window)
   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");
 
   /* read parameters, keep em sane */
@@ -115,6 +116,8 @@ spotlight_init (Display *dpy, Window window)
   st->radius = get_integer_resource (st->dpy, "radius", "Integer");
   if (st->radius < 0) st->radius = 125;
 
+  if (xgwa.width > 2560) st->radius *= 2;  /* Retina displays */
+
   /* Don't let the spotlight be bigger than the window */
   while (st->radius > xgwa.width * 0.45)
     st->radius /= 2;
@@ -139,8 +142,10 @@ spotlight_init (Display *dpy, Window window)
   st->pm = XCreatePixmap(st->dpy, st->window, st->sizex, st->sizey, xgwa.depth);
   XClearWindow(st->dpy, st->window);
 
+  st->first_time = 1;
+
   /* create buffer to reduce flicker */
-#ifdef HAVE_COCOA      /* Don't second-guess Quartz's double-buffering */
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
   st->buffer = 0;
 #else
   st->buffer = XCreatePixmap(st->dpy, st->window, st->sizex, st->sizey, xgwa.depth);
@@ -150,15 +155,11 @@ spotlight_init (Display *dpy, Window window)
   if (st->buffer)
     XFillRectangle(st->dpy, st->buffer, st->buffer_gc, 0, 0, st->sizex, st->sizey);
 
-  /* blank out screen */
-  XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey);
-  XSetWindowBackground (st->dpy, st->window, bg);
-
   /* create clip mask (so it's a circle, not a square) */
   clip_pm = XCreatePixmap(st->dpy, st->window, st->radius*4, st->radius*4, 1);
   st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, st->pm,
-                                            0, 0);
-  st->start_time = time ((time_t) 0);
+                                            0, &st->geom);
+  st->start_time = time ((time_t *) 0);
 
   gcv.foreground = 0L;
   clip_gc = XCreateGC(st->dpy, clip_pm, gcflags, &gcv);
@@ -180,11 +181,9 @@ spotlight_init (Display *dpy, Window window)
   
   st->off = random();
 
-#ifdef DEBUG
-  /* create GC with white fg */
-  gcv.foreground = fg;
-  st->white_gc = XCreateGC(st->dpy, st->window, gcflags, &gcv);
-#endif
+  /* blank out screen */
+  XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey);
+
   return st;
 }
 
@@ -196,20 +195,22 @@ static void
 onestep (struct state *st, Bool first_p)
 {
   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);
+      st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 
+                                                &st->geom);
       if (! st->img_loader) {  /* just finished */
-        st->start_time = time ((time_t) 0);
+        st->start_time = time ((time_t *) 0);
       }
       return;
     }
 
   if (!st->img_loader &&
-      st->start_time + st->duration < time ((time_t) 0)) {
+      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);
+                                              st->pm, 0, &st->geom);
     return;
   }
 
@@ -220,13 +221,16 @@ onestep (struct state *st, Bool first_p)
 
   st->s = st->radius *4 ;   /* s = width of buffer */
 
-  now = currentTimeInMs(st) + st->off;
+  now_unsigned = (unsigned long) currentTimeInMs(st) + st->off;
+  now = (now_unsigned <= LONG_MAX) ? now_unsigned : -1 - (long)(ULONG_MAX - now_unsigned);
 
   /* find new x,y */
-  st->x = ((1 + sin(((double)now) / X_PERIOD * 2. * M_PI))/2.0) 
-    * (st->sizex - st->s/2) -st->s/4  + MINX;
-  st->y = ((1 + sin(((double)now) / Y_PERIOD * 2. * M_PI))/2.0) 
-    * (st->sizey - st->s/2) -st->s/4  + MINY;
+  st->x = st->geom.x +
+    ((1 + sin(((double)now) / X_PERIOD * 2. * M_PI))/2.0) 
+    * (st->geom.width - st->s/2) -st->s/4;
+  st->y = st->geom.y +
+    ((1 + sin(((double)now) / Y_PERIOD * 2. * M_PI))/2.0) 
+    * (st->geom.height - st->s/2) -st->s/4;
     
   if (!st->first_p)
     {
@@ -253,8 +257,21 @@ onestep (struct state *st, Bool first_p)
       XSetClipOrigin(st->dpy, st->buffer_gc, st->x,st->y);
       XCopyArea(st->dpy, st->pm, st->buffer, st->buffer_gc, st->x, st->y, st->s, st->s, st->x, st->y);
 
+      if (st->first_time) {
+        /* blank out screen */
+        XFillRectangle(st->dpy, st->window, st->window_gc, 0, 0, st->sizex, st->sizey);
+        st->first_time = 0;
+      }
+
       /* copy buffer to screen (window) */
       XCopyArea(st->dpy, st->buffer, st->window, st->window_gc, st->x , st->y, st->s, st->s, st->x, st->y);
+
+# if 0
+      XSetForeground (st->dpy, st->window_gc,
+                      WhitePixel (st->dpy, DefaultScreen (st->dpy)));
+      XDrawRectangle(st->dpy, st->window, st->window_gc,
+                     st->geom.x, st->geom.y, st->geom.width, st->geom.height);
+# endif
     }
 
 #ifdef DEBUG
@@ -283,6 +300,12 @@ spotlight_reshape (Display *dpy, Window window, void *closure,
 static Bool
 spotlight_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;
 }
 
@@ -313,6 +336,10 @@ static const char *spotlight_defaults [] = {
   "*delay:                     10000",
   "*duration:                  120",
   "*radius:                    125",
+#ifdef HAVE_MOBILE
+  "*ignoreRotation:             True",
+  "*rotateImages:               True",
+#endif
   0
 };