[15682] | 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 | |
---|
[20147] | 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 | |
---|
[15682] | 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 }, |
---|
[20147] | 190 | { "-pixspacey", ".pixspacey", XrmoptionSepArg, 0 }, |
---|
[15682] | 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 | } |
---|