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 | } |
---|