X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fmismunch.c;h=cda0a0b0e523712a509f93c1ff9f54aa2acbc5c4;hp=0283f93840003d2d8e1010d0775a077cdafd2f09;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hpb=ccb7f4903325f92555a9722bba74b58346654ba0 diff --git a/hacks/mismunch.c b/hacks/mismunch.c index 0283f938..cda0a0b0 100644 --- a/hacks/mismunch.c +++ b/hacks/mismunch.c @@ -22,33 +22,6 @@ #include #include "screenhack.h" -char *progclass = "Mismunch"; - -char *defaults [] = { - ".background: black", - ".foreground: white", - "*delay: 2500", - "*simul: 5", - "*clear: 65", - "*xor: True", - 0 -}; - -XrmOptionDescRec options [] = { - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { "-simul", ".simul", XrmoptionSepArg, 0 }, - { "-clear", ".clear", XrmoptionSepArg, "true" }, - { "-xor", ".xor", XrmoptionNoArg, "true" }, - { "-no-xor", ".xor", XrmoptionNoArg, "false" }, - { 0, 0, 0, 0 } -}; - - -static GC gc; -static int delay, simul, clear, xor; -static int logminwidth, logmaxwidth; -static int restart, window_width, window_height; - typedef struct _muncher { int width; int atX, atY; @@ -62,11 +35,28 @@ typedef struct _muncher { } muncher; +struct state { + Display *dpy; + Window window; + + GC gc; + int delay, simul, clear, xor; + int logminwidth, logmaxwidth; + int restart, window_width, window_height; + + int draw_n; /* number of squares before we have to clear */ + int draw_i; + + muncher **munchers; +}; + + /* * dumb way to get # of digits in number. Probably faster than actually * doing a log and a division, maybe. */ -static int dumb_log_2(int k) { +static int dumb_log_2(int k) +{ int r = -1; while (k > 0) { k >>= 1; r++; @@ -75,66 +65,45 @@ static int dumb_log_2(int k) { } -void calc_logwidths (void) { +static void calc_logwidths (struct state *st) +{ /* Choose a range of square sizes based on the window size. We want a power of 2 for the square width or the munch doesn't fill up. Also, if a square doesn't fit inside an area 20% smaller than the window, it's too big. Mismunched squares that big make things look too noisy. */ - if (window_height < window_width) { - logmaxwidth = (int)dumb_log_2(window_height * 0.8); + if (st->window_height < st->window_width) { + st->logmaxwidth = (int)dumb_log_2(st->window_height * 0.8); } else { - logmaxwidth = (int)dumb_log_2(window_width * 0.8); + st->logmaxwidth = (int)dumb_log_2(st->window_width * 0.8); } - if (logmaxwidth < 2) { - logmaxwidth = 2; + if (st->logmaxwidth < 2) { + st->logmaxwidth = 2; } /* we always want three sizes of squares */ - logminwidth = logmaxwidth - 2; + st->logminwidth = st->logmaxwidth - 2; - if (logminwidth < 2) { - logminwidth = 2; + if (st->logminwidth < 2) { + st->logminwidth = 2; } } -void mismunch_handle_events (Display *dpy) { - XEvent e; - - while (XPending(dpy)) { - XNextEvent(dpy, &e); - - switch (e.type) { - case ConfigureNotify: - if (e.xconfigure.width != window_width || - e.xconfigure.height != window_height) { - window_width = e.xconfigure.width; - window_height = e.xconfigure.height; - calc_logwidths(); - restart = 1; - } - break; - default: - screenhack_handle_event(dpy, &e); - } - } -} - - -static muncher *make_muncher (Display *dpy, Window w) { +static muncher *make_muncher (struct state *st) +{ int logwidth; XWindowAttributes xgwa; muncher *m = (muncher *) malloc(sizeof(muncher)); - XGetWindowAttributes(dpy, w, &xgwa); + XGetWindowAttributes(st->dpy, st->window, &xgwa); /* choose size -- power of two */ - logwidth = (logminwidth + - (random() % (1 + logmaxwidth - logminwidth))); + logwidth = (st->logminwidth + + (random() % (1 + st->logmaxwidth - st->logminwidth))); m->width = 1 << logwidth; @@ -213,23 +182,21 @@ static muncher *make_muncher (Display *dpy, Window w) { } -static void munch (Display *dpy, Window w, muncher *m) { +static void munch (struct state *st, muncher *m) +{ int drawX, drawY; XWindowAttributes xgwa; - static Colormap cmap; if (m->done) { return; } - XGetWindowAttributes(dpy, w, &xgwa); + XGetWindowAttributes(st->dpy, st->window, &xgwa); if (!mono_p) { /* XXX there are probably bugs with this. */ - cmap = xgwa.colormap; - - if (XAllocColor(dpy, cmap, &m->fgc)) { - XSetForeground(dpy, gc, m->fgc.pixel); + if (XAllocColor(st->dpy, xgwa.colormap, &m->fgc)) { + XSetForeground(st->dpy, st->gc, m->fgc.pixel); } } @@ -251,111 +218,159 @@ static void munch (Display *dpy, Window w, muncher *m) { drawX = ((m->x + m->kX) % m->width) + m->atX; drawY = (m->grav ? m->y + m->atY : m->atY + m->width - 1 - m->y); - XDrawPoint(dpy, w, gc, drawX, drawY); + XDrawPoint(st->dpy, st->window, st->gc, drawX, drawY); if ((m->xshadow != 0) || (m->yshadow != 0)) { /* draw the corresponding shadow point */ - XDrawPoint(dpy, w, gc, drawX + m->xshadow, drawY + m->yshadow); + XDrawPoint(st->dpy, st->window, st->gc, drawX + m->xshadow, drawY + m->yshadow); } /* XXX may want to change this to XDrawPoints, but it's fast enough without it for the moment. */ } - /* - we've drawn one pass' worth of points. let the server catch up or - this won't be interesting to watch at all. we call this here in - the hopes of having one whole sequence of dots appear at the same - time (one for each value of x, surprisingly enough) - */ - XSync(dpy, False); - mismunch_handle_events(dpy); - - if (delay) usleep(delay); - m->t++; if (m->t > m->doom) { m->done = 1; - return; } - - return; } -void screenhack (Display *dpy, Window w) +static void * +mismunch_init (Display *dpy, Window w) { + struct state *st = (struct state *) calloc (1, sizeof(*st)); XWindowAttributes xgwa; - Colormap cmap; XGCValues gcv; - int n = 0; /* number of squares before we have to clear */ - muncher **munchers; int i; - restart = 0; + st->dpy = dpy; + st->window = w; + st->restart = 0; /* get the dimensions of the window */ - XGetWindowAttributes(dpy, w, &xgwa); + XGetWindowAttributes(st->dpy, w, &xgwa); /* create the gc */ - cmap = xgwa.colormap; - gcv.foreground= get_pixel_resource("foreground","Foreground", - dpy, cmap); - gcv.background= get_pixel_resource("background","Background", - dpy, cmap); + gcv.foreground= get_pixel_resource(st->dpy, xgwa.colormap, + "foreground","Foreground"); + gcv.background= get_pixel_resource(st->dpy, xgwa.colormap, + "background","Background"); - gc = XCreateGC(dpy, w, GCForeground|GCBackground, &gcv); + st->gc = XCreateGC(st->dpy, w, GCForeground|GCBackground, &gcv); - delay = get_integer_resource("delay", "Integer"); - if (delay < 0) delay = 0; + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; - simul = get_integer_resource("simul", "Integer"); - if (simul < 1) simul = 1; + st->simul = get_integer_resource(st->dpy, "simul", "Integer"); + if (st->simul < 1) st->simul = 1; - clear = get_integer_resource("clear", "Integer"); - if (clear < 0) clear = 0; + st->clear = get_integer_resource(st->dpy, "clear", "Integer"); + if (st->clear < 0) st->clear = 0; - xor = get_boolean_resource("xor", "Boolean"); + st->xor = get_boolean_resource(st->dpy, "xor", "Boolean"); - window_width = xgwa.width; - window_height = xgwa.height; + st->window_width = xgwa.width; + st->window_height = xgwa.height; - calc_logwidths(); + calc_logwidths(st); /* always draw xor on mono. */ - if (mono_p || xor) { - XSetFunction(dpy, gc, GXxor); + if (mono_p || st->xor) { + XSetFunction(st->dpy, st->gc, GXxor); } - munchers = (muncher **) calloc(simul, sizeof(muncher *)); - for (i = 0; i < simul; i++) { - munchers[i] = make_muncher(dpy, w); + st->munchers = (muncher **) calloc(st->simul, sizeof(muncher *)); + for (i = 0; i < st->simul; i++) { + st->munchers[i] = make_muncher(st); } - for(;;) { - for (i = 0; i < simul; i++) { - munch(dpy, w, munchers[i]); + return st; +} - if (munchers[i]->done) { - n++; +static unsigned long +mismunch_draw (Display *dpy, Window w, void *closure) +{ + struct state *st = (struct state *) closure; - free(munchers[i]); - munchers[i] = make_muncher(dpy, w); + /* for (draw_i = 0; draw_i < simul; draw_i++) */ + { + munch(st, st->munchers[st->draw_i]); - mismunch_handle_events(dpy); - } + if (st->munchers[st->draw_i]->done) { + st->draw_n++; + + free(st->munchers[st->draw_i]); + st->munchers[st->draw_i] = make_muncher(st); } + } - if (restart || (clear && n >= clear)) { - for (i = 0; i < simul; i++) { - free(munchers[i]); - munchers[i] = make_muncher(dpy, w); + st->draw_i++; + if (st->draw_i >= st->simul) { + int i = 0; + st->draw_i = 0; + if (st->restart || (st->clear && st->draw_n >= st->clear)) { + for (i = 0; i < st->simul; i++) { + free(st->munchers[i]); + st->munchers[i] = make_muncher(st); } - XClearWindow(dpy, w); - n = 0; - restart = 0; + XClearWindow(st->dpy, w); + st->draw_n = 0; + st->restart = 0; } + } - XSync(dpy, False); + return st->delay; +} + + +static void +mismunch_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (w != st->window_width || + h != st->window_height) { + st->window_width = w; + st->window_height = h; + calc_logwidths(st); + st->restart = 1; + st->draw_i = 0; } } + +static Bool +mismunch_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +mismunch_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *mismunch_defaults [] = { + ".background: black", + ".foreground: white", + "*delay: 2500", + "*simul: 5", + "*clear: 65", + "*xor: True", + 0 +}; + +static XrmOptionDescRec mismunch_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-simul", ".simul", XrmoptionSepArg, 0 }, + { "-clear", ".clear", XrmoptionSepArg, "true" }, + { "-xor", ".xor", XrmoptionNoArg, "true" }, + { "-no-xor", ".xor", XrmoptionNoArg, "false" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Mismunch", mismunch)