http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / compass.c
index ed765a987c0bdeba36373344e09cf2af7445d6c2..5b9ba4990ec51febf325ae04183ec366d5bc14cf 100644 (file)
 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
 #define RANDSIGN() ((random() & 1) ? 1 : -1)
 
+struct state {
+  Display *dpy;
+  Window window;
+
+  int delay;
+  Bool dbuf;
+  struct disc *discs[4];
+  int x, y, size, size2;
+  GC ptr_gc;
+  GC erase_gc;
+  XWindowAttributes xgwa;
+  Pixmap b, ba, bb;    /* double-buffer to reduce flicker */
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  XdbeBackBuffer backb;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+};
+
+
+
 struct disc {
   int theta;           /* 0 - 360*64 */
   int velocity;
   int acceleration;
   int limit;
   GC gc;
-  void (*draw) (Display *, Drawable, struct disc *,
+  void (*draw) (struct state *, Drawable, struct disc *,
                 int x, int y, int radius);
 };
 
 
 static void
-draw_letters (Display *dpy, Drawable d, struct disc *disc,
+draw_letters (struct state *st, Drawable d, struct disc *disc,
               int x, int y, int radius)
 {
   XPoint points[50];
@@ -61,7 +80,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[4].x = x + radius * 0.8 * cos(th + 0.07);
   points[4].y = y + radius * 0.8 * sin(th + 0.07);
 
-  XDrawLines (dpy, d, disc->gc, points, 5, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 5, CoordModeOrigin);
 
   /* 30 (1) */
 
@@ -94,7 +113,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[8].x = x + radius * 0.72  * cos(th - 0.13);
   points[8].y = y + radius * 0.72  * sin(th - 0.13);
 
-  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
 
   /* 30 (2) */
 
@@ -118,7 +137,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
 
   points[6] = points[0];
 
-  XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin);
 
   /* 33 (1) */
 
@@ -151,7 +170,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[8].x = x + radius * 0.72  * cos(th - 0.13);
   points[8].y = y + radius * 0.72  * sin(th - 0.13);
 
-  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
 
   /* 33 (2) */
 
@@ -182,7 +201,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[8].x = x + radius * 0.72  * cos(th + 0.03);
   points[8].y = y + radius * 0.72  * sin(th + 0.03);
 
-  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
 
   /* N */
 
@@ -200,7 +219,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[3].x = x + radius * 0.8 * cos(th + 0.05);
   points[3].y = y + radius * 0.8 * sin(th + 0.05);
 
-  XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin);
 
   /* 3 */
 
@@ -233,7 +252,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[8].x = x + radius * 0.72  * cos(th - 0.05);
   points[8].y = y + radius * 0.72  * sin(th - 0.05);
 
-  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
 
   /* 6 */
 
@@ -266,7 +285,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[8].x = x + radius * 0.74 * cos(th - 0.05);
   points[8].y = y + radius * 0.74 * sin(th - 0.05);
 
-  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
 
 
   /* E */
@@ -294,7 +313,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[6].x = x + radius * 0.7 * cos(th + 0.05);
   points[6].y = y + radius * 0.7 * sin(th + 0.05);
 
-  XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin);
 
   /* 12 (1) */
 
@@ -309,7 +328,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[2].x = x + radius * 0.7  * cos(th - 0.03);
   points[2].y = y + radius * 0.7  * sin(th - 0.03);
 
-  XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin);
 
   /* 12 (2) */
 
@@ -337,7 +356,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[7].x = x + radius * 0.7  * cos(th + 0.13);
   points[7].y = y + radius * 0.7  * sin(th + 0.13);
 
-  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
 
   /* 15 (1) */
 
@@ -352,7 +371,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[2].x = x + radius * 0.7  * cos(th - 0.03);
   points[2].y = y + radius * 0.7  * sin(th - 0.03);
 
-  XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin);
 
   /* 15 (2) */
 
@@ -383,7 +402,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[8].x = x + radius * 0.72 * cos(th + 0.02);
   points[8].y = y + radius * 0.72 * sin(th + 0.02);
 
-  XDrawLines (dpy, d, disc->gc, points, 9, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 9, CoordModeOrigin);
 
   /* S */
 
@@ -413,7 +432,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[7].x = x + radius * 0.72  * cos(th - 0.05);
   points[7].y = y + radius * 0.72  * sin(th - 0.05);
 
-  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
 
   /* 21 (1) */
 
@@ -443,7 +462,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[7].x = x + radius * 0.7  * cos(th - 0.02);
   points[7].y = y + radius * 0.7  * sin(th - 0.02);
 
-  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
 
   /* 21 (2) */
 
@@ -456,7 +475,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[2].x = x + radius * 0.7  * cos(th + 0.06);
   points[2].y = y + radius * 0.7  * sin(th + 0.06);
 
-  XDrawLines (dpy, d, disc->gc, points, 3, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 3, CoordModeOrigin);
 
   /* 24 (1) */
 
@@ -486,7 +505,7 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[7].x = x + radius * 0.7  * cos(th - 0.02);
   points[7].y = y + radius * 0.7  * sin(th - 0.02);
 
-  XDrawLines (dpy, d, disc->gc, points, 8, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 8, CoordModeOrigin);
 
   /* 24 (2) */
 
@@ -502,12 +521,12 @@ draw_letters (Display *dpy, Drawable d, struct disc *disc,
   points[3].x = x + radius * 0.72 * cos(th + 0.13);
   points[3].y = y + radius * 0.72 * sin(th + 0.13);
 
-  XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin);
 }
 
 
 static void
-draw_ticks (Display *dpy, Drawable d, struct disc *disc,
+draw_ticks (struct state *st, Drawable d, struct disc *disc,
             int x, int y, int radius)
 {
   XSegment segs[72];
@@ -529,14 +548,14 @@ draw_ticks (Display *dpy, Drawable d, struct disc *disc,
       segs[i].x2 = x + radius2 * cos(th);
       segs[i].y2 = y + radius2 * sin(th);
     }
-  XDrawSegments (dpy, d, disc->gc, segs, countof(segs));
+  XDrawSegments (st->dpy, d, disc->gc, segs, countof(segs));
 
-  draw_letters (dpy, d, disc, x, y, radius);
+  draw_letters (st, d, disc, x, y, radius);
 }
 
 
 static void
-draw_thin_arrow (Display *dpy, Drawable d, struct disc *disc,
+draw_thin_arrow (struct state *st, Drawable d, struct disc *disc,
                  int x, int y, int radius)
 {
   XPoint points[3];
@@ -558,18 +577,18 @@ draw_thin_arrow (Display *dpy, Drawable d, struct disc *disc,
   points[2].x = x + radius2 * cos(th + tick);  /* tip right */
   points[2].y = y + radius2 * sin(th + tick);
 
-  XDrawLine (dpy, d, disc->gc,
+  XDrawLine (st->dpy, d, disc->gc,
              (int) (x + radius2 * cos(th)),
              (int) (y + radius2 * sin(th)),
              (int) (x + -radius * cos(th)),
              (int) (y + -radius * sin(th)));
 
-  XFillPolygon (dpy, d, disc->gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, d, disc->gc, points, 3, Convex, CoordModeOrigin);
 }
 
 
 static void
-draw_thick_arrow (Display *dpy, Drawable d, struct disc *disc,
+draw_thick_arrow (struct state *st, Drawable d, struct disc *disc,
                   int x, int y, int radius)
 {
   XPoint points[10];
@@ -593,7 +612,7 @@ draw_thick_arrow (Display *dpy, Drawable d, struct disc *disc,
 
   points[3] = points[0];
 
-  XDrawLines (dpy, d, disc->gc, points, 4, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 4, CoordModeOrigin);
 
   points[0].x = x + radius2 * cos(th - tick/2);         /* top left */
   points[0].y = y + radius2 * sin(th - tick/2);
@@ -615,7 +634,7 @@ draw_thick_arrow (Display *dpy, Drawable d, struct disc *disc,
   points[6].x = x + radius2 * cos(th + tick/2);  /* top right */
   points[6].y = y + radius2 * sin(th + tick/2);
 
-  XDrawLines (dpy, d, disc->gc, points, 7, CoordModeOrigin);
+  XDrawLines (st->dpy, d, disc->gc, points, 7, CoordModeOrigin);
 }
 
 
@@ -668,268 +687,287 @@ init_spin (struct disc *disc)
 
 
 static void
-draw_compass (Display *dpy, Drawable d, struct disc **discs,
-              int x, int y, int radius)
+draw_compass (struct state *st)
 {
   int i = 0;
-  while (discs[i])
+  while (st->discs[i])
     {
-      discs[i]->draw (dpy, d, discs[i], x, y, radius);
-      roll_disc (discs[i]);
+      st->discs[i]->draw (st, st->b, st->discs[i], st->x, st->y, st->size);
+      roll_disc (st->discs[i]);
       i++;
     }
 }
 
 static void
-draw_pointer (Display *dpy, Drawable d, GC ptr_gc, GC dot_gc,
-              int x, int y, int radius)
+draw_pointer (struct state *st)
 {
+  int radius = st->size;
+  GC dot_gc = st->discs[0]->gc;
   XPoint points[3];
   int size = radius * 0.1;
 
   /* top */
 
-  points[0].x = x - size;
-  points[0].y = y - radius - size;
+  points[0].x = st->x - size;
+  points[0].y = st->y - radius - size;
 
-  points[1].x = x + size;
-  points[1].y = y - radius - size;
+  points[1].x = st->x + size;
+  points[1].y = st->y - radius - size;
 
-  points[2].x = x;
-  points[2].y = y - radius;
+  points[2].x = st->x;
+  points[2].y = st->y - radius;
   
-  XFillPolygon (dpy, d, ptr_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, st->ptr_gc, points, 3, Convex, CoordModeOrigin);
 
   /* top right */
 
-  points[0].x = x - (radius * 0.85);
-  points[0].y = y - (radius * 0.8);
+  points[0].x = st->x - (radius * 0.85);
+  points[0].y = st->y - (radius * 0.8);
 
-  points[1].x = x - (radius * 1.1);
-  points[1].y = y - (radius * 0.55);
+  points[1].x = st->x - (radius * 1.1);
+  points[1].y = st->y - (radius * 0.55);
 
-  points[2].x = x - (radius * 0.6);
-  points[2].y = y - (radius * 0.65);
+  points[2].x = st->x - (radius * 0.6);
+  points[2].y = st->y - (radius * 0.65);
   
-  XFillPolygon (dpy, d, ptr_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, st->ptr_gc, points, 3, Convex, CoordModeOrigin);
 
   /* left */
 
-  points[0].x = x - (radius * 1.05);
-  points[0].y = y;
+  points[0].x = st->x - (radius * 1.05);
+  points[0].y = st->y;
 
-  points[1].x = x - (radius * 1.1);
-  points[1].y = y - (radius * 0.025);
+  points[1].x = st->x - (radius * 1.1);
+  points[1].y = st->y - (radius * 0.025);
 
-  points[2].x = x - (radius * 1.1);
-  points[2].y = y + (radius * 0.025);
+  points[2].x = st->x - (radius * 1.1);
+  points[2].y = st->y + (radius * 0.025);
   
-  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
 
   /* right */
 
-  points[0].x = x + (radius * 1.05);
-  points[0].y = y;
+  points[0].x = st->x + (radius * 1.05);
+  points[0].y = st->y;
 
-  points[1].x = x + (radius * 1.1);
-  points[1].y = y - (radius * 0.025);
+  points[1].x = st->x + (radius * 1.1);
+  points[1].y = st->y - (radius * 0.025);
 
-  points[2].x = x + (radius * 1.1);
-  points[2].y = y + (radius * 0.025);
+  points[2].x = st->x + (radius * 1.1);
+  points[2].y = st->y + (radius * 0.025);
   
-  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
 
   /* bottom */
 
-  points[0].x = x;
-  points[0].y = y + (radius * 1.05);
+  points[0].x = st->x;
+  points[0].y = st->y + (radius * 1.05);
 
-  points[1].x = x - (radius * 0.025);
-  points[1].y = y + (radius * 1.1);
+  points[1].x = st->x - (radius * 0.025);
+  points[1].y = st->y + (radius * 1.1);
 
-  points[2].x = x + (radius * 0.025);
-  points[2].y = y + (radius * 1.1);
+  points[2].x = st->x + (radius * 0.025);
+  points[2].y = st->y + (radius * 1.1);
   
-  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
 
   /* bottom left */
 
-  points[0].x = x + (radius * 0.74);
-  points[0].y = y + (radius * 0.74);
+  points[0].x = st->x + (radius * 0.74);
+  points[0].y = st->y + (radius * 0.74);
 
-  points[1].x = x + (radius * 0.78);
-  points[1].y = y + (radius * 0.75);
+  points[1].x = st->x + (radius * 0.78);
+  points[1].y = st->y + (radius * 0.75);
 
-  points[2].x = x + (radius * 0.75);
-  points[2].y = y + (radius * 0.78);
+  points[2].x = st->x + (radius * 0.75);
+  points[2].y = st->y + (radius * 0.78);
   
-  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
 
   /* top left */
 
-  points[0].x = x + (radius * 0.74);
-  points[0].y = y - (radius * 0.74);
+  points[0].x = st->x + (radius * 0.74);
+  points[0].y = st->y - (radius * 0.74);
 
-  points[1].x = x + (radius * 0.78);
-  points[1].y = y - (radius * 0.75);
+  points[1].x = st->x + (radius * 0.78);
+  points[1].y = st->y - (radius * 0.75);
 
-  points[2].x = x + (radius * 0.75);
-  points[2].y = y - (radius * 0.78);
+  points[2].x = st->x + (radius * 0.75);
+  points[2].y = st->y - (radius * 0.78);
   
-  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
 
   /* bottom right */
 
-  points[0].x = x - (radius * 0.74);
-  points[0].y = y + (radius * 0.74);
+  points[0].x = st->x - (radius * 0.74);
+  points[0].y = st->y + (radius * 0.74);
 
-  points[1].x = x - (radius * 0.78);
-  points[1].y = y + (radius * 0.75);
+  points[1].x = st->x - (radius * 0.78);
+  points[1].y = st->y + (radius * 0.75);
 
-  points[2].x = x - (radius * 0.75);
-  points[2].y = y + (radius * 0.78);
+  points[2].x = st->x - (radius * 0.75);
+  points[2].y = st->y + (radius * 0.78);
   
-  XFillPolygon (dpy, d, dot_gc, points, 3, Convex, CoordModeOrigin);
+  XFillPolygon (st->dpy, st->b, dot_gc, points, 3, Convex, CoordModeOrigin);
 }
 
-\f
-char *progclass = "Compass";
 
-char *defaults [] = {
-  ".background:                #000000",
-  ".foreground:                #DDFFFF",
-  "*arrow1Foreground:  #FFF66A",
-  "*arrow2Foreground:  #F7D64A",
-  "*pointerForeground: #FF0000",
-  "*delay:             20000",
-  "*doubleBuffer:      True",
-#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-  "*useDBE:            True",
-#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-  0
-};
-
-XrmOptionDescRec options [] = {
-  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
-  { "-db",             ".doubleBuffer", XrmoptionNoArg,  "True" },
-  { "-no-db",          ".doubleBuffer", XrmoptionNoArg,  "False" },
-  { 0, 0, 0, 0 }
-};
-
-void
-screenhack (Display *dpy, Window window)
+static void *
+compass_init (Display *dpy, Window window)
 {
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   XGCValues gcv;
-  int delay = get_integer_resource ("delay", "Integer");
-  Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean");
-  struct disc *discs[4];
-  int x, y, size, size2;
-  GC ptr_gc;
-  GC erase_gc = 0;
-  XWindowAttributes xgwa;
-  Pixmap b=0, ba=0, bb=0;      /* double-buffer to reduce flicker */
-#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-  XdbeBackBuffer backb = 0;
-#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+  st->dpy = dpy;
+  st->window = window;
+  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+  st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
+
+# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+  st->dbuf = False;
+# endif
 
-  XGetWindowAttributes (dpy, window, &xgwa);
-  size2 = MIN(xgwa.width, xgwa.height);
+  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+  st->size2 = MIN(st->xgwa.width, st->xgwa.height);
 
-  if (size2 > 600) size2 = 600;
+  if (st->size2 > 600) st->size2 = 600;
 
-  size = (size2 / 2) * 0.8;
+  st->size = (st->size2 / 2) * 0.8;
 
-  x = xgwa.width/2;
-  y = xgwa.height/2;
+  st->x = st->xgwa.width/2;
+  st->y = st->xgwa.height/2;
 
-  if (dbuf)
+  if (st->dbuf)
     {
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-      b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
+      st->b = st->backb = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
 
-      if (!b)
+      if (!st->b)
         {
-          x = size2/2;
-          y = size2/2;
-          ba = XCreatePixmap (dpy, window, size2, size2, xgwa.depth);
-          bb = XCreatePixmap (dpy, window, size2, size2, xgwa.depth);
-          b = ba;
+          st->x = st->size2/2;
+          st->y = st->size2/2;
+          st->ba = XCreatePixmap (st->dpy, st->window, st->size2, st->size2, st->xgwa.depth);
+          st->bb = XCreatePixmap (st->dpy, st->window, st->size2, st->size2, st->xgwa.depth);
+          st->b = st->ba;
         }
     }
   else
     {
-      b = window;
+      st->b = st->window;
     }
 
-  discs[0] = (struct disc *) calloc (1, sizeof (struct disc));
-  discs[1] = (struct disc *) calloc (1, sizeof (struct disc));
-  discs[2] = (struct disc *) calloc (1, sizeof (struct disc));
-  discs[3] = 0;
+  st->discs[0] = (struct disc *) calloc (1, sizeof (struct disc));
+  st->discs[1] = (struct disc *) calloc (1, sizeof (struct disc));
+  st->discs[2] = (struct disc *) calloc (1, sizeof (struct disc));
+  st->discs[3] = 0;
 
-  gcv.foreground = get_pixel_resource ("foreground", "Foreground",
-                                       dpy, xgwa.colormap);
-  gcv.line_width = MAX(2, (size/60));
+  gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                                       "foreground", "Foreground");
+  gcv.line_width = MAX(2, (st->size/60));
   gcv.join_style = JoinBevel;
-  discs[0]->draw = draw_ticks;
-  discs[0]->gc = XCreateGC (dpy, b, GCForeground|GCLineWidth|GCJoinStyle,
+  st->discs[0]->draw = draw_ticks;
+  st->discs[0]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth|GCJoinStyle,
                             &gcv);
-  init_spin (discs[0]);
-
-  gcv.foreground = get_pixel_resource ("arrow2Foreground", "Foreground",
-                                       dpy, xgwa.colormap);
-  gcv.line_width = MAX(4, (size / 30));
-  discs[1]->draw = draw_thick_arrow;
-  discs[1]->gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
-  init_spin (discs[1]);
-
-  gcv.foreground = get_pixel_resource ("arrow1Foreground", "Foreground",
-                                       dpy, xgwa.colormap);
-  gcv.line_width = MAX(4, (size / 30));
-  discs[2]->draw = draw_thin_arrow;
-  discs[2]->gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
-  init_spin (discs[2]);
-
-  gcv.foreground = get_pixel_resource ("pointerForeground", "Foreground",
-                                       dpy, xgwa.colormap);
-  ptr_gc = XCreateGC (dpy, b, GCForeground|GCLineWidth, &gcv);
-
-  gcv.foreground = get_pixel_resource ("background", "Background",
-                                       dpy, xgwa.colormap);
-  erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
-
-  if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, size2, size2);
-  if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, size2, size2);
-
-  while (1)
-    {
-      XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
+  init_spin (st->discs[0]);
+
+  gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                                       "arrow2Foreground", "Foreground");
+  gcv.line_width = MAX(4, (st->size / 30));
+  st->discs[1]->draw = draw_thick_arrow;
+  st->discs[1]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv);
+  init_spin (st->discs[1]);
+
+  gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                                       "arrow1Foreground", "Foreground");
+  gcv.line_width = MAX(4, (st->size / 30));
+  st->discs[2]->draw = draw_thin_arrow;
+  st->discs[2]->gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv);
+  init_spin (st->discs[2]);
+
+  gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                                       "pointerForeground", "Foreground");
+  st->ptr_gc = XCreateGC (st->dpy, st->b, GCForeground|GCLineWidth, &gcv);
+
+  gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
+                                       "background", "Background");
+  st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &gcv);
+
+  if (st->ba) XFillRectangle (st->dpy, st->ba, st->erase_gc, 0, 0, st->size2, st->size2);
+  if (st->bb) XFillRectangle (st->dpy, st->bb, st->erase_gc, 0, 0, st->size2, st->size2);
+
+  return st;
+}
+
+static unsigned long
+compass_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
 
-      draw_compass (dpy, b, discs, x, y, size);
-      draw_pointer (dpy, b, ptr_gc, discs[0]->gc, x, y, size);
+  draw_compass (st);
+  draw_pointer (st);
 
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-      if (backb)
-        {
-          XdbeSwapInfo info[1];
-          info[0].swap_window = window;
-          info[0].swap_action = XdbeUndefined;
-          XdbeSwapBuffers (dpy, info, 1);
-        }
-      else
+  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 (dbuf)
-        {
-          XCopyArea (dpy, b, window, erase_gc, 0, 0,
-                     size2, size2,
-                     xgwa.width/2 - x,
-                     xgwa.height/2 - y);
-          b = (b == ba ? bb : ba);
-        }
+    if (st->dbuf)
+      {
+        XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0,
+                   st->size2, st->size2,
+                   st->xgwa.width/2 - st->x,
+                   st->xgwa.height/2 - st->y);
+        st->b = (st->b == st->ba ? st->bb : st->ba);
+      }
+
+  return st->delay;
+}
 
-      XSync (dpy, False);
-      screenhack_handle_events (dpy);
-      if (delay)
-        usleep (delay);
-    }
+static void
+compass_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+compass_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
 }
+
+static void
+compass_free (Display *dpy, Window window, void *closure)
+{
+}
+
+\f
+
+static const char *compass_defaults [] = {
+  ".background:                #000000",
+  ".foreground:                #DDFFFF",
+  "*arrow1Foreground:  #FFF66A",
+  "*arrow2Foreground:  #F7D64A",
+  "*pointerForeground: #FF0000",
+  "*delay:             20000",
+  "*doubleBuffer:      True",
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  "*useDBE:            True",
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+  0
+};
+
+static XrmOptionDescRec compass_options [] = {
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-db",             ".doubleBuffer", XrmoptionNoArg,  "True" },
+  { "-no-db",          ".doubleBuffer", XrmoptionNoArg,  "False" },
+  { 0, 0, 0, 0 }
+};
+
+
+XSCREENSAVER_MODULE ("Compass", compass)