summaryrefslogtreecommitdiffstats
path: root/hacks/popsquares.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/popsquares.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/popsquares.c')
-rw-r--r--hacks/popsquares.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/hacks/popsquares.c b/hacks/popsquares.c
new file mode 100644
index 0000000..3b83fd7
--- /dev/null
+++ b/hacks/popsquares.c
@@ -0,0 +1,306 @@
+/* Copyright (c) 2003 Levi Burton <donburton@sbcglobal.net>
+ *
+ * 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.
+ */
+
+#include "screenhack.h"
+#include "colors.h"
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+# include "xdbe.h"
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+typedef struct _square {
+ int x, y, w, h;
+ int color;
+} square;
+
+static void
+randomize_square_colors(square *squares, int nsquares, int ncolors)
+{
+ int i;
+ square *s = squares;
+ for (i = 0; i < nsquares; i++)
+ s[i].color = random() % ncolors;
+}
+
+
+struct state {
+ Display *dpy;
+ Window window;
+
+ int delay, subdivisionx, subdivisiony, border, ncolors, twitch, dbuf;
+ XWindowAttributes xgwa;
+ GC gc;
+ XColor *colors;
+ int sw, sh, gw, gh, nsquares;
+ square *squares;
+ Pixmap b, ba, bb;
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ XdbeBackBuffer backb;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+};
+
+static void
+popsquares_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ int s = get_integer_resource(st->dpy, "subdivision", "Integer");
+ int x, y;
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+ if (st->xgwa.width < 100 || st->xgwa.height < 100) /* tiny window */
+ {
+ int ss = (st->xgwa.width < st->xgwa.height
+ ? st->xgwa.width : st->xgwa.height);
+ s = ss / 15;
+ if (s < 1) s = 1;
+ }
+
+ if (st->xgwa.width > st->xgwa.height * 5 || /* weird aspect ratio */
+ st->xgwa.height > st->xgwa.width * 5)
+ {
+ double r = st->xgwa.width / (double) st->xgwa.height;
+ if (r > 1)
+ {
+ st->subdivisiony = s;
+ st->subdivisionx = s * r;
+ }
+ else
+ {
+ st->subdivisionx = s;
+ st->subdivisiony = s / r;
+ }
+ }
+ else
+ {
+ st->subdivisionx = st->subdivisiony = s;
+ }
+
+ st->sw = st->xgwa.width / st->subdivisionx;
+ st->sh = st->xgwa.height / st->subdivisiony;
+ st->gw = st->sw ? st->xgwa.width / st->sw : 0;
+ st->gh = st->sh ? st->xgwa.height / st->sh : 0;
+ st->nsquares = st->gw * st->gh;
+ free (st->squares);
+ if (st->nsquares < 1) st->nsquares = 1;
+ st->squares = (square *) calloc (st->nsquares, sizeof(square));
+
+ for (y = 0; y < st->gh; y++)
+ for (x = 0; x < st->gw; x++)
+ {
+ square *s = (square *) &st->squares[st->gw * y + x];
+ s->w = st->sw;
+ s->h = st->sh;
+ s->x = x * st->sw;
+ s->y = y * st->sh;
+ }
+
+ randomize_square_colors(st->squares, st->nsquares, st->ncolors);
+
+ if (st->dbuf) {
+ XFreePixmap (dpy, st->ba);
+ XFreePixmap (dpy, st->bb);
+ st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+ st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+ st->b = st->ba;
+ }
+}
+
+static void *
+popsquares_init (Display *dpy, Window window)
+{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
+ int x, y;
+ double s1, v1, s2, v2 = 0;
+ int h1, h2 = 0;
+ /* Not sure how to use DBEClear */
+ /* Bool dbeclear_p = get_boolean_resource(dpy, "useDBEClear", "Boolean"); */
+ XColor fg, bg;
+ XGCValues gcv;
+
+ st->dpy = dpy;
+ st->window = window;
+
+ st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+ st->subdivisionx = get_integer_resource(st->dpy, "subdivision", "Integer");
+ st->subdivisiony = st->subdivisionx;
+ st->border = get_integer_resource(st->dpy, "border", "Integer");
+ st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
+ st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean");
+ st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");
+
+# ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */
+ st->dbuf = False;
+# endif
+
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+ fg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "foreground", "Foreground");
+ bg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background");
+
+ XQueryColor (st->dpy, st->xgwa.colormap, &fg);
+ XQueryColor (st->dpy, st->xgwa.colormap, &bg);
+
+ st->sw = st->xgwa.width / st->subdivisionx;
+ st->sh = st->xgwa.height / st->subdivisiony;
+ st->gw = st->sw ? st->xgwa.width / st->sw : 0;
+ st->gh = st->sh ? st->xgwa.height / st->sh : 0;
+ st->nsquares = st->gw * st->gh;
+ if (st->nsquares < 1) st->nsquares = 1;
+ if (st->ncolors < 1) st->ncolors = 1;
+
+ gcv.foreground = fg.pixel;
+ gcv.background = bg.pixel;
+ st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
+
+ st->colors = (XColor *) calloc (st->ncolors, sizeof(XColor));
+ st->squares = (square *) calloc (st->nsquares, sizeof(square));
+
+ rgb_to_hsv (fg.red, fg.green, fg.blue, &h1, &s1, &v1);
+ rgb_to_hsv (bg.red, bg.green, bg.blue, &h2, &s2, &v2);
+ make_color_ramp (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
+ h1, s1, v1,
+ h2, s2, v2,
+ st->colors, &st->ncolors, /* would this be considered a value-result argument? */
+ True, True, False);
+ if (st->ncolors < 2)
+ {
+ fprintf (stderr, "%s: insufficient colors!\n", progname);
+ exit (1);
+ }
+
+ for (y = 0; y < st->gh; y++)
+ for (x = 0; x < st->gw; x++)
+ {
+ square *s = (square *) &st->squares[st->gw * y + x];
+ s->w = st->sw;
+ s->h = st->sh;
+ s->x = x * st->sw;
+ s->y = y * st->sh;
+ }
+
+ randomize_square_colors(st->squares, st->nsquares, st->ncolors);
+
+ if (st->dbuf)
+ {
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
+ st->backb = st->b;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+ if (!st->b)
+ {
+ st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+ st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+ st->b = st->ba;
+ }
+ }
+ else
+ {
+ st->b = st->window;
+ }
+
+ popsquares_reshape (dpy, window, st, st->xgwa.width, st->xgwa.height);
+
+ return st;
+}
+
+static unsigned long
+popsquares_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ int x, y;
+ for (y = 0; y < st->gh; y++)
+ for (x = 0; x < st->gw; x++)
+ {
+ square *s = (square *) &st->squares[st->gw * y + x];
+ XSetForeground (st->dpy, st->gc, st->colors[s->color].pixel);
+ XFillRectangle (st->dpy, st->b, st->gc, s->x, s->y,
+ st->border ? s->w - st->border : s->w,
+ st->border ? s->h - st->border : s->h);
+ s->color++;
+ if (s->color == st->ncolors)
+ {
+ if (st->twitch && ((random() % 4) == 0))
+ randomize_square_colors (st->squares, st->nsquares, st->ncolors);
+ else
+ s->color = random() % st->ncolors;
+ }
+ }
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ if (st->backb)
+ {
+ XdbeSwapInfo info[1];
+ info[0].swap_window = st->window;
+ info[0].swap_action = XdbeUndefined;
+ XdbeSwapBuffers (st->dpy, info, 1);
+ }
+ else
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+ if (st->dbuf)
+ {
+ XCopyArea (st->dpy, st->b, st->window, st->gc, 0, 0,
+ st->xgwa.width, st->xgwa.height, 0, 0);
+ st->b = (st->b == st->ba ? st->bb : st->ba);
+ }
+
+ return st->delay;
+}
+
+
+static Bool
+popsquares_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+
+static void
+popsquares_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st);
+}
+
+
+static const char *popsquares_defaults [] = {
+ ".background: #0000FF",
+ ".foreground: #00008B",
+ "*delay: 25000",
+ "*subdivision: 5",
+ "*border: 1",
+ "*ncolors: 128",
+ "*twitch: False",
+ "*doubleBuffer: False",
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ "*useDBE: True",
+ "*useDBEClear: True",
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
+ 0
+};
+
+static XrmOptionDescRec popsquares_options [] = {
+ { "-fg", ".foreground", XrmoptionSepArg, 0},
+ { "-bg", ".background", XrmoptionSepArg, 0},
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-subdivision", ".subdivision", XrmoptionSepArg, 0 },
+ { "-border", ".border", XrmoptionSepArg, 0},
+ { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
+ { "-twitch", ".twitch", XrmoptionNoArg, "True" },
+ { "-no-twitch", ".twitch", XrmoptionNoArg, "False" },
+ { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
+ { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
+ { 0, 0, 0, 0 }
+};
+
+
+XSCREENSAVER_MODULE ("PopSquares", popsquares)