source: trunk/third/xscreensaver/hacks/spotlight.c @ 20148

Revision 20148, 6.9 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * spotlight - an xscreensaver module
3 * Copyright (c) 1999, 2001 Rick Schultz <rick@skapunx.net>
4 *
5 * loosely based on the BackSpace module "StefView" by Darcy Brockbank
6 */
7
8/* modified from a module from the xscreensaver distribution */
9
10/*
11 * xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997, 1998
12 * Jamie Zawinski <jwz@jwz.org>
13 *
14 * Permission to use, copy, modify, distribute, and sell this software and its
15 * documentation for any purpose is hereby granted without fee, provided that
16 * the above copyright notice appear in all copies and that both that
17 * copyright notice and this permission notice appear in supporting
18 * documentation.  No representations are made about the suitability of this
19 * software for any purpose.  It is provided "as is" without express or
20 * implied warranty.
21 */
22
23/* #define DEBUG */
24#include <math.h>
25#include "screenhack.h"
26#include <X11/Xutil.h>
27#include <sys/time.h>
28
29#define MINX 0.0
30#define MINY 0.0
31#define X_PERIOD 15000.0
32#define Y_PERIOD 12000.0
33
34static int sizex, sizey; /* screen size */
35static int delay;        /* in case it's too fast... */
36static GC window_gc;
37#ifdef DEBUG
38static GC white_gc;
39#endif
40static GC buffer_gc;     /* draw in buffer, then flush to screen
41                            to avoid flicker */
42static int radius;       /* radius of spotlight in pixels */
43
44static Pixmap pm;        /* pixmap grabbed from screen */
45static Pixmap clip_pm;   /* pixmap for clipping (spotlight shape) */
46static Pixmap buffer;    /* pixmap for the buffer */
47
48static GC clip_gc;       /* GC for the clip pixmap */
49
50static int x, y, s;      /* x & y coords of buffer (upper left corner) */
51                         /* s is the width of the buffer */
52
53static int oldx, oldy, max_x_speed, max_y_speed;
54                         /* used to keep the new buffer position
55                            over the old spotlight image to make sure
56                            the old image is completely erased */
57
58/* The path the spotlight follows around the screen is sinusoidal.
59   This function is fed to sin() to get the x & y coords */
60static long
61currentTimeInMs(void)
62{
63  struct timeval curTime;
64#ifdef GETTIMEOFDAY_TWO_ARGS
65  struct timezone tz = {0,0};
66  gettimeofday(&curTime, &tz);
67#else
68  gettimeofday(&curTime);
69#endif
70  return curTime.tv_sec*1000 + curTime.tv_usec/1000.0;
71}
72
73
74static void
75init_hack (Display *dpy, Window window)
76{
77  XGCValues gcv;
78  XWindowAttributes xgwa;
79  long gcflags;
80  Colormap cmap;
81  unsigned long fg, bg;
82
83  XGetWindowAttributes (dpy, window, &xgwa);
84  sizex = xgwa.width;
85  sizey = xgwa.height;
86  cmap = xgwa.colormap;
87  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
88  bg = get_pixel_resource ("background", "Background", dpy, cmap);
89
90  /* read parameters, keep em sane */
91  delay = get_integer_resource ("delay", "Integer");
92  if (delay < 1) delay = 1;
93  radius = get_integer_resource ("radius", "Integer");
94  if (radius < 0) radius = 125;
95
96  /* Don't let the spotlight be bigger than 1/4 of the window */
97  if (radius > xgwa.width  / 4) radius = xgwa.width  / 4;
98  if (radius > xgwa.height / 4) radius = xgwa.height / 4;
99
100  /* do the dance */
101  gcv.function = GXcopy;
102  gcv.subwindow_mode = IncludeInferiors;
103  gcflags = GCForeground | GCFunction;
104  gcv.foreground = bg;
105
106#ifdef NOPE
107  if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
108    gcflags |= GCSubwindowMode;
109#endif
110  window_gc = XCreateGC(dpy, window, gcflags, &gcv);
111
112  /* grab screen to pixmap */
113  pm = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
114  load_random_image (xgwa.screen, window, pm, NULL);
115  XClearWindow(dpy, window);
116  XFlush (dpy);
117
118  /* create buffer to reduce flicker */
119  buffer = XCreatePixmap(dpy, window, sizex, sizey, xgwa.depth);
120  buffer_gc = XCreateGC(dpy, buffer, gcflags, &gcv);
121  XFillRectangle(dpy, buffer, buffer_gc, 0, 0, sizex, sizey);
122
123  /* blank out screen */
124  XFillRectangle(dpy, window, window_gc, 0, 0, sizex, sizey);
125  XSetWindowBackground (dpy, window, bg);
126
127  /* create clip mask (so it's a circle, not a square) */
128  clip_pm = XCreatePixmap(dpy, window, radius*4, radius*4, 1);
129
130  gcv.foreground = 0L;
131  clip_gc = XCreateGC(dpy, clip_pm, gcflags, &gcv);
132  XFillRectangle(dpy, clip_pm, clip_gc, 0, 0, radius*4, radius*4);
133
134  XSetForeground(dpy, clip_gc, 1L);
135  XFillArc(dpy, clip_pm, clip_gc, radius , radius,
136           radius*2, radius*2, 0, 360*64);
137
138  /* set buffer's clip mask to the one we just made */
139  XSetClipMask(dpy, buffer_gc, clip_pm);
140
141  /* free everything */
142  XFreeGC(dpy, clip_gc);
143  XFreePixmap(dpy, clip_pm);
144
145  /* avoid remants */
146  max_x_speed = max_y_speed = radius;
147
148#ifdef DEBUG
149  /* create GC with white fg */
150  gcv.foreground = fg;
151  white_gc = XCreateGC(dpy, window, gcflags, &gcv);
152#endif
153 
154  /* initialize x and y to avoid initial `jump' across screen */
155  x = ((1 + sin(((float)currentTimeInMs()) / X_PERIOD * 2. * M_PI))/2.0)
156    * (sizex - s/2) -s/4  + MINX;
157  y = ((1 + sin(((float)currentTimeInMs()) / Y_PERIOD * 2. * M_PI))/2.0)
158    * (sizey - s/2) -s/4  + MINY;
159
160}
161
162
163/*
164 * perform one iteration
165 */
166static void
167onestep (Display *dpy, Window window)
168{
169    long now;
170
171    /* clear buffer */
172    XFillRectangle(dpy, buffer, buffer_gc, x, y, s, s);
173
174   
175#define nrnd(x) (random() % (x))
176
177    oldx = x;
178    oldy = y;
179
180    s = radius *4 ;   /* s = width of buffer */
181
182    now = currentTimeInMs();
183
184    /* find new x,y */
185    x = ((1 + sin(((float)now) / X_PERIOD * 2. * M_PI))/2.0)
186      * (sizex - s/2) -s/4  + MINX;
187    y = ((1 + sin(((float)now) / Y_PERIOD * 2. * M_PI))/2.0)
188      * (sizey - s/2) -s/4  + MINY;
189   
190    /* limit change in x and y to buffer width */
191    if ( x < (oldx - max_x_speed) ) x = oldx - max_x_speed;
192    if ( x > (oldx + max_x_speed) ) x = oldx + max_x_speed;
193    if ( y < (oldy - max_y_speed) ) y = oldy - max_y_speed;
194    if ( y > (oldy + max_y_speed) ) y = oldy + max_y_speed;
195
196    /* copy area of screen image (pm) to buffer
197       Clip to a circle */
198    XSetClipOrigin(dpy, buffer_gc, x,y);
199    XCopyArea(dpy, pm, buffer, buffer_gc, x, y, s, s, x, y);
200    /* copy buffer to screen (window) */
201    XCopyArea(dpy, buffer, window, window_gc, x , y, s, s, x, y);
202
203#ifdef DEBUG
204    /* draw a box around the buffer */
205    XDrawLine(dpy, window, white_gc, x, y, x+s, y);
206    XDrawLine(dpy, window, white_gc, x, y, x, y+s);
207    XDrawLine(dpy, window, white_gc, x+s, y, x+s, y+s);
208    XDrawLine(dpy, window, white_gc, x, y+s, x+s, y+s);
209#endif
210
211}
212
213
214char *progclass = "Spotlight";
215
216char *defaults [] = {
217  ".background:                 black",
218  ".foreground:                 white",
219  "*dontClearRoot:              True",
220
221#ifdef __sgi    /* really, HAVE_READ_DISPLAY_EXTENSION */
222  "*visualID:                   Best",
223#endif
224
225  "*delay:                      10000",
226  "*radius:                     125",
227  0
228};
229
230XrmOptionDescRec options [] = {
231  { "-delay",           ".delay",               XrmoptionSepArg, 0 },
232  { "-radius",          ".radius",              XrmoptionSepArg, 0 },
233  { 0, 0, 0, 0 }
234};
235
236void
237screenhack (Display *dpy, Window window)
238{
239  init_hack (dpy, window);
240  while (1) {
241    onestep(dpy, window);
242    XSync(dpy, False);
243    if (delay) usleep (delay);
244    screenhack_handle_events (dpy);
245  }
246}
247 
Note: See TracBrowser for help on using the repository browser.