#define SHIFT_KY (0x04)
#define GRAV (0x08)
-char *progclass = "Munch";
-char *defaults [] = {
- ".background: black",
- ".foreground: white",
- "*delay: 5000",
- "*hold: 100000",
- "*clear: 50",
- "*logminwidth: 7",
- "*shift: True",
- "*xor: True",
- 0
-};
+struct state {
+ Display *dpy;
+ Window window;
-XrmOptionDescRec options [] = {
- { "-delay", ".delay", XrmoptionSepArg, 0 },
- { "-hold", ".hold", XrmoptionSepArg, 0 },
- { "-clear", ".clear", XrmoptionSepArg, "true" },
- { "-shift", ".shift", XrmoptionNoArg, "true" },
- { "-no-shift", ".shift", XrmoptionNoArg, "false" },
- { "-logminwidth", ".logminwidth", XrmoptionSepArg, 0 },
- { "-xor", ".xor", XrmoptionNoArg, "true" },
- { "-no-xor", ".xor", XrmoptionNoArg, "false" },
- { 0, 0, 0, 0 }
-};
+ GC gc;
+ int delay, hold, clear, logminwidth, shiftk, xor;
+ int logmaxwidth;
+ int maxwidth;
+ int randflags;
+ int thiswidth;
+ XWindowAttributes xgwa;
-static GC gc;
-/* only configurable things right now */
-static int delay, hold, clear, logminwidth, shiftk, xor;
+ int munch_t;
-static void munchOnce (Display* dpy, Window w,
- int width, /* pixels */
- int atX, int atY, /* pixels */
- int kX, int kT, int kY, /* pixels */
- int grav /* 0 or not */) {
+ int reset;
+ int atX, atY, kX, kT, kY, grav;
+ int square_count;
+};
- int x, y, t;
- static Colormap cmap;
- XWindowAttributes xgwa;
- XColor fgc;
- int drawX, drawY;
- /*
- fprintf(stderr,"Doing width %d at %d %d shift %d %d %d grav %d\n",
- width, atX, atY, kX, kT, kY, grav);
- */
-
- XGetWindowAttributes (dpy, w, &xgwa);
+static int munchOnce (struct state *st, int width)
+{
- if (!mono_p) {
- /* XXX there are probably bugs with this. */
- cmap = xgwa.colormap;
-
+ if (st->munch_t == 0) {
+ /*
+ fprintf(stderr,"Doing width %d at %d %d shift %d %d %d grav %d\n",
+ width, atX, atY, kX, kT, kY, grav);
+ */
+
+ if (!mono_p) {
+ XColor fgc;
fgc.red = random() % 65535;
fgc.green = random() % 65535;
fgc.blue = random() % 65535;
- if (XAllocColor(dpy, cmap, &fgc)) {
- XSetForeground(dpy, gc, fgc.pixel);
+ if (XAllocColor(st->dpy, st->xgwa.colormap, &fgc)) {
+ XSetForeground(st->dpy, st->gc, fgc.pixel);
}
+ }
}
/* Finally draw this munching square. */
- for(t = 0; t < width; t++) {
- for(x = 0; x < width; x++) {
- /* figure out the next point */
- y = ((x ^ ((t + kT) % width)) + kY) % width;
-
- drawX = ((x + kX) % width) + atX;
- drawY = (grav ? y + atY : atY + width - 1 - y);
-
- /* used to be bugs where it would draw partially offscreen.
- while that might be a pretty feature, I didn't want it to do
- that yet. if these trigger, please let me know.
- */
-/* assert(drawX >= 0 && drawX < xgwa.width);
- assert(drawY >= 0 && drawY < xgwa.height);
-*/
-
- XDrawPoint(dpy, w, gc, drawX, drawY);
- /* XXX may want to change this to XDrawPoints,
- but it's fast enough without it for the moment. */
+ /* for(munch_t = 0; munch_t < width; munch_t++) */
+ {
+ int x;
+ for(x = 0; x < width; x++) {
+ /* figure out the next point */
+ int y = ((x ^ ((st->munch_t + st->kT) % width)) + st->kY) % width;
+ int drawX = ((x + st->kX) % width) + st->atX;
+ int drawY = (st->grav ? y + st->atY : st->atY + width - 1 - y);
+
+ /* used to be bugs where it would draw partially offscreen.
+ while that might be a pretty feature, I didn'munch_t want it to do
+ that yet. if these trigger, please let me know.
+ */
+ /* assert(drawX >= 0 && drawX < xgwa.width);
+ assert(drawY >= 0 && drawY < xgwa.height);
+ */
+
+ XDrawPoint(st->dpy, st->window, st->gc, drawX, drawY);
+ /* 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);
- screenhack_handle_events (dpy);
- if (delay) usleep(delay);
+ }
+ }
+
+ st->munch_t++;
+ if (st->munch_t >= width) {
+ st->munch_t = 0;
+ return 1;
}
+
+ return 0;
}
/*
* 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++;
return r;
}
-/* This parses arguments, initializes the window, etc., and finally starts
- * calling munchOnce ad infinitum.
- */
-void
-screenhack (dpy, w) Display *dpy; Window w;
+static void *
+munch_init (Display *dpy, Window w)
{
- int logmaxwidth;
- int maxwidth;
- XWindowAttributes xgwa;
- Colormap cmap;
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
XGCValues gcv;
- int n = 0; /* number of squares before we have to clear */
- int randflags;
- int thiswidth;
+ st->dpy = dpy;
+ st->window = w;
+
/* get the dimensions of the window */
- XGetWindowAttributes (dpy, w, &xgwa);
+ XGetWindowAttributes (st->dpy, w, &st->xgwa);
/* We need a square; limit on screen size? */
/* we want a power of 2 for the width or the munch doesn't fill up.
*/
- logmaxwidth = (int)
- dumb_log_2(xgwa.height < xgwa.width ? xgwa.height : xgwa.width);
+ st->logmaxwidth = (int)
+ dumb_log_2(st->xgwa.height < st->xgwa.width ? st->xgwa.height : st->xgwa.width);
- maxwidth = 1 << logmaxwidth;
+ st->maxwidth = 1 << st->logmaxwidth;
- if (logmaxwidth < logminwidth) {
+ if (st->logmaxwidth < st->logminwidth) {
/* off-by-one error here? Anyone running on < 640x480? */
fprintf(stderr, "munch: screen too small; use -logminwidth\n");
fprintf(stderr, "\t(width is %d; log is %d; log must be at least "
"%d)\n",
- (xgwa.height < xgwa.width ? xgwa.height : xgwa.width),
- logmaxwidth, logminwidth);
+ (st->xgwa.height < st->xgwa.width ? st->xgwa.height : st->xgwa.width),
+ st->logmaxwidth, st->logminwidth);
exit(0);
}
/* 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, st->xgwa.colormap,
+ "foreground","Foreground");
+ gcv.background= get_pixel_resource(st->dpy, st->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;
- hold = get_integer_resource ("hold", "Integer");
- if (hold < 0) hold = 0;
+ st->hold = get_integer_resource (st->dpy, "hold", "Integer");
+ if (st->hold < 0) st->hold = 0;
- 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;
- logminwidth = get_integer_resource ("logminwidth", "Integer");
- if (logminwidth < 2) logminwidth = 2;
+ st->logminwidth = get_integer_resource (st->dpy, "logminwidth", "Integer");
+ if (st->logminwidth < 2) st->logminwidth = 2;
- shiftk = get_boolean_resource("shift", "Boolean");
+ st->shiftk = get_boolean_resource(st->dpy, "shift", "Boolean");
- xor = get_boolean_resource("xor", "Boolean");
+ st->xor = get_boolean_resource(st->dpy, "xor", "Boolean");
/* always draw xor on mono. */
- if (mono_p || xor) {
- XSetFunction(dpy, gc, GXxor);
+ if (mono_p || st->xor) {
+ XSetFunction(st->dpy, st->gc, GXxor);
}
- for(;;) {
- /* saves some calls to random. big deal */
- randflags = random();
+ st->reset = 1;
- /* choose size -- power of two */
- thiswidth = 1 << (logminwidth +
- (random() % (1 + logmaxwidth - logminwidth)));
+ return st;
+}
- munchOnce(dpy, w,
- thiswidth, /* Width, in pixels */
-
- /* draw at this location */
- (random() % (xgwa.width <= thiswidth ? 1
- : xgwa.width - thiswidth)),
- (random() % (xgwa.height <= thiswidth ? 1
- : xgwa.width - thiswidth)),
+static unsigned long
+munch_draw (Display *dpy, Window w, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ int this_delay = st->delay;
+
+ if (st->reset)
+ {
+ st->reset = 0;
+
+ this_delay = st->hold;
+ /* saves some calls to random. big deal */
+ st->randflags = random();
+
+ /* choose size -- power of two */
+ st->thiswidth = 1 << (st->logminwidth +
+ (random() % (1 + st->logmaxwidth - st->logminwidth)));
+
+ if (st->clear && ++st->square_count >= st->clear) {
+ XClearWindow(st->dpy, w);
+ st->square_count = 0;
+ }
+
+ /* draw at this location */
+ st->atX = (random() % (st->xgwa.width <= st->thiswidth ? 1
+ : st->xgwa.width - st->thiswidth));
+ st->atY = (random() % (st->xgwa.height <= st->thiswidth ? 1
+ : st->xgwa.width - st->thiswidth));
- /* wrap-around by these values; no need to %
- as we end up doing that later anyway*/
- ((shiftk && (randflags & SHIFT_KX))
- ? (random() % thiswidth) : 0),
- ((shiftk && (randflags & SHIFT_KT))
- ? (random() % thiswidth) : 0),
- ((shiftk && (randflags & SHIFT_KY))
- ? (random() % thiswidth) : 0),
+ /* wrap-around by these values; no need to %
+ as we end up doing that later anyway*/
+ st->kX = ((st->shiftk && (st->randflags & SHIFT_KX))
+ ? (random() % st->thiswidth) : 0);
+ st->kT = ((st->shiftk && (st->randflags & SHIFT_KT))
+ ? (random() % st->thiswidth) : 0);
+ st->kY = ((st->shiftk && (st->randflags & SHIFT_KY))
+ ? (random() % st->thiswidth) : 0);
- /* set the gravity of the munch, or rather,
- which direction we draw stuff in. */
- (randflags & GRAV)
- );
-
- screenhack_handle_events (dpy);
- if (hold) usleep(hold);
-
- if (clear && ++n >= clear) {
- XClearWindow(dpy, w);
- n = 0;
- }
+ /* set the gravity of the munch, or rather,
+ which direction we draw stuff in. */
+ st->grav = (st->randflags & GRAV);
}
+
+ if (munchOnce (st, st->thiswidth))
+ st->reset = 1;
+
+/* printf("%d\n",this_delay);*/
+ return this_delay;
}
+
+static void
+munch_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ st->xgwa.width = w;
+ st->xgwa.height = h;
+ st->logmaxwidth = (int)
+ dumb_log_2(st->xgwa.height < st->xgwa.width ? st->xgwa.height : st->xgwa.width);
+ st->maxwidth = 1 << st->logmaxwidth;
+}
+
+static Bool
+munch_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+
+static void
+munch_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st);
+}
+
+\f
+static const char *munch_defaults [] = {
+ ".background: black",
+ ".foreground: white",
+ "*fpsSolid: true",
+ "*delay: 10000",
+ "*hold: 100000",
+ "*clear: 50",
+ "*logminwidth: 7",
+ "*shift: True",
+ "*xor: True",
+ 0
+};
+
+static XrmOptionDescRec munch_options [] = {
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-hold", ".hold", XrmoptionSepArg, 0 },
+ { "-clear", ".clear", XrmoptionSepArg, "true" },
+ { "-shift", ".shift", XrmoptionNoArg, "true" },
+ { "-no-shift", ".shift", XrmoptionNoArg, "false" },
+ { "-logminwidth", ".logminwidth", XrmoptionSepArg, 0 },
+ { "-xor", ".xor", XrmoptionNoArg, "true" },
+ { "-no-xor", ".xor", XrmoptionNoArg, "false" },
+ { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("Munch", munch)