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);
102 grab_screen_image(xgwa.screen, window);
104 /* We might have needed this to grab the image, but if we leave this set
105 to GCSubwindowMode, then we'll *draw* right over subwindows too. */
106 XSetSubwindowMode (dpy, window_gc, ClipByChildren);
110 pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
111 XCopyArea(dpy, window, pm, window_gc, 0, 0, sizex, sizey, 0, 0);
113 orig_map = XGetImage(dpy, window, 0, 0, sizex, sizey, ~0L, ZPixmap);
117 XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
118 XSetWindowBackground(dpy, window, bg);
120 nblocksx = (int)ceil((double)sizex / (double)(pixwidth + pixspacex));
121 nblocksy = (int)ceil((double)sizey / (double)(pixheight + pixspacey));
123 s = MAX((nblocksx - 1) * lensoffsetx + pixwidth,
124 (nblocksy - 1) * lensoffsety + pixheight) * 2;
126 s = MAX(nblocksx, nblocksy) * 2;
129 static void onestep(Display *dpy, Window window)
135 #define nrnd(x) (random() % (x))
137 now = currentTimeInMs();
140 tlx = ((1. + sin(((float)now) / X_PERIOD * 2. * M_PI))/2.0)
141 * (sizex - s/2) /* -s/4 */ + MINX;
142 tly = ((1. + sin(((float)now) / Y_PERIOD * 2. * M_PI))/2.0)
143 * (sizey - s/2) /* -s/4 */ + MINY;
146 for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
147 for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
148 XCopyArea(dpy, pm /* src */, window /* dest */, window_gc,
149 tlx + i * lensoffsetx /* src_x */,
150 tly + j * lensoffsety /* src_y */,
152 x /* dest_x */, y /* dest_y */);
155 for (x = i = 0; x < sizex; x += (pixwidth + pixspacex), ++i)
156 for (y = j = 0; y < sizey; y += (pixheight + pixspacey), ++j) {
157 XSetForeground(dpy, window_gc, XGetPixel(orig_map, tlx+i, tly+j));
158 XFillRectangle(dpy, window, window_gc,
159 i * (pixwidth + pixspacex),
160 j * (pixheight + pixspacey), pixwidth, pixheight);
165 char *progclass = "Zoom";
168 "*dontClearRoot: True",
169 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
183 XrmOptionDescRec options[] = {
184 { "-lenses", ".lenses", XrmoptionNoArg, "true" },
185 { "-delay", ".delay", XrmoptionSepArg, 0 },
186 { "-pixwidth", ".pixwidth", XrmoptionSepArg, 0 },
187 { "-pixheight", ".pixheight", XrmoptionSepArg, 0 },
188 { "-pixspacex", ".pixspacex", XrmoptionSepArg, 0 },
189 { "-pixspacey", ".pixspacey", XrmoptionSepArg, 0 },
190 { "-lensoffsetx", ".lensoffsetx", XrmoptionSepArg, 0 },
191 { "-lensoffsety", ".lensoffsety", XrmoptionSepArg, 0 },
195 void screenhack(Display *dpy, Window window)
197 init_hack(dpy, window);
199 onestep(dpy, window);
203 screenhack_handle_events(dpy);