#include <math.h>
#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;
} 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++;
}
-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;
}
-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);
}
}
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)