X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fdecayscreen.c;h=855d80a5e45dc819445d4219d838619fd7d18602;hp=d4b95f1c1b1d300625bcf9fb1a1d99f9a2f73ca2;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hpb=ccb7f4903325f92555a9722bba74b58346654ba0 diff --git a/hacks/decayscreen.c b/hacks/decayscreen.c index d4b95f1c..855d80a5 100644 --- a/hacks/decayscreen.c +++ b/hacks/decayscreen.c @@ -1,5 +1,4 @@ -/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997, 2005 - * Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -38,157 +37,177 @@ #include "screenhack.h" -static int sizex, sizey; -static int delay; -static GC gc; -static int mode; -static int iterations=100; - -#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 +struct state { + Display *dpy; + Window window; -static void -init_decay (Display *dpy, Window window) + int sizex, sizey; + int delay; + GC gc; + int mode; + int iterations; + + 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_init (Display *dpy, Window window) { + struct state *st = (struct state *) calloc (1, sizeof(*st)); XGCValues gcv; XWindowAttributes xgwa; long gcflags; unsigned long bg; - - char *s = get_string_resource("mode", "Mode"); - if (s && !strcmp(s, "shuffle")) mode = SHUFFLE; - else if (s && !strcmp(s, "up")) mode = UP; - else if (s && !strcmp(s, "left")) mode = LEFT; - else if (s && !strcmp(s, "right")) mode = RIGHT; - else if (s && !strcmp(s, "down")) mode = DOWN; - else if (s && !strcmp(s, "upleft")) mode = UPLEFT; - else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT; - else if (s && !strcmp(s, "upright")) mode = UPRIGHT; - else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT; - else if (s && !strcmp(s, "in")) mode = IN; - else if (s && !strcmp(s, "out")) mode = OUT; - else if (s && !strcmp(s, "melt")) mode = MELT; - else if (s && !strcmp(s, "stretch")) mode = STRETCH; - else if (s && !strcmp(s, "fuzz")) mode = FUZZ; + char *s; + + st->dpy = dpy; + st->window = window; + + 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); - mode = random() % (FUZZ+1); + st->mode = random() % (FUZZ+1); } - delay = get_integer_resource ("delay", "Integer"); + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); - if (delay < 0) delay = 0; + if (st->delay < 0) st->delay = 0; - XGetWindowAttributes (dpy, window, &xgwa); + XGetWindowAttributes (st->dpy, st->window, &xgwa); gcv.function = GXcopy; gcv.subwindow_mode = IncludeInferiors; + bg = get_pixel_resource (st->dpy, xgwa.colormap, "background", "Background"); + gcv.foreground = bg; - if (mode == MELT || mode == STRETCH) { - bg = get_pixel_resource ("background", "Background", dpy, xgwa.colormap); - gcv.foreground = bg; - } - - gcflags = GCForeground |GCFunction; - if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */ + gcflags = GCForeground | GCFunction; + if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */ gcflags |= GCSubwindowMode; - gc = XCreateGC (dpy, window, gcflags, &gcv); + st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv); - sizex = xgwa.width; - sizey = xgwa.height; + st->sizex = xgwa.width; + st->sizey = xgwa.height; - load_random_image (xgwa.screen, window, window, NULL, NULL); - - if (mode == MELT || mode == STRETCH) { - /* make sure screen eventually turns background color */ - XDrawLine(dpy, window, gc, 0, 0, sizex, 0); + if (st->mode == MELT || st->mode == STRETCH) + st->iterations = 1; /* slow down for smoother melting */ - /* slow down for smoother melting*/ - iterations = 1; - } + st->img_loader = load_image_async_simple (0, xgwa.screen, st->window, + st->window, 0, 0); + return st; } /* * perform one iteration of decay */ -static void -decay1 (Display *dpy, Window window) +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 int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D }; - static int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D }; - static int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D }; - static int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D }; - static int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D }; - - static int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D }; - static int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D }; - static int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D }; - static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D }; - static int *bias; - - switch (mode) { - case SHUFFLE: bias = no_bias; break; - case UP: bias = up_bias; break; - case LEFT: bias = left_bias; break; - case RIGHT: bias = right_bias; break; - case DOWN: bias = down_bias; break; - case UPLEFT: bias = upleft_bias; break; - case DOWNLEFT: bias = downleft_bias; break; - case UPRIGHT: bias = upright_bias; break; - case DOWNRIGHT: bias = downright_bias; break; - case IN: bias = no_bias; break; - case OUT: bias = no_bias; break; - case MELT: bias = no_bias; break; - case STRETCH: bias = no_bias; break; - case FUZZ: bias = no_bias; break; + 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 }; + + 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 */ + 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); + } + return st->delay; + } + + 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) (random() % (x)) - if (mode == MELT || mode == STRETCH) { - left = nrnd(sizex/2); - top = nrnd(sizey); - width = nrnd( sizex/2 ) + sizex/2 - left; - height = nrnd(sizey - top); + 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+1; - } else if (mode == FUZZ) { /* By Vince Levey ; + } else if (st->mode == FUZZ) { /* By Vince Levey ; inspired by the "melt" mode of the "scrhack" IrisGL program by Paul Haeberli circa 1991. */ - static int toggle = 0; - - left = nrnd(sizex - 1); - top = nrnd(sizey - 1); - toggle = !toggle; - if (toggle) + left = nrnd(st->sizex - 1); + top = nrnd(st->sizey - 1); + st->fuzz_toggle = !st->fuzz_toggle; + if (st->fuzz_toggle) { totop = top; height = 1; - toleft = nrnd(sizex - 1); + toleft = nrnd(st->sizex - 1); if (toleft > left) { width = toleft-left; @@ -206,7 +225,7 @@ decay1 (Display *dpy, Window window) { toleft = left; width = 1; - totop = nrnd(sizey - 1); + totop = nrnd(st->sizey - 1); if (totop > top) { height = totop-top; @@ -223,32 +242,32 @@ decay1 (Display *dpy, Window window) } else { - left = nrnd(sizex - 1); - top = nrnd(sizey); - width = nrnd(sizex - left); - height = nrnd(sizey - top); + left = nrnd(st->sizex - 1); + top = nrnd(st->sizey); + width = nrnd(st->sizex - left); + height = nrnd(st->sizey - top); toleft = left; totop = top; - if (mode == IN || mode == OUT) { + if (st->mode == IN || st->mode == OUT) { int x = left+(width/2); int y = top+(height/2); - int cx = sizex/2; - int cy = sizey/2; - if (mode == IN) { - if (x > cx && y > cy) bias = upleft_bias; - else if (x < cx && y > cy) bias = upright_bias; - else if (x < cx && y < cy) bias = downright_bias; - else /* (x > cx && y < cy)*/ bias = downleft_bias; + 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) bias = downright_bias; - else if (x < cx && y > cy) bias = downleft_bias; - else if (x < cx && y < cy) bias = upleft_bias; - else /* (x > cx && y < cy)*/ bias = upright_bias; + 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 (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) { + switch (st->current_bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) { case L: toleft = left-1; break; case R: toleft = left+1; break; case U: totop = top-1; break; @@ -257,21 +276,46 @@ decay1 (Display *dpy, Window window) } } - if (mode == STRETCH) { - XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1, - 0, sizey-top-1); + if (st->mode == STRETCH) { + XCopyArea (st->dpy, st->window, st->window, st->gc, 0, st->sizey-top-2, st->sizex, top+1, + 0, st->sizey-top-1); } else { - XCopyArea (dpy, window, window, gc, left, top, width, height, + 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; + st->sizex = w; + st->sizey = h; +} + +static Bool +decayscreen_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +decayscreen_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); } -char *progclass = "DecayScreen"; -char *defaults [] = { +static const char *decayscreen_defaults [] = { + ".background: Black", + ".foreground: Yellow", "*dontClearRoot: True", #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */ @@ -283,22 +327,11 @@ char *defaults [] = { 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec decayscreen_options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-mode", ".mode", XrmoptionSepArg, 0 }, { 0, 0, 0, 0 } }; -void -screenhack (Display *dpy, Window window) -{ - init_decay (dpy, window); - while (1) { - int i; - for (i = 0; i < iterations; i++) - decay1 (dpy, window); - XSync(dpy, False); - screenhack_handle_events (dpy); - if (delay) usleep (delay); - } -} + +XSCREENSAVER_MODULE ("DecayScreen", decayscreen)