diff options
Diffstat (limited to 'hacks/decayscreen.c')
-rw-r--r-- | hacks/decayscreen.c | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/hacks/decayscreen.c b/hacks/decayscreen.c new file mode 100644 index 0000000..8b45af9 --- /dev/null +++ b/hacks/decayscreen.c @@ -0,0 +1,397 @@ +/* xscreensaver, Copyright (c) 1992-2018 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +/* decayscreen + * + * Based on slidescreen program from the xscreensaver application and the + * decay program for Sun framebuffers. This is the comment from the decay.c + * file: + + * decay.c + * find the screen bitmap for the console and make it "decay" by + * randomly shifting random rectangles by one pixelwidth at a time. + * + * by David Wald, 1988 + * rewritten by Natuerlich! + * based on a similar "utility" on the Apollo ring at Yale. + + * X version by + * + * Vivek Khera <khera@cs.duke.edu> + * 5-AUG-1993 + * + * Hacked by jwz, 28-Nov-97 (sped up and added new motion directions) + + * R. Schultz + * Added "melt" & "stretch" modes 28-Mar-1999 + * + */ + +#include "screenhack.h" +#include <time.h> + +struct state { + Display *dpy; + Window window; + XWindowAttributes xgwa; + Pixmap saved; + int saved_w, saved_h; + + int sizex, sizey; + int delay; + int duration; + GC gc; + int mode; + int random_p; + time_t start_time; + + int fuzz_toggle; + const int *current_bias; + + async_load_state *img_loader; +}; + + +#define SHUFFLE 0 +#define UP 1 +#define LEFT 2 +#define RIGHT 3 +#define DOWN 4 +#define UPLEFT 5 +#define DOWNLEFT 6 +#define UPRIGHT 7 +#define DOWNRIGHT 8 +#define IN 9 +#define OUT 10 +#define MELT 11 +#define STRETCH 12 +#define FUZZ 13 + +static void +decayscreen_load_image (struct state *st) +{ + XWindowAttributes xgwa; + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->sizex = xgwa.width; + st->sizey = xgwa.height; + if (st->img_loader) abort(); + + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); +} + +static void * +decayscreen_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XGCValues gcv; + long gcflags; + unsigned long bg; + char *s; + + st->dpy = dpy; + st->window = window; + st->random_p = 0; + + s = get_string_resource(st->dpy, "mode", "Mode"); + if (s && !strcmp(s, "shuffle")) st->mode = SHUFFLE; + else if (s && !strcmp(s, "up")) st->mode = UP; + else if (s && !strcmp(s, "left")) st->mode = LEFT; + else if (s && !strcmp(s, "right")) st->mode = RIGHT; + else if (s && !strcmp(s, "down")) st->mode = DOWN; + else if (s && !strcmp(s, "upleft")) st->mode = UPLEFT; + else if (s && !strcmp(s, "downleft")) st->mode = DOWNLEFT; + else if (s && !strcmp(s, "upright")) st->mode = UPRIGHT; + else if (s && !strcmp(s, "downright")) st->mode = DOWNRIGHT; + else if (s && !strcmp(s, "in")) st->mode = IN; + else if (s && !strcmp(s, "out")) st->mode = OUT; + else if (s && !strcmp(s, "melt")) st->mode = MELT; + else if (s && !strcmp(s, "stretch")) st->mode = STRETCH; + else if (s && !strcmp(s, "fuzz")) st->mode = FUZZ; + else { + if (s && *s && !!strcmp(s, "random")) + fprintf(stderr, "%s: unknown mode %s\n", progname, s); + st->random_p = 1; + st->mode = random() % (FUZZ+1); + } + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + + st->duration = get_integer_resource (st->dpy, "duration", "Seconds"); + if (st->duration < 1) st->duration = 1; + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + bg = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background"); + gcv.foreground = bg; + + gcflags = GCForeground | GCFunction; + if (use_subwindow_mode_p(st->xgwa.screen, st->window)) /* see grabscreen.c */ + gcflags |= GCSubwindowMode; + st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); + + st->start_time = time ((time_t *) 0); + decayscreen_load_image (st); + + return st; +} + + +/* + * perform one iteration of decay + */ +static unsigned long +decayscreen_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int left, top, width, height, toleft, totop; + +#define L 101 +#define R 102 +#define U 103 +#define D 104 + static const int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D }; + static const int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D }; + static const int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D }; + static const int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D }; + static const int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D }; + + static const int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D }; + static const int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D }; + static const int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D }; + static const int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D }; + + int off = 1; + if (st->sizex > 2560) off *= 2; /* Retina displays */ + + if (st->img_loader) /* still loading */ + { + st->img_loader = load_image_async_simple (st->img_loader, + 0, 0, 0, 0, 0); + if (! st->img_loader) { /* just finished */ + + st->start_time = time ((time_t *) 0); + if (st->random_p) + st->mode = random() % (FUZZ+1); + + if (st->mode == MELT || st->mode == STRETCH) + /* make sure screen eventually turns background color */ + XDrawLine (st->dpy, st->window, st->gc, 0, 0, st->sizex, 0); + + if (!st->saved) { + st->saved = XCreatePixmap (st->dpy, st->window, + st->sizex, st->sizey, + st->xgwa.depth); + st->saved_w = st->sizex; + st->saved_h = st->sizey; + } + XCopyArea (st->dpy, st->window, st->saved, st->gc, 0, 0, + st->sizex, st->sizey, 0, 0); + } + return st->delay; + } + + if (!st->img_loader && + st->start_time + st->duration < time ((time_t *) 0)) { + decayscreen_load_image (st); + } + + switch (st->mode) { + case SHUFFLE: st->current_bias = no_bias; break; + case UP: st->current_bias = up_bias; break; + case LEFT: st->current_bias = left_bias; break; + case RIGHT: st->current_bias = right_bias; break; + case DOWN: st->current_bias = down_bias; break; + case UPLEFT: st->current_bias = upleft_bias; break; + case DOWNLEFT: st->current_bias = downleft_bias; break; + case UPRIGHT: st->current_bias = upright_bias; break; + case DOWNRIGHT: st->current_bias = downright_bias; break; + case IN: st->current_bias = no_bias; break; + case OUT: st->current_bias = no_bias; break; + case MELT: st->current_bias = no_bias; break; + case STRETCH: st->current_bias = no_bias; break; + case FUZZ: st->current_bias = no_bias; break; + default: abort(); + } + +#define nrnd(x) ((x) ? random() % (x) : x) + + if (st->mode == MELT || st->mode == STRETCH) { + left = nrnd(st->sizex/2); + top = nrnd(st->sizey); + width = nrnd( st->sizex/2 ) + st->sizex/2 - left; + height = nrnd(st->sizey - top); + toleft = left; + totop = top+off; + + } else if (st->mode == FUZZ) { /* By Vince Levey <vincel@vincel.org>; + inspired by the "melt" mode of the + "scrhack" IrisGL program by Paul Haeberli + circa 1991. */ + left = nrnd(st->sizex - 1); + top = nrnd(st->sizey - 1); + st->fuzz_toggle = !st->fuzz_toggle; + if (st->fuzz_toggle) + { + totop = top; + height = off; + toleft = nrnd(st->sizex - 1); + if (toleft > left) + { + width = toleft-left; + toleft = left; + left++; + } + else + { + width = left-toleft; + left = toleft; + toleft++; + } + } + else + { + toleft = left; + width = off; + totop = nrnd(st->sizey - 1); + if (totop > top) + { + height = totop-top; + totop = top; + top++; + } + else + { + height = top-totop; + top = totop; + totop++; + } + } + + } else { + + left = nrnd(st->sizex - 1); + top = nrnd(st->sizey); + width = nrnd(st->sizex - left); + height = nrnd(st->sizey - top); + + toleft = left; + totop = top; + if (st->mode == IN || st->mode == OUT) { + int x = left+(width/2); + int y = top+(height/2); + int cx = st->sizex/2; + int cy = st->sizey/2; + if (st->mode == IN) { + if (x > cx && y > cy) st->current_bias = upleft_bias; + else if (x < cx && y > cy) st->current_bias = upright_bias; + else if (x < cx && y < cy) st->current_bias = downright_bias; + else /* (x > cx && y < cy)*/ st->current_bias = downleft_bias; + } else { + if (x > cx && y > cy) st->current_bias = downright_bias; + else if (x < cx && y > cy) st->current_bias = downleft_bias; + else if (x < cx && y < cy) st->current_bias = upleft_bias; + else /* (x > cx && y < cy)*/ st->current_bias = upright_bias; + } + } + + switch (st->current_bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) { + case L: toleft = left-off; break; + case R: toleft = left+off; break; + case U: totop = top-off; break; + case D: totop = top+off; break; + default: abort(); break; + } + } + + if (st->mode == STRETCH) { + XCopyArea (st->dpy, st->window, st->window, st->gc, + 0, st->sizey-top-off*2, st->sizex, top+off, + 0, st->sizey-top-off); + } else { + XCopyArea (st->dpy, st->window, st->window, st->gc, + left, top, width, height, + toleft, totop); + } + +#undef nrnd + + return st->delay; +} + +static void +decayscreen_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (! st->saved) return; /* Image might not be loaded yet */ + XClearWindow (st->dpy, st->window); + XCopyArea (st->dpy, st->saved, st->window, st->gc, + 0, 0, st->saved_w, st->saved_h, + ((int)w - st->saved_w) / 2, + ((int)h - st->saved_h) / 2); + st->sizex = w; + st->sizey = h; +} + +static Bool +decayscreen_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (screenhack_event_helper (dpy, window, event)) + { + st->start_time = 0; + return True; + } + return False; +} + +static void +decayscreen_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + + +static const char *decayscreen_defaults [] = { + ".background: Black", + ".foreground: Yellow", + "*dontClearRoot: True", + "*fpsSolid: True", + +#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ + "*visualID: Best", +#endif + + "*delay: 10000", + "*mode: random", + "*duration: 120", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", + "*rotateImages: True", +#endif + 0 +}; + +static XrmOptionDescRec decayscreen_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-duration", ".duration", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("DecayScreen", decayscreen) |