http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.tar.gz
[xscreensaver] / hacks / zoom.c
diff --git a/hacks/zoom.c b/hacks/zoom.c
new file mode 100644 (file)
index 0000000..f6cb4b9
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ *  Copyright (C) 2000 James Macnicol
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+#include <X11/Xutil.h>
+#include <sys/time.h>
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b))?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b))?(a):(b))
+#endif
+
+#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
+
+static int sizex, sizey;
+
+static int delay;
+static int pixwidth, pixheight, pixspacex, pixspacey, lensoffsetx, lensoffsety;
+static Bool lenses;
+
+static GC window_gc;
+
+static XImage *orig_map;
+static Pixmap pm;
+
+static int tlx, tly, s;
+
+static long currentTimeInMs(void)
+{ 
+  struct timeval curTime;
+#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;
+}
+
+static void init_hack(Display *dpy, Window window)
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  unsigned long fg, bg;
+  long gcflags;
+  int nblocksx, nblocksy;
+
+  XGetWindowAttributes(dpy, window, &xgwa);
+  sizex = xgwa.width;
+  sizey = xgwa.height;
+  cmap = xgwa.colormap;
+  fg = get_pixel_resource("foreground", "Foreground", dpy, cmap);
+  bg = get_pixel_resource("background", "Background", dpy, cmap);
+
+  delay = get_integer_resource("delay", "Integer");
+  if (delay < 1)
+    delay = 1;
+  pixwidth = get_integer_resource("pixwidth", "Integer");
+  if (pixwidth < 1)
+    pixwidth = 1;
+  pixheight = get_integer_resource("pixheight", "Integer");
+  if (pixheight < 1)
+    pixheight = 1;
+  pixspacex = get_integer_resource("pixspacex", "Integer");
+  if (pixspacex < 0)
+    pixspacex = 0;
+  pixspacey = get_integer_resource("pixspacey", "Integer");
+  if (pixspacey < 0)
+    pixspacey = 0;
+  lenses = get_boolean_resource("lenses", "Boolean");
+  lensoffsetx = get_integer_resource("lensoffsetx", "Integer");
+  lensoffsetx = MAX(0, MIN(pixwidth, lensoffsetx));
+  lensoffsety = get_integer_resource("lensoffsety", "Integer");
+  lensoffsety = MAX(0, MIN(pixwidth, lensoffsety));
+
+  gcv.function = GXcopy;
+  gcv.subwindow_mode = IncludeInferiors;
+  gcflags = GCForeground|GCFunction;
+  gcv.foreground = bg;
+  if (!lenses && use_subwindow_mode_p(xgwa.screen, window))       /* see grabscreen.c */
+    gcflags |= GCSubwindowMode;
+  window_gc = XCreateGC(dpy, window, gcflags, &gcv);
+
+  grab_screen_image(xgwa.screen, window);
+  if (lenses) {
+    orig_map = NULL;
+    pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
+    XCopyArea(dpy, window, pm, window_gc, 0, 0, sizex, sizey, 0, 0);
+  } else {
+    orig_map = XGetImage(dpy, window, 0, 0, sizex, sizey, ~0L, ZPixmap);
+    pm = 0;
+  }
+
+  XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
+  XSetWindowBackground(dpy, window, bg);
+
+  nblocksx = (int)ceil((double)sizex / (double)(pixwidth + pixspacex));
+  nblocksy = (int)ceil((double)sizey / (double)(pixheight + pixspacey));
+  if (lenses)
+    s = MAX((nblocksx - 1) * lensoffsetx + pixwidth, 
+           (nblocksy - 1) * lensoffsety + pixheight) * 2;
+  else
+    s = MAX(nblocksx, nblocksy) * 2;
+}
+
+static void onestep(Display *dpy, Window window)
+{
+  unsigned x, y, i, j;
+
+  long now;
+
+#define nrnd(x) (random() % (x))
+
+  now = currentTimeInMs();
+
+  /* find new x,y */
+  tlx = ((1. + sin(((float)now) / X_PERIOD * 2. * M_PI))/2.0)
+    * (sizex - s/2) /* -s/4 */ + MINX;
+  tly = ((1. + sin(((float)now) / Y_PERIOD * 2. * M_PI))/2.0)
+    * (sizey - s/2) /* -s/4 */ + MINY;
+
+  if (lenses) {
+    for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
+      for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
+       XCopyArea(dpy, pm /* src */, window /* dest */, window_gc,
+                 tlx + i * lensoffsetx /* src_x */, 
+                 tly + j * lensoffsety /* src_y */,
+                 pixwidth, pixheight,
+                 x /* dest_x */, y /* dest_y */);
+      }
+  } else {
+    for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
+      for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
+       XSetForeground(dpy, window_gc, XGetPixel(orig_map, tlx+i, tly+j));
+       XFillRectangle(dpy, window, window_gc, 
+                      i * (pixwidth + pixspacex),
+                      j * (pixheight + pixspacey), pixwidth, pixheight);
+      }
+  }
+}
+
+char *progclass = "Zoom";
+
+char *defaults[] = {
+  "*dontClearRoot: True",
+#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
+  "*visualID: Best",
+#endif
+  "*lenses:      false",
+  "*delay:       10000",
+  "*pixwidth:    10",
+  "*pixheight:   10",
+  "*pixspacex:   2",
+  "*pixspacey:   2",
+  "*lensoffsetx: 5",
+  "*lensoffsety: 5",
+  0
+};
+
+XrmOptionDescRec options[] = {
+  { "-lenses", ".lenses", XrmoptionNoArg, "true" },
+  { "-delay", ".delay", XrmoptionSepArg, 0 },
+  { "-pixwidth", ".pixwidth", XrmoptionSepArg, 0 },
+  { "-pixheight", ".pixheight", XrmoptionSepArg, 0 },
+  { "-pixspacex", ".pixspacex", XrmoptionSepArg, 0 },
+  { "-pixspacey", ".pixspacex", XrmoptionSepArg, 0 },
+  { "-lensoffsetx", ".lensoffsetx", XrmoptionSepArg, 0 },
+  { "-lensoffsety", ".lensoffsety", XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+
+void screenhack(Display *dpy, Window window)
+{
+  init_hack(dpy, window);
+  while (1) {
+    onestep(dpy, window);
+    XSync(dpy, False);
+    if (delay)
+      usleep(delay);
+    screenhack_handle_events(dpy);
+  }
+}