/*
* spotlight - an xscreensaver module
- * Copyright (c) 1999 Rick Schultz <rick@skapunx.net>
+ * Copyright (c) 1999, 2001 Rick Schultz <rick@skapunx.net>
*
* loosely based on the BackSpace module "StefView" by Darcy Brockbank
*/
static int sizex, sizey; /* screen size */
static int delay; /* in case it's too fast... */
-static GC gc;
+static GC window_gc;
#ifdef DEBUG
static GC white_gc;
#endif
static GC buffer_gc; /* draw in buffer, then flush to screen
to avoid flicker */
static int radius; /* radius of spotlight in pixels */
-static XGCValues gcv;
static Pixmap pm; /* pixmap grabbed from screen */
static Pixmap clip_pm; /* pixmap for clipping (spotlight shape) */
static GC clip_gc; /* GC for the clip pixmap */
-int x, y, s; /* x & y coords of buffer (upper left corner) */
+static int x, y, s; /* x & y coords of buffer (upper left corner) */
/* s is the width of the buffer */
-int oldx, oldy, max_x_speed, max_y_speed;
+static int off = 0; /* random offset from currentTimeInMs(), so that
+ two concurrent copies of spotlight have different
+ behavior. */
+
+static int oldx, oldy, max_x_speed, max_y_speed;
/* used to keep the new buffer position
over the old spotlight image to make sure
the old image is completely erased */
static void
init_hack (Display *dpy, Window window)
{
+ XGCValues gcv;
XWindowAttributes xgwa;
long gcflags;
Colormap cmap;
radius = get_integer_resource ("radius", "Integer");
if (radius < 0) radius = 125;
+ /* Don't let the spotlight be bigger than 1/4 of the window */
+ if (radius > xgwa.width / 4) radius = xgwa.width / 4;
+ if (radius > xgwa.height / 4) radius = xgwa.height / 4;
+
/* do the dance */
gcv.function = GXcopy;
gcv.subwindow_mode = IncludeInferiors;
gcflags = GCForeground | GCFunction;
gcv.foreground = bg;
- gcv.background = fg;
#ifdef NOPE
if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
gcflags |= GCSubwindowMode;
#endif
- gc = XCreateGC (dpy, window, gcflags, &gcv);
-
+ window_gc = XCreateGC(dpy, window, gcflags, &gcv);
- /* grab screen to window */
- grab_screen_image (xgwa.screen, window);
-
- /* save screen to pixmap for copying later */
+ /* grab screen to pixmap */
pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
- XCopyArea(dpy, window, pm, gc, 0, 0, sizex, sizey, 0, 0);
-
+ load_random_image (xgwa.screen, window, pm, NULL);
+ XClearWindow(dpy, window);
+ XFlush (dpy);
/* create buffer to reduce flicker */
buffer = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
- buffer_gc = XCreateGC (dpy, buffer, gcflags, &gcv);
+ buffer_gc = XCreateGC(dpy, buffer, gcflags, &gcv);
+ XFillRectangle(dpy, buffer, buffer_gc, 0, 0, sizex, sizey);
/* blank out screen */
- XFillRectangle(dpy,window,gc,0,0,sizex,sizey);
+ XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
+ XSetWindowBackground (dpy, window, bg);
/* create clip mask (so it's a circle, not a square) */
clip_pm = XCreatePixmap(dpy, window, radius*4, radius*4, 1);
- gcv.foreground=bg;
- gcv.background=bg;
+
+ gcv.foreground = 0L;
clip_gc = XCreateGC(dpy, clip_pm, gcflags, &gcv);
- XFillRectangle(dpy,clip_pm,clip_gc,0,0,radius*4, radius*4);
- XSetForeground(dpy,clip_gc,fg);
+ XFillRectangle(dpy, clip_pm, clip_gc, 0, 0, radius*4, radius*4);
+
+ XSetForeground(dpy, clip_gc, 1L);
XFillArc(dpy, clip_pm, clip_gc, radius , radius,
radius*2, radius*2, 0, 360*64);
+
/* set buffer's clip mask to the one we just made */
XSetClipMask(dpy, buffer_gc, clip_pm);
+
/* free everything */
XFreeGC(dpy, clip_gc);
XFreePixmap(dpy, clip_pm);
/* avoid remants */
max_x_speed = max_y_speed = radius;
+
+ off = random();
#ifdef DEBUG
/* create GC with white fg */
gcv.foreground = fg;
- white_gc = XCreateGC (dpy, window, gcflags, &gcv);
+ white_gc = XCreateGC(dpy, window, gcflags, &gcv);
#endif
-
- /* initialize x and y to avoid initial `jump' across screen */
- x = ((1 + sin(((float)currentTimeInMs()) / X_PERIOD * 2. * M_PI))/2.0)
- * (sizex - s/2) -s/4 + MINX;
- y = ((1 + sin(((float)currentTimeInMs()) / Y_PERIOD * 2. * M_PI))/2.0)
- * (sizey - s/2) -s/4 + MINY;
-
}
* perform one iteration
*/
static void
-onestep (Display *dpy, Window window)
+onestep (Display *dpy, Window window, Bool first_p)
{
long now;
s = radius *4 ; /* s = width of buffer */
- now = currentTimeInMs();
+ now = currentTimeInMs() + off;
/* find new x,y */
x = ((1 + sin(((float)now) / X_PERIOD * 2. * M_PI))/2.0)
y = ((1 + sin(((float)now) / Y_PERIOD * 2. * M_PI))/2.0)
* (sizey - s/2) -s/4 + MINY;
- /* limit change in x and y to buffer width */
- if ( x < (oldx - max_x_speed) ) x = oldx - max_x_speed;
- if ( x > (oldx + max_x_speed) ) x = oldx + max_x_speed;
- if ( y < (oldy - max_y_speed) ) y = oldy - max_y_speed;
- if ( y > (oldy + max_y_speed) ) y = oldy + max_y_speed;
+ if (!first_p)
+ {
+ /* limit change in x and y to buffer width */
+ if ( x < (oldx - max_x_speed) ) x = oldx - max_x_speed;
+ if ( x > (oldx + max_x_speed) ) x = oldx + max_x_speed;
+ if ( y < (oldy - max_y_speed) ) y = oldy - max_y_speed;
+ if ( y > (oldy + max_y_speed) ) y = oldy + max_y_speed;
+ }
/* copy area of screen image (pm) to buffer
Clip to a circle */
XSetClipOrigin(dpy, buffer_gc, x,y);
XCopyArea(dpy, pm, buffer, buffer_gc, x, y, s, s, x, y);
/* copy buffer to screen (window) */
- XCopyArea(dpy, buffer, window, gc, x , y, s, s, x, y);
+ XCopyArea(dpy, buffer, window, window_gc, x , y, s, s, x, y);
#ifdef DEBUG
/* draw a box around the buffer */
char *progclass = "Spotlight";
char *defaults [] = {
+ ".background: black",
+ ".foreground: white",
"*dontClearRoot: True",
#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
void
screenhack (Display *dpy, Window window)
{
+ Bool first_p = True;
init_hack (dpy, window);
while (1) {
- onestep(dpy, window);
+ onestep(dpy, window, first_p);
+ first_p = False;
XSync(dpy, False);
if (delay) usleep (delay);
screenhack_handle_events (dpy);