14
14
enum { DOWN = 0, LEFT, UP, RIGHT };
15
15
enum { VERTICAL, HORIZONTAL };
19
static int hole_x, hole_y;
20
static int bitmap_w, bitmap_h;
21
static int xoff, yoff;
22
static int grid_w, grid_h;
23
static int delay, delay2;
25
static int max_width, max_height;
28
init_slide (Display *dpy, Window window)
24
int bitmap_w, bitmap_h;
30
int max_width, max_height;
34
int draw_x, draw_y, draw_ix, draw_iy, draw_dx, draw_dy;
35
int draw_dir, draw_w, draw_h, draw_size, draw_inc;
39
async_load_state *img_loader;
44
slidescreen_init (Display *dpy, Window window)
46
struct state *st = (struct state *) calloc (1, sizeof(*st));
47
XWindowAttributes xgwa;
32
XWindowAttributes xgwa;
40
XGetWindowAttributes (dpy, window, &xgwa);
41
load_random_image (xgwa.screen, window, window, NULL, NULL);
54
XGetWindowAttributes (st->dpy, st->window, &xgwa);
55
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
43
58
visual = xgwa.visual;
44
max_width = xgwa.width;
45
max_height = xgwa.height;
47
delay = get_integer_resource ("delay", "Integer");
48
delay2 = get_integer_resource ("delay2", "Integer");
49
grid_size = get_integer_resource ("gridSize", "Integer");
50
pix_inc = get_integer_resource ("pixelIncrement", "Integer");
51
border = get_integer_resource ("internalBorderWidth", "InternalBorderWidth");
53
/* Don't let the grid be smaller than 3x3 */
54
if (grid_size > xgwa.width / 3)
55
grid_size = xgwa.width / 3;
56
if (grid_size > xgwa.height / 3)
57
grid_size = xgwa.height / 3;
59
st->max_width = xgwa.width;
60
st->max_height = xgwa.height;
62
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
63
st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
64
st->grid_size = get_integer_resource (st->dpy, "gridSize", "Integer");
65
st->pix_inc = get_integer_resource (st->dpy, "pixelIncrement", "Integer");
67
/* Don't let the grid be smaller than 5x5 */
68
while (st->grid_size > xgwa.width / 5)
70
while (st->grid_size > xgwa.height / 5)
73
if (st->delay < 0) st->delay = 0;
74
if (st->delay2 < 0) st->delay2 = 0;
75
if (st->pix_inc < 1) st->pix_inc = 1;
76
if (st->grid_size < 1) st->grid_size = 1;
61
char *fgs = get_string_resource("background", "Background");
62
char *bgs = get_string_resource("foreground", "Foreground");
81
char *fgs = get_string_resource(st->dpy, "background", "Background");
82
char *bgs = get_string_resource(st->dpy, "foreground", "Foreground");
64
if (!XParseColor (dpy, cmap, fgs, &fgc))
65
XParseColor (dpy, cmap, "black", &bgc);
66
if (!XParseColor (dpy, cmap, bgs, &bgc))
67
XParseColor (dpy, cmap, "gray", &fgc);
84
if (!XParseColor (st->dpy, xgwa.colormap, fgs, &fgc))
85
XParseColor (st->dpy, xgwa.colormap, "black", &bgc);
86
if (!XParseColor (st->dpy, xgwa.colormap, bgs, &bgc))
87
XParseColor (st->dpy, xgwa.colormap, "gray", &fgc);
69
fg_ok = XAllocColor (dpy, cmap, &fgc);
70
bg_ok = XAllocColor (dpy, cmap, &bgc);
89
fg_ok = XAllocColor (st->dpy, xgwa.colormap, &fgc);
90
bg_ok = XAllocColor (st->dpy, xgwa.colormap, &bgc);
72
92
/* If we weren't able to allocate the two colors we want from the
73
93
colormap (which is likely if the screen has been grabbed on an
167
#endif /* !HAVE_COCOA */
148
if (delay < 0) delay = 0;
149
if (delay2 < 0) delay2 = 0;
150
if (pix_inc < 1) pix_inc = 1;
151
if (grid_size < 1) grid_size = 1;
170
gcv.foreground = st->fg;
154
171
gcv.function = GXcopy;
155
172
gcv.subwindow_mode = IncludeInferiors;
156
173
gcflags = GCForeground |GCFunction;
157
if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
174
if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */
158
175
gcflags |= GCSubwindowMode;
159
gc = XCreateGC (dpy, window, gcflags, &gcv);
161
XGetWindowAttributes (dpy, window, &xgwa);
162
bitmap_w = xgwa.width;
163
bitmap_h = xgwa.height;
165
grid_w = bitmap_w / grid_size;
166
grid_h = bitmap_h / grid_size;
167
hole_x = random () % grid_w;
168
hole_y = random () % grid_h;
169
xoff = (bitmap_w - (grid_w * grid_size)) / 2;
170
yoff = (bitmap_h - (grid_h * grid_size)) / 2;
176
st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
182
draw_grid (struct state *st)
187
XWindowAttributes xgwa;
189
XGetWindowAttributes (st->dpy, st->window, &xgwa);
191
border = get_integer_resource (st->dpy, "internalBorderWidth",
192
"InternalBorderWidth");
194
XGetWindowAttributes (st->dpy, st->window, &xgwa);
195
st->bitmap_w = xgwa.width;
196
st->bitmap_h = xgwa.height;
198
st->grid_w = st->bitmap_w / st->grid_size;
199
st->grid_h = st->bitmap_h / st->grid_size;
200
st->hole_x = random () % st->grid_w;
201
st->hole_y = random () % st->grid_h;
202
st->xoff = (st->bitmap_w - (st->grid_w * st->grid_size)) / 2;
203
st->yoff = (st->bitmap_h - (st->grid_h * st->grid_size)) / 2;
176
212
int half = border/2;
177
213
int half2 = (border & 1 ? half+1 : half);
178
XSetForeground(dpy, gc, bg);
179
for (i = 0; i < bitmap_w; i += grid_size)
214
XSetForeground(st->dpy, st->gc, st->bg);
215
for (i = 0; i < st->bitmap_w; i += st->grid_size)
182
for (j = 0; j < bitmap_h; j += grid_size)
183
XDrawRectangle (dpy, d, gc,
184
xoff+i+half2, yoff+j+half2,
185
grid_size-border-1, grid_size-border-1);
218
for (j = 0; j < st->bitmap_h; j += st->grid_size)
219
XDrawRectangle (st->dpy, d, st->gc,
220
st->xoff+i+half2, st->yoff+j+half2,
221
st->grid_size-border-1, st->grid_size-border-1);
188
XSetForeground(dpy, gc, fg);
189
for (i = 0; i <= bitmap_w; i += grid_size)
190
XFillRectangle (dpy, d, gc, xoff+i-half, yoff, border, bitmap_h);
191
for (i = 0; i <= bitmap_h; i += grid_size)
192
XFillRectangle (dpy, d, gc, xoff, yoff+i-half, bitmap_w, border);
197
XFillRectangle (dpy, d, gc, 0, 0, xoff, bitmap_h);
198
XFillRectangle (dpy, d, gc, bitmap_w - xoff, 0, xoff, bitmap_h);
202
XFillRectangle (dpy, d, gc, 0, 0, bitmap_w, yoff);
203
XFillRectangle (dpy, d, gc, 0, bitmap_h - yoff, bitmap_w, yoff);
207
if (delay2) usleep (delay2);
208
for (i = 0; i < grid_size; i += pix_inc)
224
XSetForeground(st->dpy, st->gc, st->fg);
225
for (i = 0; i <= st->bitmap_w; i += st->grid_size)
226
XFillRectangle (st->dpy, d, st->gc, st->xoff+i-half, st->yoff, border, st->bitmap_h);
227
for (i = 0; i <= st->bitmap_h; i += st->grid_size)
228
XFillRectangle (st->dpy, d, st->gc, st->xoff, st->yoff+i-half, st->bitmap_w, border);
233
XFillRectangle (st->dpy, d, st->gc, 0, 0, st->xoff, st->bitmap_h);
234
XFillRectangle (st->dpy, d, st->gc, st->bitmap_w - st->xoff, 0, st->xoff, st->bitmap_h);
238
XFillRectangle (st->dpy, d, st->gc, 0, 0, st->bitmap_w, st->yoff);
239
XFillRectangle (st->dpy, d, st->gc, 0, st->bitmap_h - st->yoff, st->bitmap_w, st->yoff);
245
slidescreen_draw_early (struct state *st)
247
while (st->early_i < 0)
253
/* for (early_i = 0; early_i < grid_size; early_i += pix_inc) */
210
255
XPoint points [3];
211
points[0].x = xoff + grid_size * hole_x;
212
points[0].y = yoff + grid_size * hole_y;
213
points[1].x = points[0].x + grid_size;
256
points[0].x = st->xoff + st->grid_size * st->hole_x;
257
points[0].y = st->yoff + st->grid_size * st->hole_y;
258
points[1].x = points[0].x + st->grid_size;
214
259
points[1].y = points[0].y;
215
260
points[2].x = points[0].x;
216
points[2].y = points[0].y + i;
217
XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
261
points[2].y = points[0].y + st->early_i;
262
XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
219
264
points[1].x = points[0].x;
220
points[1].y = points[0].y + grid_size;
221
points[2].x = points[0].x + i;
222
points[2].y = points[0].y + grid_size;
223
XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
265
points[1].y = points[0].y + st->grid_size;
266
points[2].x = points[0].x + st->early_i;
267
points[2].y = points[0].y + st->grid_size;
268
XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
225
points[0].x = points[1].x + grid_size;
270
points[0].x = points[1].x + st->grid_size;
226
271
points[0].y = points[1].y;
227
272
points[2].x = points[0].x;
228
points[2].y = points[0].y - i;
229
XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
273
points[2].y = points[0].y - st->early_i;
274
XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
231
276
points[1].x = points[0].x;
232
points[1].y = points[0].y - grid_size;
233
points[2].x = points[1].x - i;
277
points[1].y = points[0].y - st->grid_size;
278
points[2].x = points[1].x - st->early_i;
234
279
points[2].y = points[1].y;
235
XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
238
if (delay) usleep (delay);
280
XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
241
XFillRectangle (dpy, window, gc,
242
xoff + grid_size * hole_x,
243
yoff + grid_size * hole_y,
244
grid_size, grid_size);
283
st->early_i += st->pix_inc;
284
if (st->early_i < st->grid_size)
247
if (delay2) usleep (delay2);
287
XFillRectangle (st->dpy, st->window, st->gc,
288
st->xoff + st->grid_size * st->hole_x,
289
st->yoff + st->grid_size * st->hole_y,
290
st->grid_size, st->grid_size);
251
slide1 (Display *dpy, Window window)
296
slidescreen_draw (Display *dpy, Window window, void *closure)
298
struct state *st = (struct state *) closure;
299
int this_delay = st->delay;
253
301
/* this code is a total kludge, but who cares, it works... */
254
int rnd, i, x, y, ix, iy, dx, dy, dir, w, h, size, inc;
255
static int last = -1;
257
if (last == -1) last = random () % 2;
259
/* alternate between horizontal and vertical slides */
260
/* note that dir specifies the direction the _hole_ moves, not the tiles */
261
if (last == VERTICAL) {
262
if ((rnd = random () % (grid_w - 1)) < hole_x) {
263
dx = -1; dir = LEFT; hole_x -= rnd;
265
dx = 1; dir = RIGHT; rnd -= hole_x;
267
dy = 0; w = size = rnd + 1; h = 1;
270
if ((rnd = random () % (grid_h - 1)) < hole_y) {
271
dy = -1; dir = UP; hole_y -= rnd;
273
dy = 1; dir = DOWN; rnd -= hole_y;
275
dx = 0; h = size = rnd + 1; w = 1;
303
if (st->img_loader) /* still loading */
305
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
306
if (! st->img_loader) /* just finished */
311
if (! st->draw_initted)
313
if (!slidescreen_draw_early (st))
315
st->draw_initted = 1;
324
if (st->draw_last == -1) st->draw_last = random () % 2;
326
/* alternate between horizontal and vertical slides */
327
/* note that draw_dir specifies the direction the _hole_ moves, not the tiles */
328
if (st->draw_last == VERTICAL) {
329
if (((st->grid_w > 1) ? st->draw_rnd = random () % (st->grid_w - 1) : 0)
331
st->draw_dx = -1; st->draw_dir = LEFT; st->hole_x -= st->draw_rnd;
333
st->draw_dx = 1; st->draw_dir = RIGHT; st->draw_rnd -= st->hole_x;
335
st->draw_dy = 0; st->draw_w = st->draw_size = st->draw_rnd + 1; st->draw_h = 1;
336
st->draw_last = HORIZONTAL;
338
if (((st->grid_h > 1) ? st->draw_rnd = random () % (st->grid_h - 1) : 0)
340
st->draw_dy = -1; st->draw_dir = UP; st->hole_y -= st->draw_rnd;
342
st->draw_dy = 1; st->draw_dir = DOWN; st->draw_rnd -= st->hole_y;
344
st->draw_dx = 0; st->draw_h = st->draw_size = st->draw_rnd + 1; st->draw_w = 1;
345
st->draw_last = VERTICAL;
279
ix = x = xoff + (hole_x + dx) * grid_size;
280
iy = y = yoff + (hole_y + dy) * grid_size;
282
for (i = 0; i < grid_size; i += inc)
348
st->draw_ix = st->draw_x = st->xoff + (st->hole_x + st->draw_dx) * st->grid_size;
349
st->draw_iy = st->draw_y = st->yoff + (st->hole_y + st->draw_dy) * st->grid_size;
350
st->draw_inc = st->pix_inc;
354
/* for (draw_i = 0; draw_i < grid_size; draw_i += draw_inc) */
284
356
int fx, fy, tox, toy;
285
if (inc + i > grid_size)
290
fx = (x < 0 ? 0 : x > max_width ? max_width : x);
291
fy = (y < 0 ? 0 : y > max_height ? max_height : y);
292
tox = (tox < 0 ? 0 : tox > max_width ? max_width : tox);
293
toy = (toy < 0 ? 0 : toy > max_height ? max_height : toy);
295
XCopyArea (dpy, window, window, gc,
357
if (st->draw_inc + st->draw_i > st->grid_size)
358
st->draw_inc = st->grid_size - st->draw_i;
359
tox = st->draw_x - st->draw_dx * st->draw_inc;
360
toy = st->draw_y - st->draw_dy * st->draw_inc;
362
fx = (st->draw_x < 0 ? 0 : st->draw_x > st->max_width ? st->max_width : st->draw_x);
363
fy = (st->draw_y < 0 ? 0 : st->draw_y > st->max_height ? st->max_height : st->draw_y);
364
tox = (tox < 0 ? 0 : tox > st->max_width ? st->max_width : tox);
365
toy = (toy < 0 ? 0 : toy > st->max_height ? st->max_height : toy);
367
XCopyArea (st->dpy, st->window, st->window, st->gc,
297
grid_size * w, grid_size * h,
369
st->grid_size * st->draw_w, st->grid_size * st->draw_h,
372
st->draw_x -= st->draw_dx * st->draw_inc;
373
st->draw_y -= st->draw_dy * st->draw_inc;
374
switch (st->draw_dir)
304
case DOWN: XFillRectangle (dpy, window, gc,
305
ix, y + grid_size * h, grid_size * w, iy - y);
307
case LEFT: XFillRectangle (dpy, window, gc, ix, iy, x - ix, grid_size * h);
309
case UP: XFillRectangle (dpy, window, gc, ix, iy, grid_size * w, y - iy);
311
case RIGHT: XFillRectangle (dpy, window, gc,
312
x + grid_size * w, iy, ix - x, grid_size * h);
376
case DOWN: XFillRectangle (st->dpy, st->window, st->gc,
377
st->draw_ix, st->draw_y + st->grid_size * st->draw_h, st->grid_size * st->draw_w, st->draw_iy - st->draw_y);
379
case LEFT: XFillRectangle (st->dpy, st->window, st->gc, st->draw_ix, st->draw_iy, st->draw_x - st->draw_ix, st->grid_size * st->draw_h);
381
case UP: XFillRectangle (st->dpy, st->window, st->gc, st->draw_ix, st->draw_iy, st->grid_size * st->draw_w, st->draw_y - st->draw_iy);
383
case RIGHT: XFillRectangle (st->dpy, st->window, st->gc,
384
st->draw_x + st->grid_size * st->draw_w, st->draw_iy, st->draw_ix - st->draw_x, st->grid_size * st->draw_h);
317
if (delay) usleep (delay);
321
case DOWN: hole_y += size; break;
322
case LEFT: hole_x--; break;
323
case UP: hole_y--; break;
324
case RIGHT: hole_x += size; break;
389
st->draw_i += st->draw_inc;
390
if (st->draw_i >= st->grid_size)
394
switch (st->draw_dir)
396
case DOWN: st->hole_y += st->draw_size; break;
397
case LEFT: st->hole_x--; break;
398
case UP: st->hole_y--; break;
399
case RIGHT: st->hole_x += st->draw_size; break;
402
this_delay = st->delay2;
409
slidescreen_reshape (Display *dpy, Window window, void *closure,
410
unsigned int w, unsigned int h)
415
slidescreen_event (Display *dpy, Window window, void *closure, XEvent *event)
421
slidescreen_free (Display *dpy, Window window, void *closure)
423
struct state *st = (struct state *) closure;
424
XFreeGC (dpy, st->gc);
329
char *progclass = "SlidePuzzle";
331
char *defaults [] = {
430
static const char *slidescreen_defaults [] = {
332
431
"*dontClearRoot: True",
334
433
#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */