http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / zoom.c
1 /*
2  *  Copyright (C) 2000 James Macnicol
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 #include <math.h>
14 #include "screenhack.h"
15 #include <X11/Xutil.h>
16 #include <sys/time.h>
17
18 #ifndef MIN
19 #define MIN(a, b) (((a) < (b))?(a):(b))
20 #endif
21
22 #ifndef MAX
23 #define MAX(a, b) (((a) > (b))?(a):(b))
24 #endif
25
26 #define MINX 0.0
27 #define MINY 0.0
28 /* This should be *way* slower than the spotlight hack was */
29 #define X_PERIOD 45000.0
30 #define Y_PERIOD 36000.0
31
32 static int sizex, sizey;
33
34 static int delay;
35 static int pixwidth, pixheight, pixspacex, pixspacey, lensoffsetx, lensoffsety;
36 static Bool lenses;
37
38 static GC window_gc;
39
40 static XImage *orig_map;
41 static Pixmap pm;
42
43 static int tlx, tly, s;
44
45 static long currentTimeInMs(void)
46
47   struct timeval curTime;
48 #ifdef GETTIMEOFDAY_TWO_ARGS
49   struct timezone tz = {0,0};
50   gettimeofday(&curTime, &tz);
51 #else
52   gettimeofday(&curTime);
53 #endif
54   return curTime.tv_sec*1000 + curTime.tv_usec/1000.0;
55 }
56
57 static void init_hack(Display *dpy, Window window)
58 {
59   XGCValues gcv;
60   XWindowAttributes xgwa;
61   Colormap cmap;
62   unsigned long fg, bg;
63   long gcflags;
64   int nblocksx, nblocksy;
65
66   XGetWindowAttributes(dpy, window, &xgwa);
67   sizex = xgwa.width;
68   sizey = xgwa.height;
69   cmap = xgwa.colormap;
70   fg = get_pixel_resource("foreground", "Foreground", dpy, cmap);
71   bg = get_pixel_resource("background", "Background", dpy, cmap);
72
73   delay = get_integer_resource("delay", "Integer");
74   if (delay < 1)
75     delay = 1;
76   pixwidth = get_integer_resource("pixwidth", "Integer");
77   if (pixwidth < 1)
78     pixwidth = 1;
79   pixheight = get_integer_resource("pixheight", "Integer");
80   if (pixheight < 1)
81     pixheight = 1;
82   pixspacex = get_integer_resource("pixspacex", "Integer");
83   if (pixspacex < 0)
84     pixspacex = 0;
85   pixspacey = get_integer_resource("pixspacey", "Integer");
86   if (pixspacey < 0)
87     pixspacey = 0;
88   lenses = get_boolean_resource("lenses", "Boolean");
89   lensoffsetx = get_integer_resource("lensoffsetx", "Integer");
90   lensoffsetx = MAX(0, MIN(pixwidth, lensoffsetx));
91   lensoffsety = get_integer_resource("lensoffsety", "Integer");
92   lensoffsety = MAX(0, MIN(pixwidth, lensoffsety));
93
94   gcv.function = GXcopy;
95   gcv.subwindow_mode = IncludeInferiors;
96   gcflags = GCForeground|GCFunction;
97   gcv.foreground = bg;
98   if (!lenses && use_subwindow_mode_p(xgwa.screen, window))       /* see grabscreen.c */
99     gcflags |= GCSubwindowMode;
100   window_gc = XCreateGC(dpy, window, gcflags, &gcv);
101
102
103   orig_map = NULL;
104   pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
105   load_random_image (xgwa.screen, window, pm, NULL);
106
107   if (!lenses) {
108     orig_map = XGetImage(dpy, pm, 0, 0, sizex, sizey, ~0L, ZPixmap);
109     XFreePixmap(dpy, pm);
110     pm = 0;
111   }
112
113   /* We might have needed this to grab the image, but if we leave this set
114      to GCSubwindowMode, then we'll *draw* right over subwindows too. */
115   XSetSubwindowMode (dpy, window_gc, ClipByChildren);
116
117
118   XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
119   XSetWindowBackground(dpy, window, bg);
120
121   nblocksx = (int)ceil((double)sizex / (double)(pixwidth + pixspacex));
122   nblocksy = (int)ceil((double)sizey / (double)(pixheight + pixspacey));
123   if (lenses)
124     s = MAX((nblocksx - 1) * lensoffsetx + pixwidth, 
125             (nblocksy - 1) * lensoffsety + pixheight) * 2;
126   else
127     s = MAX(nblocksx, nblocksy) * 2;
128 }
129
130 static void onestep(Display *dpy, Window window)
131 {
132   unsigned x, y, i, j;
133
134   long now;
135
136 #define nrnd(x) (random() % (x))
137
138   now = currentTimeInMs();
139
140   /* find new x,y */
141   tlx = ((1. + sin(((float)now) / X_PERIOD * 2. * M_PI))/2.0)
142     * (sizex - s/2) /* -s/4 */ + MINX;
143   tly = ((1. + sin(((float)now) / Y_PERIOD * 2. * M_PI))/2.0)
144     * (sizey - s/2) /* -s/4 */ + MINY;
145
146   if (lenses) {
147     for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
148       for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
149         XCopyArea(dpy, pm /* src */, window /* dest */, window_gc,
150                   tlx + i * lensoffsetx /* src_x */, 
151                   tly + j * lensoffsety /* src_y */,
152                   pixwidth, pixheight,
153                   x /* dest_x */, y /* dest_y */);
154       }
155   } else {
156     for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
157       for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
158         XSetForeground(dpy, window_gc, XGetPixel(orig_map, tlx+i, tly+j));
159         XFillRectangle(dpy, window, window_gc, 
160                        i * (pixwidth + pixspacex),
161                        j * (pixheight + pixspacey), pixwidth, pixheight);
162       }
163   }
164 }
165
166 char *progclass = "Zoom";
167
168 char *defaults[] = {
169   "*dontClearRoot: True",
170 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
171   "*visualID: Best",
172 #endif
173   "*lenses:      false",
174   "*delay:       10000",
175   "*pixwidth:    10",
176   "*pixheight:   10",
177   "*pixspacex:   2",
178   "*pixspacey:   2",
179   "*lensoffsetx: 5",
180   "*lensoffsety: 5",
181   0
182 };
183
184 XrmOptionDescRec options[] = {
185   { "-lenses", ".lenses", XrmoptionNoArg, "true" },
186   { "-delay", ".delay", XrmoptionSepArg, 0 },
187   { "-pixwidth", ".pixwidth", XrmoptionSepArg, 0 },
188   { "-pixheight", ".pixheight", XrmoptionSepArg, 0 },
189   { "-pixspacex", ".pixspacex", XrmoptionSepArg, 0 },
190   { "-pixspacey", ".pixspacey", XrmoptionSepArg, 0 },
191   { "-lensoffsetx", ".lensoffsetx", XrmoptionSepArg, 0 },
192   { "-lensoffsety", ".lensoffsety", XrmoptionSepArg, 0 },
193   { 0, 0, 0, 0 }
194 };
195
196 void screenhack(Display *dpy, Window window)
197 {
198   init_hack(dpy, window);
199   while (1) {
200     onestep(dpy, window);
201     XSync(dpy, False);
202     if (delay)
203       usleep(delay);
204     screenhack_handle_events(dpy);
205   }
206 }