http://packetstorm.tacticalflex.com/UNIX/admin/xscreensaver-3.27.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   grab_screen_image(xgwa.screen, window);
103   if (lenses) {
104     orig_map = NULL;
105     pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
106     XCopyArea(dpy, window, pm, window_gc, 0, 0, sizex, sizey, 0, 0);
107   } else {
108     orig_map = XGetImage(dpy, window, 0, 0, sizex, sizey, ~0L, ZPixmap);
109     pm = 0;
110   }
111
112   XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
113   XSetWindowBackground(dpy, window, bg);
114
115   nblocksx = (int)ceil((double)sizex / (double)(pixwidth + pixspacex));
116   nblocksy = (int)ceil((double)sizey / (double)(pixheight + pixspacey));
117   if (lenses)
118     s = MAX((nblocksx - 1) * lensoffsetx + pixwidth, 
119             (nblocksy - 1) * lensoffsety + pixheight) * 2;
120   else
121     s = MAX(nblocksx, nblocksy) * 2;
122 }
123
124 static void onestep(Display *dpy, Window window)
125 {
126   unsigned x, y, i, j;
127
128   long now;
129
130 #define nrnd(x) (random() % (x))
131
132   now = currentTimeInMs();
133
134   /* find new x,y */
135   tlx = ((1. + sin(((float)now) / X_PERIOD * 2. * M_PI))/2.0)
136     * (sizex - s/2) /* -s/4 */ + MINX;
137   tly = ((1. + sin(((float)now) / Y_PERIOD * 2. * M_PI))/2.0)
138     * (sizey - s/2) /* -s/4 */ + MINY;
139
140   if (lenses) {
141     for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
142       for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
143         XCopyArea(dpy, pm /* src */, window /* dest */, window_gc,
144                   tlx + i * lensoffsetx /* src_x */, 
145                   tly + j * lensoffsety /* src_y */,
146                   pixwidth, pixheight,
147                   x /* dest_x */, y /* dest_y */);
148       }
149   } else {
150     for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
151       for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
152         XSetForeground(dpy, window_gc, XGetPixel(orig_map, tlx+i, tly+j));
153         XFillRectangle(dpy, window, window_gc, 
154                        i * (pixwidth + pixspacex),
155                        j * (pixheight + pixspacey), pixwidth, pixheight);
156       }
157   }
158 }
159
160 char *progclass = "Zoom";
161
162 char *defaults[] = {
163   "*dontClearRoot: True",
164 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
165   "*visualID: Best",
166 #endif
167   "*lenses:      false",
168   "*delay:       10000",
169   "*pixwidth:    10",
170   "*pixheight:   10",
171   "*pixspacex:   2",
172   "*pixspacey:   2",
173   "*lensoffsetx: 5",
174   "*lensoffsety: 5",
175   0
176 };
177
178 XrmOptionDescRec options[] = {
179   { "-lenses", ".lenses", XrmoptionNoArg, "true" },
180   { "-delay", ".delay", XrmoptionSepArg, 0 },
181   { "-pixwidth", ".pixwidth", XrmoptionSepArg, 0 },
182   { "-pixheight", ".pixheight", XrmoptionSepArg, 0 },
183   { "-pixspacex", ".pixspacex", XrmoptionSepArg, 0 },
184   { "-pixspacey", ".pixspacex", XrmoptionSepArg, 0 },
185   { "-lensoffsetx", ".lensoffsetx", XrmoptionSepArg, 0 },
186   { "-lensoffsety", ".lensoffsety", XrmoptionSepArg, 0 },
187   { 0, 0, 0, 0 }
188 };
189
190 void screenhack(Display *dpy, Window window)
191 {
192   init_hack(dpy, window);
193   while (1) {
194     onestep(dpy, window);
195     XSync(dpy, False);
196     if (delay)
197       usleep(delay);
198     screenhack_handle_events(dpy);
199   }
200 }