1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* slip --- lots of slipping blits */
5 static const char sccsid[] = "@(#)slip.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1992 by Scott Draves <spot@cs.cmu.edu>
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
23 * 01-Nov-2000: Allocation checks
24 * 10-May-1997: Jamie Zawinski <jwz@jwz.org> compatible with xscreensaver
25 * 01-Dec-1995: Patched for VMS <joukj@hrem.stm.tudelft.nl>
30 # define DEFAULTS "*delay: 50000 \n" \
34 "*fpsSolid: true \n" \
35 "*ignoreRotation: True \n" \
37 # define refresh_slip 0
38 # include "xlockmore.h" /* in xscreensaver distribution */
39 #else /* STANDALONE */
40 # include "xlock.h" /* in xlockmore distribution */
41 #endif /* STANDALONE */
45 ENTRYPOINT ModeSpecOpt slip_opts =
46 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
49 ModStruct slip_description =
50 {"slip", "init_slip", "draw_slip", "release_slip",
51 "init_slip", "init_slip", (char *) NULL, &slip_opts,
52 50000, 35, 50, 1, 64, 1.0, "",
53 "Shows slipping blits", 0, NULL};
60 int blit_width, blit_height;
69 static slipstruct *slips = (slipstruct *) NULL;
72 halfrandom(slipstruct *sp, int mv)
81 sp->lasthalf = (short) (r >> 16);
87 erandom(slipstruct *sp, int mv)
95 res = (int) (sp->r & 0xf);
106 image_loaded_cb (Screen *screen, Window w, Drawable d,
107 const char *name, XRectangle *geom,
110 ModeInfo *mi = (ModeInfo *) closure;
111 slipstruct *sp = &slips[MI_SCREEN(mi)];
112 Display *dpy = DisplayOfScreen (screen);
113 XCopyArea (dpy, d, w, mi->gc, 0, 0,
114 sp->width, sp->height, 0, 0);
115 XFreePixmap (dpy, d);
116 sp->image_loading_p = False;
118 #endif /* STANDALONE */
121 prepare_screen(ModeInfo * mi, slipstruct * sp)
124 Display *display = MI_DISPLAY(mi);
126 int i, n, w = sp->width / 20;
127 int not_solid = halfrandom(sp, 10);
129 sp->backwards = (int) (LRAND() & 1); /* jwz: go the other way sometimes */
131 if (sp->first_time || !halfrandom(sp, 10)) {
135 if (halfrandom(sp, 5))
137 if (halfrandom(sp, 5))
143 if (MI_NPIXELS(mi) > 2)
144 XSetForeground(display, gc, MI_PIXEL(mi, halfrandom(sp, MI_NPIXELS(mi))));
145 else if (halfrandom(sp, 2))
146 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
148 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
150 for (i = 0; i < n; i++) {
151 int ww = ((w / 2) + halfrandom(sp, MAX(w, 1)));
154 if (MI_NPIXELS(mi) > 2)
155 XSetForeground(display, gc, MI_PIXEL(mi, halfrandom(sp, MI_NPIXELS(mi))));
156 else if (halfrandom(sp, 2))
157 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
159 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
161 XFillRectangle(display, MI_WINDOW(mi), gc,
162 halfrandom(sp, MAX(sp->width - ww, 1)),
163 halfrandom(sp, MAX(sp->height - ww, 1)),
169 #ifdef STANDALONE /* jwz -- sometimes hack the desktop image! */
170 if (!sp->image_loading_p &&
171 (1||halfrandom(sp, 2) == 0)) {
172 /* Load it into a pixmap so that the "Loading" message and checkerboard
173 don't show up on the window -- we keep running while the image is
175 Pixmap p = XCreatePixmap (MI_DISPLAY(mi), MI_WINDOW(mi),
176 sp->width, sp->height, mi->xgwa.depth);
177 sp->image_loading_p = True;
178 load_image_async (ScreenOfDisplay (MI_DISPLAY(mi), 0/*####MI_SCREEN(mi)*/),
179 MI_WINDOW(mi), p, image_loaded_cb, mi);
187 int i = (int) floor(d);
190 if ((LRAND() & 0xff) < f * 0xff)
196 reshape_slip (ModeInfo * mi, int w, int h)
198 slipstruct *sp = &slips[MI_SCREEN(mi)];
201 sp->blit_width = sp->width / 25;
202 sp->blit_height = sp->height / 25;
205 sp->nblits_remaining = 0;
209 init_slip (ModeInfo * mi)
214 if ((slips = (slipstruct *) calloc(MI_NUM_SCREENS(mi),
215 sizeof (slipstruct))) == NULL)
218 sp = &slips[MI_SCREEN(mi)];
220 sp->nblits_remaining = 0;
224 /* no "NoExpose" events from XCopyArea wanted */
225 XSetGraphicsExposures(MI_DISPLAY(mi), MI_GC(mi), False);
227 reshape_slip (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
231 draw_slip (ModeInfo * mi)
233 Display *display = MI_DISPLAY(mi);
234 Window window = MI_WINDOW(mi);
241 sp = &slips[MI_SCREEN(mi)];
243 timer = MI_COUNT(mi) * MI_CYCLES(mi);
245 MI_IS_DRAWN(mi) = True;
248 int xi = halfrandom(sp, MAX(sp->width - sp->blit_width, 1));
249 int yi = halfrandom(sp, MAX(sp->height - sp->blit_height, 1));
250 double x, y, dx = 0, dy = 0, t, s1, s2;
252 if (0 == sp->nblits_remaining--) {
253 static const int lut[] = {0, 0, 0, 1, 1, 1, 2};
255 prepare_screen(mi, sp);
256 sp->nblits_remaining = MI_COUNT(mi) *
257 (2000 + halfrandom(sp, 1000) + halfrandom(sp, 1000));
259 sp->mode = halfrandom(sp, 2);
261 sp->mode = lut[halfrandom(sp, 7)];
263 x = (2 * xi + sp->blit_width) / (double) sp->width - 1;
264 y = (2 * yi + sp->blit_height) / (double) sp->height - 1;
266 /* (x,y) is in biunit square */
282 t = dx * dx + dy * dy + 1e-10;
283 s1 = 2 * dx * dx / t - 1;
284 s2 = 2 * dx * dy / t;
288 if (sp->backwards) { /* jwz: go the other way sometimes */
293 case 1: /* shuffle */
297 case 2: /* explode */
303 int qx = xi + quantize(dx), qy = yi + quantize(dy);
306 if (qx < 0 || qy < 0 ||
307 qx >= sp->width - sp->blit_width ||
308 qy >= sp->height - sp->blit_height)
312 Seems to cause problems using Exceed
314 X Error of failed request: BadGC (invalid GC parameter)
316 X Error of failed request: BadDrawable (invalid Pixmap or Window parameter)
317 Major opcode of failed request: 62 (X_CopyArea)
319 XCopyArea(display, window, window, gc, xi, yi,
320 sp->blit_width, sp->blit_height,
325 wrap = sp->width - (2 * sp->blit_width);
327 XCopyArea(display, window, window, gc, qx, qy,
328 sp->blit_width, sp->blit_height,
331 if (qx < 2 * sp->blit_width) {
332 XCopyArea(display, window, window, gc, qx, qy,
333 sp->blit_width, sp->blit_height,
336 wrap = sp->height - (2 * sp->blit_height);
338 XCopyArea(display, window, window, gc, qx, qy,
339 sp->blit_width, sp->blit_height,
342 if (qy < 2 * sp->blit_height) {
343 XCopyArea(display, window, window, gc, qx, qy,
344 sp->blit_width, sp->blit_height,
357 release_slip (ModeInfo * mi)
360 (void) free((void *) slips);
361 slips = (slipstruct *) NULL;
366 slip_handle_event (ModeInfo *mi, XEvent *event)
368 slipstruct *sp = &slips[MI_SCREEN(mi)];
369 if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
372 sp->nblits_remaining = 0;
378 XSCREENSAVER_MODULE ("Slip", slip)
380 #endif /* MODE_slip */