-/* xscreensaver, Copyright (c) 1992-1997 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1992-2018 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
*/
#include "screenhack.h"
+#include "pow2.h"
+#include "ximage-loader.h"
#include <stdio.h>
+#include <time.h>
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# ifndef PIXEL_ALREADY_TYPEDEFED
-# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
-# endif
-#endif
+#include "images/gen/som_png.h"
+
+/* Implementing this using XCopyArea doesn't work with color images on OSX.
+ This means that the Cocoa implementation of XCopyArea in jwxyz.m is
+ broken with the GXor, GXand, and/or the GXxor GC operations. This
+ probably means that (e.g.) "kCGBlendModeDarken" is not close enough
+ to being "GXand" to use for that. (It works with monochrome images,
+ just not color ones).
-#ifdef HAVE_XMU
-# ifndef VMS
-# include <X11/Xmu/Drawing.h>
-#else /* VMS */
-# include <Xmu/Drawing.h>
-# endif /* VMS */
+ So, on OSX, we implement the blitter by hand. It is correct, but
+ orders of magnitude slower.
+ */
+#ifndef HAVE_JWXYZ
+# define USE_XCOPYAREA
#endif
-#include "default.xbm"
+struct state {
+ Display *dpy;
+ Window window;
+ XWindowAttributes xgwa;
+ int width, height, size;
+ Bool scale_up;
+ Pixmap self, temp, mask;
+# ifdef USE_XCOPYAREA
+ GC gc_set, gc_clear, gc_copy, gc_and, gc_or, gc_xor;
+# endif
+ GC gc;
+ int delay, delay2;
+ int duration;
+ Pixmap bitmap;
+ unsigned int fg, bg;
-static Display *dpy;
-static Window window;
-static unsigned int size;
-static Pixmap self, temp, mask;
-static GC SET, CLR, CPY, IOR, AND, XOR;
-static GC gc;
-static int delay, delay2;
-static Pixmap bitmap;
-static int depth;
-static unsigned int fg, bg;
+ int qwad; /* fuckin' C, man... who needs namespaces? */
+ int first_time;
+ int last_w, last_h;
+
+ time_t start_time;
+ Bool loaded_p;
+ Bool load_ext_p;
+ async_load_state *img_loader;
+};
-static void display (Pixmap);
+static void display (struct state *, Pixmap);
+static void blitspin_init_2 (struct state *);
-#define copy_all_to(from, xoff, yoff, to, gc) \
- XCopyArea (dpy, (from), (to), (gc), 0, 0, \
- size-(xoff), size-(yoff), (xoff), (yoff))
+#define copy_to(from, xoff, yoff, to, op) \
+ bitblt (st, st->from, st->to, op, 0, 0, \
+ st->size-(xoff), st->size-(yoff), (xoff), (yoff))
-#define copy_all_from(to, xoff, yoff, from, gc) \
- XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff), \
- size-(xoff), size-(yoff), 0, 0)
+#define copy_from(to, xoff, yoff, from, op) \
+ bitblt (st, st->from, st->to, op, (xoff), (yoff), \
+ st->size-(xoff), st->size-(yoff), 0, 0)
+
+
+#ifdef USE_XCOPYAREA
+# define bitblt(st, from, to, op, src_x, src_y, w, h, dst_x, dst_y) \
+ XCopyArea((st)->dpy, (from), (to), (st)->gc_##op, \
+ (src_x), (src_y), (w), (h), (dst_x), (dst_y))
+#else /* !USE_XCOPYAREA */
+
+# define bitblt(st, from, to, op, src_x, src_y, w, h, dst_x, dst_y) \
+ do_bitblt((st)->dpy, (from), (to), st->gc, GX##op, \
+ (src_x), (src_y), (w), (h), (dst_x), (dst_y))
static void
-rotate (void)
+do_bitblt (Display *dpy, Drawable src, Drawable dst, GC gc, int op,
+ int src_x, int src_y,
+ unsigned int width, unsigned int height,
+ int dst_x, int dst_y)
{
- int qwad; /* fuckin' C, man... who needs namespaces? */
- XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
- XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
- for (qwad = size>>1; qwad > 0; qwad>>=1)
+ if (op == GXclear)
+ {
+ XSetForeground (dpy, gc, 0xFF000000); /* ARGB black for Cocoa */
+ XFillRectangle (dpy, dst, gc, dst_x, dst_y, width, height);
+ }
+ else if (op == GXset)
+ {
+ XSetForeground (dpy, gc, ~0L);
+ XFillRectangle (dpy, dst, gc, dst_x, dst_y, width, height);
+ }
+ else if (op == GXcopy)
{
- if (delay) usleep (delay);
- copy_all_to (mask, 0, 0, temp, CPY); /* 1 */
- copy_all_to (mask, 0, qwad, temp, IOR); /* 2 */
- copy_all_to (self, 0, 0, temp, AND); /* 3 */
- copy_all_to (temp, 0, 0, self, XOR); /* 4 */
- copy_all_from (temp, qwad, 0, self, XOR); /* 5 */
- copy_all_from (self, qwad, 0, self, IOR); /* 6 */
- copy_all_to (temp, qwad, 0, self, XOR); /* 7 */
- copy_all_to (self, 0, 0, temp, CPY); /* 8 */
- copy_all_from (temp, qwad, qwad, self, XOR); /* 9 */
- copy_all_to (mask, 0, 0, temp, AND); /* A */
- copy_all_to (temp, 0, 0, self, XOR); /* B */
- copy_all_to (temp, qwad, qwad, self, XOR); /* C */
- copy_all_from (mask, qwad>>1, qwad>>1, mask, AND); /* D */
- copy_all_to (mask, qwad, 0, mask, IOR); /* E */
- copy_all_to (mask, 0, qwad, mask, IOR); /* F */
- display (self);
+ XCopyArea (dpy, src, dst, gc, src_x, src_y, width, height, dst_x, dst_y);
+ }
+ else
+ {
+ XImage *srci = XGetImage (dpy, src, src_x, src_y, width, height,
+ ~0L, ZPixmap);
+ XImage *dsti = XGetImage (dpy, dst, dst_x, dst_y, width, height,
+ ~0L, ZPixmap);
+ unsigned long *out = (unsigned long *) dsti->data;
+ unsigned long *in = (unsigned long *) srci->data;
+ unsigned long *end = (in + (height * srci->bytes_per_line
+ / sizeof(unsigned long)));
+ switch (op)
+ {
+ case GXor: while (in < end) { *out++ |= *in++; } break;
+ case GXand: while (in < end) { *out++ &= *in++; } break;
+ case GXxor: while (in < end) { *out++ ^= *in++; } break;
+ default: abort();
+ }
+ XPutImage (dpy, dst, gc, dsti, 0, 0, dst_x, dst_y, width, height);
+ XDestroyImage (srci);
+ XDestroyImage (dsti);
}
}
-static void
-read_bitmap (char *bitmap_name, int *widthP, int *heightP)
-{
-#ifdef HAVE_XPM
- XWindowAttributes xgwa;
- XpmAttributes xpmattrs;
- int result;
- xpmattrs.valuemask = 0;
- bitmap = 0;
+#endif /* !USE_XCOPYAREA */
- XGetWindowAttributes (dpy, window, &xgwa);
-# ifdef XpmCloseness
- xpmattrs.valuemask |= XpmCloseness;
- xpmattrs.closeness = 40000;
-# endif
-# ifdef XpmVisual
- xpmattrs.valuemask |= XpmVisual;
- xpmattrs.visual = xgwa.visual;
-# endif
-# ifdef XpmDepth
- xpmattrs.valuemask |= XpmDepth;
- xpmattrs.depth = xgwa.depth;
-# endif
-# ifdef XpmColormap
- xpmattrs.valuemask |= XpmColormap;
- xpmattrs.colormap = xgwa.colormap;
-# endif
- result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0,
- &xpmattrs);
- switch (result)
+static unsigned long
+blitspin_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ int this_delay = st->delay;
+ int qwad;
+
+ if (st->img_loader) /* still loading */
{
- case XpmColorError:
- fprintf (stderr, "%s: warning: xpm color substitution performed\n",
- progname);
- /* fall through */
- case XpmSuccess:
- *widthP = xpmattrs.width;
- *heightP = xpmattrs.height;
- break;
- case XpmFileInvalid:
- case XpmOpenFailed:
- bitmap = 0;
- break;
- case XpmColorFailed:
- fprintf (stderr, "%s: xpm: color allocation failed\n", progname);
- exit (-1);
- case XpmNoMemory:
- fprintf (stderr, "%s: xpm: out of memory\n", progname);
- exit (-1);
- default:
- fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result);
- exit (-1);
+ st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
+
+ if (!st->img_loader) { /* just finished */
+ st->first_time = 0;
+ st->loaded_p = True;
+ st->qwad = -1;
+ st->start_time = time ((time_t *) 0);
+ blitspin_init_2 (st);
+ }
+
+ /* Rotate nothing if the very first image is not yet loaded */
+ if (! st->loaded_p)
+ return this_delay;
}
- if (! bitmap)
-#endif
-#ifdef HAVE_XMU
+ if (!st->img_loader &&
+ st->load_ext_p &&
+ st->start_time + st->duration < time ((time_t *) 0)) {
+ /* Start a new image loading, but keep rotating the old image
+ until the new one arrives. */
+ st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
+ st->bitmap, 0, 0);
+ }
+
+ if (st->qwad == -1)
{
- int xh, yh;
- Pixmap b2;
- bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
- 0, 0, widthP, heightP, &xh, &yh);
- if (! bitmap)
- {
- fprintf (stderr, "%s: couldn't find bitmap %s\n", progname,
- bitmap_name);
- exit (1);
- }
- b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP,
- depth, fg, bg);
- XFreePixmap (dpy, bitmap);
- bitmap = b2;
+ bitblt(st, st->mask, st->mask, clear,0,0, st->size, st->size, 0,0);
+ bitblt(st, st->mask, st->mask, set, 0,0, st->size>>1, st->size>>1, 0,0);
+ st->qwad = st->size>>1;
}
-#else /* !XMU */
+
+ if (st->first_time)
{
- fprintf (stderr,
- "%s: your vendor doesn't ship the standard Xmu library.\n",
- progname);
- fprintf (stderr, "\tWe can't load XBM files without it.\n");
- exit (1);
+ st->first_time = 0;
+ display (st, st->self);
+ return st->delay2;
}
-#endif /* !XMU */
-}
+ /* for (st->qwad = st->size>>1; st->qwad > 0; st->qwad>>=1) */
+
+ qwad = st->qwad;
+
+ copy_to (mask, 0, 0, temp, copy); /* 1 */
+ copy_to (mask, 0, qwad, temp, or); /* 2 */
+ copy_to (self, 0, 0, temp, and); /* 3 */
+ copy_to (temp, 0, 0, self, xor); /* 4 */
+ copy_from (temp, qwad, 0, self, xor); /* 5 */
+ copy_from (self, qwad, 0, self, or); /* 6 */
+ copy_to (temp, qwad, 0, self, xor); /* 7 */
+ copy_to (self, 0, 0, temp, copy); /* 8 */
+ copy_from (temp, qwad, qwad, self, xor); /* 9 */
+ copy_to (mask, 0, 0, temp, and); /* A */
+ copy_to (temp, 0, 0, self, xor); /* B */
+ copy_to (temp, qwad, qwad, self, xor); /* C */
+ copy_from (mask, qwad>>1, qwad>>1, mask, and); /* D */
+ copy_to (mask, qwad, 0, mask, or); /* E */
+ copy_to (mask, 0, qwad, mask, or); /* F */
+ display (st, st->self);
+
+ st->qwad >>= 1;
+ if (st->qwad == 0) /* done with this round */
+ {
+ st->qwad = -1;
+ this_delay = st->delay2;
+ }
-static Pixmap
-read_screen (Display *dpy, Window window, int *widthP, int *heightP)
-{
- Pixmap p;
- XWindowAttributes xgwa;
- XGCValues gcv;
- GC gc;
- XGetWindowAttributes (dpy, window, &xgwa);
- *widthP = xgwa.width;
- *heightP = xgwa.height;
-
- grab_screen_image(xgwa.screen, window);
- p = XCreatePixmap(dpy, window, *widthP, *heightP, xgwa.depth);
- gcv.function = GXcopy;
- gc = XCreateGC (dpy, window, GCFunction, &gcv);
- XCopyArea (dpy, window, p, gc, 0, 0, *widthP, *heightP, 0, 0);
-
- /* Reset the window's background color... */
- XSetWindowBackground (dpy, window,
- get_pixel_resource ("background", "Background",
- dpy, xgwa.colormap));
- XCopyArea (dpy, p, window, gc, 0, 0, *widthP, *heightP, 0, 0);
- XFreeGC (dpy, gc);
-
- return p;
+ return this_delay;
}
static int
-to_pow2(int n, Bool up)
+blitspin_to_pow2(int n, Bool up)
{
- /* sizeof(Dimension) == 2. */
- int powers_of_2[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
- 2048, 4096, 8192, 16384, 32768, 65536 };
- int i = 0;
- if (n > 65536) size = 65536;
- while (n >= powers_of_2[i]) i++;
- if (n == powers_of_2[i-1])
+ int pow2 = to_pow2 (n);
+ if (n == pow2)
return n;
else
- return powers_of_2[up ? i : i-1];
+ return up ? pow2 : pow2 >> 1;
}
-static void
-init (void)
+static void *
+blitspin_init (Display *d_arg, Window w_arg)
{
- XWindowAttributes xgwa;
- Colormap cmap;
- XGCValues gcv;
- int width, height;
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
char *bitmap_name;
- Bool scale_up;
- XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
- depth = xgwa.depth;
-
- fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
- bg = get_pixel_resource ("background", "Background", dpy, cmap);
- delay = get_integer_resource ("delay", "Integer");
- delay2 = get_integer_resource ("delay2", "Integer");
- if (delay < 0) delay = 0;
- if (delay2 < 0) delay2 = 0;
- bitmap_name = get_string_resource ("bitmap", "Bitmap");
+ st->dpy = d_arg;
+ st->window = w_arg;
+
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+ st->fg = get_pixel_resource (st->dpy, st->xgwa.colormap,
+ "foreground", "Foreground");
+ st->bg = get_pixel_resource (st->dpy, st->xgwa.colormap,
+ "background", "Background");
+ st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+ st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
+ st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
+ if (st->delay < 0) st->delay = 0;
+ if (st->delay2 < 0) st->delay2 = 0;
+ if (st->duration < 1) st->duration = 1;
+
+ st->start_time = time ((time_t *) 0);
+
+ bitmap_name = get_string_resource (st->dpy, "bitmap", "Bitmap");
if (! bitmap_name || !*bitmap_name)
bitmap_name = "(default)";
- if (!strcmp (bitmap_name, "(default)"))
+ if (!strcasecmp (bitmap_name, "(default)") ||
+ !strcasecmp (bitmap_name, "default"))
+ bitmap_name = "(screen)";
+
+ if (!strcasecmp (bitmap_name, "(builtin)") ||
+ !strcasecmp (bitmap_name, "builtin"))
{
- width = logo_width;
- height = logo_height;
- bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits,
- width, height, fg, bg, depth);
- scale_up = True; /* definitely. */
+ Pixmap mask = 0;
+ Pixmap pixmap = image_data_to_pixmap (st->dpy, st->window,
+ som_png, sizeof(som_png),
+ &st->width, &st->height, &mask);
+ XGCValues gcv;
+ GC gc;
+ gcv.foreground = st->bg;
+ gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
+ st->bitmap = XCreatePixmap (st->dpy, st->window,
+ st->xgwa.width, st->xgwa.height,
+ st->xgwa.depth);
+ XFillRectangle (st->dpy, st->bitmap, gc, 0, 0, st->width, st->height);
+ XSetClipMask (st->dpy, gc, mask);
+ XCopyArea (st->dpy, pixmap, st->bitmap, gc, 0, 0, st->width, st->height,
+ 0, 0);
+ XFreeGC (st->dpy, gc);
+ XFreePixmap (st->dpy, pixmap);
+ XFreePixmap (st->dpy, mask);
+
+ st->scale_up = True; /* definitely. */
+ st->loaded_p = True;
+ blitspin_init_2 (st);
}
- else if (!strcmp (bitmap_name, "(screen)"))
+ else if (!strcasecmp (bitmap_name, "(screen)") ||
+ !strcasecmp (bitmap_name, "screen"))
{
- bitmap = read_screen (dpy, window, &width, &height);
- scale_up = True; /* maybe? */
+ st->bitmap = XCreatePixmap (st->dpy, st->window,
+ st->xgwa.width, st->xgwa.height,
+ st->xgwa.depth);
+ st->width = st->xgwa.width;
+ st->height = st->xgwa.height;
+ st->scale_up = True; /* maybe? */
+ st->load_ext_p = True;
+ st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
+ st->bitmap, 0, 0);
}
else
{
- read_bitmap (bitmap_name, &width, &height);
- scale_up = True; /* probably? */
+ st->bitmap = file_to_pixmap (st->dpy, st->window, bitmap_name,
+ &st->width, &st->height, 0);
+ st->scale_up = True; /* probably? */
+ blitspin_init_2 (st);
}
- size = (width < height) ? height : width; /* make it square */
- size = to_pow2(size, scale_up); /* round up to power of 2 */
+ return st;
+}
+
+
+static void
+blitspin_init_2 (struct state *st)
+{
+ XGCValues gcv;
+
+ /* make it square */
+ st->size = (st->width < st->height) ? st->height : st->width;
+ /* round up to power of 2 */
+ st->size = blitspin_to_pow2(st->size, st->scale_up);
{ /* don't exceed screen size */
- int s = XScreenNumberOfScreen(xgwa.screen);
- int w = to_pow2(XDisplayWidth(dpy, s), False);
- int h = to_pow2(XDisplayHeight(dpy, s), False);
- if (size > w) size = w;
- if (size > h) size = h;
+ int s = XScreenNumberOfScreen(st->xgwa.screen);
+ int w = blitspin_to_pow2(XDisplayWidth(st->dpy, s), False);
+ int h = blitspin_to_pow2(XDisplayHeight(st->dpy, s), False);
+ if (st->size > w) st->size = w;
+ if (st->size > h) st->size = h;
}
- self = XCreatePixmap (dpy, window, size, size, depth);
- temp = XCreatePixmap (dpy, window, size, size, depth);
- mask = XCreatePixmap (dpy, window, size, size, depth);
- gcv.foreground = (depth == 1 ? 1 : (~0));
- gcv.function=GXset; SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
- gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
- gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
- gcv.function=GXor; IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
- gcv.function=GXand; AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
- gcv.function=GXxor; XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
-
- gcv.foreground = gcv.background = bg;
- gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
- /* Clear self to the background color (not to 0, which CLR does.) */
- XFillRectangle (dpy, self, gc, 0, 0, size, size);
- XSetForeground (dpy, gc, fg);
-
- XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
- (size - width)>>1, (size - height)>>1);
- XFreePixmap(dpy, bitmap);
-
- display (self);
- XSync(dpy, False);
+ if (st->self) XFreePixmap (st->dpy, st->self);
+ if (st->temp) XFreePixmap (st->dpy, st->temp);
+ if (st->mask) XFreePixmap (st->dpy, st->mask);
+
+ st->self = XCreatePixmap (st->dpy, st->window, st->size, st->size,
+ st->xgwa.depth);
+ st->temp = XCreatePixmap (st->dpy, st->window, st->size, st->size,
+ st->xgwa.depth);
+ st->mask = XCreatePixmap (st->dpy, st->window, st->size, st->size,
+ st->xgwa.depth);
+ gcv.foreground = (st->xgwa.depth == 1 ? 1 : (~0));
+
+# ifdef USE_XCOPYAREA
+# define make_gc(op) \
+ gcv.function=GX##op; \
+ if (st->gc_##op) XFreeGC (st->dpy, st->gc_##op); \
+ st->gc_##op = XCreateGC (st->dpy, st->self, GCFunction|GCForeground, &gcv)
+ make_gc(set);
+ make_gc(clear);
+ make_gc(copy);
+ make_gc(and);
+ make_gc(or);
+ make_gc(xor);
+# endif /* USE_XCOPYAREA */
+
+ gcv.foreground = gcv.background = st->bg;
+ if (st->gc) XFreeGC (st->dpy, st->gc);
+ st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
+ /* Clear st->self to the background color (not to 0, which 'clear' does.) */
+ XFillRectangle (st->dpy, st->self, st->gc, 0, 0, st->size, st->size);
+ XSetForeground (st->dpy, st->gc, st->fg);
+
+ XCopyArea (st->dpy, st->bitmap, st->self, st->gc, 0, 0,
+ st->width, st->height,
+ (st->size - st->width) >> 1,
+ (st->size - st->height) >> 1);
+
+ st->qwad = -1;
+ st->first_time = 1;
}
static void
-display (Pixmap pixmap)
+display (struct state *st, Pixmap pixmap)
{
- XWindowAttributes xgwa;
- static int last_w = 0, last_h = 0;
- XGetWindowAttributes (dpy, window, &xgwa);
- if (xgwa.width != last_w || xgwa.height != last_h)
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+ if (st->xgwa.width != st->last_w ||
+ st->xgwa.height != st->last_h)
{
- XClearWindow (dpy, window);
- last_w = xgwa.width;
- last_h = xgwa.height;
+ XClearWindow (st->dpy, st->window);
+ st->last_w = st->xgwa.width;
+ st->last_h = st->xgwa.height;
}
-#ifdef HAVE_XPM
- if (depth != 1)
- XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
- (xgwa.width-size)>>1, (xgwa.height-size)>>1);
+ if (st->xgwa.depth != 1)
+ XCopyArea (st->dpy, pixmap, st->window, st->gc, 0, 0, st->size, st->size,
+ (st->xgwa.width - st->size) >> 1,
+ (st->xgwa.height - st->size) >> 1);
else
-#endif
- XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
- (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
+ XCopyPlane (st->dpy, pixmap, st->window, st->gc, 0, 0, st->size, st->size,
+ (st->xgwa.width - st->size) >> 1,
+ (st->xgwa.height - st->size) >> 1,
+ 1);
/*
- XDrawRectangle (dpy, window, gc,
- ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
- size+2, size+2);
+ XDrawRectangle (st->dpy, st->window, st->gc,
+ ((st->xgwa.width - st->size) >> 1) - 1,
+ ((st->xgwa.height - st->size) >> 1) - 1,
+ st->size+2, st->size+2);
*/
- XSync (dpy, True);
}
-\f
-char *progclass = "BlitSpin";
+static void
+blitspin_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+blitspin_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ struct state *st = (struct state *) closure;
+ if (screenhack_event_helper (dpy, window, event))
+ {
+ st->start_time = 0;
+ return True;
+ }
+ return False;
+}
+
+static void
+blitspin_free (Display *dpy, Window window, void *closure)
+{
+}
-char *defaults [] = {
- "BlitSpin.background: black", /* to placate SGI */
- "BlitSpin.foreground: white",
+\f
+static const char *blitspin_defaults [] = {
+ ".background: black",
+ ".foreground: white",
+ ".fpsSolid: true",
"*delay: 500000",
"*delay2: 500000",
+ "*duration: 120",
"*bitmap: (default)",
- "*geometry: 512x512",
+ "*geometry: 1080x1080",
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
0
};
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec blitspin_options [] = {
{ "-delay", ".delay", XrmoptionSepArg, 0 },
{ "-delay2", ".delay2", XrmoptionSepArg, 0 },
+ { "-duration", ".duration", XrmoptionSepArg, 0 },
{ "-bitmap", ".bitmap", XrmoptionSepArg, 0 },
- { "-grab-screen", ".bitmap", XrmoptionNoArg, "(screen)" },
{ 0, 0, 0, 0 }
};
-void
-screenhack (Display *d, Window w)
-{
- dpy = d;
- window = w;
- init ();
- if (delay2) usleep (delay2 * 2);
- while (1)
- {
- rotate ();
- if (delay2) usleep (delay2);
- }
-}
+
+XSCREENSAVER_MODULE ("BlitSpin", blitspin)