b4light.c revision 2d861bc5
1/* 2 * $XConsortium: b4light.c,v 1.3 94/04/17 20:59:38 rws Exp $ 3 * 4Copyright (c) 1992 X Consortium 5 6Permission is hereby granted, free of charge, to any person obtaining a copy 7of this software and associated documentation files (the "Software"), to deal 8in the Software without restriction, including without limitation the rights 9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10copies of the Software, and to permit persons to whom the Software is 11furnished to do so, subject to the following conditions: 12 13The above copyright notice and this permission notice shall be included in 14all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of the X Consortium shall not be 24used in advertising or otherwise to promote the sale, use or other dealings 25in this Software without prior written authorization from the X Consortium. 26 * 27 * Author: Keith Packard, MIT X Consortium 28 */ 29/* $XFree86: xc/programs/beforelight/b4light.c,v 3.6tsi Exp $ */ 30 31#include <X11/Xatom.h> 32#include <X11/Intrinsic.h> 33#include <X11/StringDefs.h> 34#include <X11/Shell.h> 35#ifdef NOTDEF 36#include <X11/Xaw/Label.h> 37#endif 38#include <X11/Xaw/Cardinals.h> 39#include <X11/extensions/scrnsaver.h> 40#include <X11/Xcms.h> 41#include <stdlib.h> 42#include <time.h> 43 44#ifdef NOTDEF 45static void quit (Widget w, XEvent *event, 46 String *params, Cardinal *num_params); 47 48static XtActionsRec beforedark_actions[] = { 49 { "quit", quit }, 50}; 51 52static Atom wm_delete_window; 53#endif 54 55static int ss_event, ss_error; 56 57static Display *display; 58static Window root, saver; 59static int screen; 60static int scr_wid, scr_hei; 61static Colormap cmap; 62static GC gc, black_gc, erase_gc; 63static int screen_saved; 64static XtAppContext app_con; 65static GC bit_1_gc, bit_0_gc; 66static Bool filled = False; 67 68#define MAX_POINTS 16 69 70typedef struct _moving { 71 int x, y, dx, dy; 72} Moving; 73 74static Moving p[MAX_POINTS]; 75 76#define NUM_HISTORY 32 77 78static XPoint history[NUM_HISTORY][MAX_POINTS]; 79static Pixmap old_pixmaps[NUM_HISTORY]; 80static unsigned long old_pixels[NUM_HISTORY]; 81static int num_points = 3; 82static int history_head, history_tail; 83#define hist_bump(h) ((++(h) == NUM_HISTORY) ? ((h) = 0) : 0) 84 85#define NUM_COLORS 64 86 87static unsigned long black_pixel; 88static unsigned long pixels[NUM_COLORS]; 89static int cur_pen = 0; 90 91static void 92AllocateColors (void) 93{ 94 double angle; 95 double step; 96 XcmsColor cms_color; 97 int i; 98 XColor hard, exact; 99 100 XAllocNamedColor (display, cmap, "black", &hard, &exact); 101 black_pixel = hard.pixel; 102 step = 360.0 / NUM_COLORS; 103 for (i = 0; i < NUM_COLORS; i++) { 104 angle = i * step; 105 cms_color.spec.TekHVC.H = angle; 106 cms_color.spec.TekHVC.V = 75.0; 107 cms_color.spec.TekHVC.C = 75.0; 108 cms_color.format = XcmsTekHVCFormat; 109 XcmsAllocColor (display, cmap, &cms_color, XcmsRGBFormat); 110 pixels[i] = cms_color.pixel; 111 } 112} 113 114 115static void 116StepPen (void) 117{ 118 XSetForeground (display, gc, pixels[cur_pen]); 119 cur_pen++; 120 if (cur_pen == NUM_COLORS) 121 cur_pen = 0; 122} 123 124static void 125DrawPoints (Drawable draw, GC gc, XPoint *p, int n) 126{ 127 XPoint xp[MAX_POINTS + 1]; 128 int i; 129 130 switch (n) { 131 case 1: 132 XDrawPoint (display, draw, gc, p->x, p->y); 133 break; 134 case 2: 135 XDrawLine (display, draw, gc, p[0].x, p[0].y, p[1].x, p[1].y); 136 break; 137 default: 138 for (i = 0; i < n; i++) { 139 xp[i].x = p[i].x; xp[i].y = p[i].y; 140 } 141 xp[i].x = p[0].x; xp[i].y = p[0].y; 142 if (filled) 143 XFillPolygon (display, draw, gc, xp, i+1, Complex, CoordModeOrigin); 144 else 145 XDrawLines (display, draw, gc, xp, i + 1, CoordModeOrigin); 146 } 147} 148 149static void 150Draw (Moving *p, int n) 151{ 152 XPoint xp[MAX_POINTS]; 153 int i; 154 for (i = 0; i < n; i++) 155 { 156 xp[i].x = p[i].x; xp[i].y = p[i].y; 157 } 158 old_pixels[history_head] = pixels[cur_pen]; 159 StepPen (); 160 DrawPoints (saver, gc, xp, n); 161 if (filled) 162 { 163 XFillRectangle (display, old_pixmaps[history_head], bit_0_gc, 164 0, 0, scr_wid, scr_hei); 165 DrawPoints (old_pixmaps[history_head], bit_1_gc, xp, n); 166 for (i = history_tail; i != history_head; hist_bump(i)) 167 DrawPoints (old_pixmaps[i], bit_0_gc, xp, n); 168 } 169} 170 171static void 172Erase (XPoint *p, int n) 173{ 174 if (filled) { 175 XSetForeground (display, erase_gc, black_pixel ^ old_pixels[history_tail]); 176 XCopyPlane (display, old_pixmaps[history_tail], saver, erase_gc, 177 0, 0, scr_wid, scr_hei, 0, 0, 1); 178 } 179 else 180 DrawPoints (saver, black_gc, p, n); 181} 182 183#define STEP_MAX 32 184 185static int 186RandomStep (void) 187{ 188 return (rand () % STEP_MAX) + 1; 189} 190 191static void 192StepMoving (Moving *m) 193{ 194 int maxx, maxy; 195 196 maxx = DisplayWidth (display, screen); 197 maxy = DisplayHeight (display, screen); 198 m->x += m->dx; 199 if (m->x <= 0) { 200 m->x = 0; 201 m->dx = RandomStep (); 202 } 203 if (m->x >= maxx) { 204 m->x = maxx - 1; 205 m->dx = -RandomStep (); 206 } 207 m->y += m->dy; 208 if (m->y <= 0) { 209 m->y = 0; 210 m->dy = RandomStep (); 211 } 212 if (m->y >= maxy) { 213 m->y = maxy - 1; 214 m->dy = -RandomStep (); 215 } 216} 217 218static void 219StepPoints (void) 220{ 221 int i; 222 223 for (i = 0; i < num_points; i++) 224 StepMoving (&p[i]); 225 hist_bump(history_head); 226 if (history_tail == history_head) 227 { 228 Erase (history[history_tail], num_points); 229 hist_bump(history_tail); 230 } 231 Draw (p, num_points); 232 for (i = 0; i < num_points; i++) 233 { 234 history[history_head][i].x = p[i].x; 235 history[history_head][i].y = p[i].y; 236 } 237} 238 239static void 240StartPoints (void) 241{ 242 history_head = history_tail = 0; 243} 244 245static void 246Timeout (XtPointer closure, XtIntervalId *id) 247{ 248 if (screen_saved) 249 { 250 StepPoints (); 251 (void) XtAppAddTimeOut (app_con, 50, Timeout, NULL); 252 } 253} 254 255static void 256StartSaver (void) 257{ 258 if (screen_saved) 259 return; 260 screen_saved = True; 261 StartPoints (); 262 StepPoints (); 263 (void) XtAppAddTimeOut (app_con, 50, Timeout, NULL); 264} 265 266static void 267StopSaver (void) 268{ 269 if (!screen_saved) 270 return; 271 screen_saved = False; 272} 273 274static int 275ignoreError (Display *display, XErrorEvent *error) 276{ 277 return 0; 278} 279 280int 281main(int argc, char *argv[]) 282{ 283 Widget toplevel; 284 XEvent event; 285 XScreenSaverNotifyEvent *sevent; 286 XSetWindowAttributes attr; 287 XScreenSaverInfo *info; 288 unsigned long mask; 289 Pixmap blank_pix; 290 XColor dummyColor; 291 XID kill_id; 292 Atom kill_type; 293 int i; 294 int (*oldHandler)(Display*, XErrorEvent*); 295 Window r; 296 int x, y; 297 unsigned int w, h, b, d; 298 Status s; 299 300#if !defined(X_NOT_POSIX) 301 srand((int)time((time_t *)NULL)); 302#else 303 srand((int)time((int *)NULL)); 304#endif 305 306 toplevel = XtAppInitialize (&app_con, "Beforelight", NULL, ZERO, 307 &argc, argv, NULL, NULL, ZERO); 308 display = XtDisplay (toplevel); 309 root = DefaultRootWindow (display); 310 screen = DefaultScreen (display); 311 scr_wid = DisplayWidth (display, screen); 312 scr_hei = DisplayHeight (display, screen); 313 if (!XScreenSaverQueryExtension (display, &ss_event, &ss_error)) 314 exit (1); 315#ifdef NOTDEF 316 XtAppAddActions (app_con, beforedark_actions, XtNumber(beforedark_actions)); 317 318 /* 319 * This is a hack so that f.delete will do something useful in this 320 * single-window application. 321 */ 322 XtOverrideTranslations(toplevel, 323 XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); 324 325 XtCreateManagedWidget ("label", labelWidgetClass, toplevel, NULL, ZERO); 326 XtRealizeWidget (toplevel); 327 wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", 328 False); 329 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 330 &wm_delete_window, 1); 331 332#endif 333 oldHandler = XSetErrorHandler (ignoreError); 334 if (XScreenSaverGetRegistered (display, screen, &kill_id, &kill_type)) { 335 s = XGetGeometry(display, kill_id, &r, &x, &y, &w, &h, &b, &d); 336 if (s == True && r == root && w == 1 && h == 1 && d == 1) { 337 /* Try to clean up existing saver & resources */ 338 XKillClient (display, kill_id); 339 XScreenSaverUnregister(display, screen); 340 } 341 } 342 XSync(display, FALSE); 343 XSetErrorHandler(oldHandler); 344 XScreenSaverSelectInput (display, root, ScreenSaverNotifyMask); 345#ifdef NOTDEF 346 cmap = XCreateColormap (display, root, DefaultVisual (display, screen), AllocNone); 347#else 348 cmap = DefaultColormap (display, screen); 349#endif 350 AllocateColors(); 351 blank_pix = XCreatePixmap (display, root, 1, 1, 1); 352 XScreenSaverRegister (display, screen, (XID) blank_pix, XA_PIXMAP); 353 bit_0_gc = XCreateGC (display, blank_pix, 0, NULL); 354 XSetForeground (display, bit_0_gc, 0); 355 bit_1_gc = XCreateGC (display, blank_pix, 0, NULL); 356 XSetForeground (display, bit_1_gc, ~0); 357 XFillRectangle (display, blank_pix, bit_0_gc, 0, 0, 1, 1); 358 info = XScreenSaverAllocInfo (); 359 XScreenSaverQueryInfo (display, root, info); 360 mask = 0; 361 attr.colormap = cmap; 362 mask |= CWColormap; 363 attr.background_pixel = black_pixel; 364 mask |= CWBackPixel; 365 attr.cursor = XCreatePixmapCursor (display, blank_pix, blank_pix, &dummyColor, &dummyColor, 0, 0); 366 mask |= CWCursor; 367 XScreenSaverSetAttributes (display, root, 0, 0, 368 DisplayWidth (display, screen), DisplayHeight(display, screen), 0, 369 CopyFromParent, CopyFromParent, (Visual *)CopyFromParent, mask, &attr); 370 XSync (display, False); 371 gc = XCreateGC (display, root, 0, NULL); 372 black_gc = XCreateGC (display, root, 0, NULL); 373 XSetForeground (display, black_gc, black_pixel); 374 if (filled) 375 { 376 erase_gc = XCreateGC (display, root, 0, NULL); 377 XSetBackground (display, erase_gc, 0); 378 XSetFunction (display, erase_gc, GXxor); 379 XSetGraphicsExposures (display, erase_gc, False); 380 for (i = 0; i < NUM_HISTORY; i++) 381 old_pixmaps[i] = XCreatePixmap (display, root, scr_wid, scr_hei, 1); 382 } 383 XSetErrorHandler (ignoreError); 384 saver = info->window; 385 if (info->state == ScreenSaverOn) 386 { 387 if (info->kind != ScreenSaverExternal) 388 { 389 XResetScreenSaver (display); 390 XActivateScreenSaver (display); 391 } 392 StartSaver (); 393 } 394 for (;;) 395 { 396 XtAppNextEvent (app_con, &event); 397 if (event.type == ss_event) { 398 sevent = (XScreenSaverNotifyEvent *) &event; 399 if (sevent->state == ScreenSaverOn) { 400 if (sevent->kind != ScreenSaverExternal) { 401 XResetScreenSaver (display); 402 XActivateScreenSaver (display); 403 } else { 404 StartSaver (); 405 } 406 } else if (sevent->state == ScreenSaverOff) { 407 StopSaver (); 408 } 409 } else { 410 XtDispatchEvent(&event); 411 } 412 } 413} 414 415#ifdef NOTDEF 416static void 417quit (Widget w, XEvent *event, String *params, Cardinal *num_params) 418{ 419 if (event->type == ClientMessage && 420 event->xclient.data.l[0] != wm_delete_window) { 421 XBell (XtDisplay(w), 0); 422 return; 423 } 424 XCloseDisplay (XtDisplay(w)); 425 exit (0); 426} 427#endif 428