2 * Copyright (C) 2000 James Macnicol
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
14 #include "screenhack.h"
15 #include <X11/Xutil.h>
19 #define MIN(a, b) (((a) < (b))?(a):(b))
23 #define MAX(a, b) (((a) > (b))?(a):(b))
28 /* This should be *way* slower than the spotlight hack was */
29 #define X_PERIOD 45000.0
30 #define Y_PERIOD 36000.0
32 static int sizex, sizey;
35 static int pixwidth, pixheight, pixspacex, pixspacey, lensoffsetx, lensoffsety;
40 static XImage *orig_map;
43 static int tlx, tly, s;
45 static long currentTimeInMs(void)
47 struct timeval curTime;
48 #ifdef GETTIMEOFDAY_TWO_ARGS
49 struct timezone tz = {0,0};
50 gettimeofday(&curTime, &tz);
52 gettimeofday(&curTime);
54 return curTime.tv_sec*1000 + curTime.tv_usec/1000.0;
57 static void init_hack(Display *dpy, Window window)
60 XWindowAttributes xgwa;
64 int nblocksx, nblocksy;
66 XGetWindowAttributes(dpy, window, &xgwa);
70 fg = get_pixel_resource("foreground", "Foreground", dpy, cmap);
71 bg = get_pixel_resource("background", "Background", dpy, cmap);
73 delay = get_integer_resource("delay", "Integer");
76 pixwidth = get_integer_resource("pixwidth", "Integer");
79 pixheight = get_integer_resource("pixheight", "Integer");
82 pixspacex = get_integer_resource("pixspacex", "Integer");
85 pixspacey = get_integer_resource("pixspacey", "Integer");
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));
94 gcv.function = GXcopy;
95 gcv.subwindow_mode = IncludeInferiors;
96 gcflags = GCForeground|GCFunction;
98 if (!lenses && use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
99 gcflags |= GCSubwindowMode;
100 window_gc = XCreateGC(dpy, window, gcflags, &gcv);
104 pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
105 load_random_image (xgwa.screen, window, pm);
108 orig_map = XGetImage(dpy, pm, 0, 0, sizex, sizey, ~0L, ZPixmap);
109 XFreePixmap(dpy, pm);
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);
118 XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
119 XSetWindowBackground(dpy, window, bg);
121 nblocksx = (int)ceil((double)sizex / (double)(pixwidth + pixspacex));
122 nblocksy = (int)ceil((double)sizey / (double)(pixheight + pixspacey));
124 s = MAX((nblocksx - 1) * lensoffsetx + pixwidth,
125 (nblocksy - 1) * lensoffsety + pixheight) * 2;
127 s = MAX(nblocksx, nblocksy) * 2;
130 static void onestep(Display *dpy, Window window)
136 #define nrnd(x) (random() % (x))
138 now = currentTimeInMs();
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;
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 */,
153 x /* dest_x */, y /* dest_y */);
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);
166 char *progclass = "Zoom";
169 "*dontClearRoot: True",
170 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
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 },
196 void screenhack(Display *dpy, Window window)
198 init_hack(dpy, window);
200 onestep(dpy, window);
204 screenhack_handle_events(dpy);