b4light.c revision caec6540
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#include <X11/Xaw/Cardinals.h> 38#endif 39#include <X11/extensions/scrnsaver.h> 40#include <X11/Xcms.h> 41#include <stdlib.h> 42#include <time.h> 43 44#ifndef ZERO 45# define ZERO ((Cardinal)0) 46#endif 47 48#ifdef NOTDEF 49static void quit (Widget w, XEvent *event, 50 String *params, Cardinal *num_params); 51 52static XtActionsRec beforedark_actions[] = { 53 { "quit", quit }, 54}; 55 56static Atom wm_delete_window; 57#endif 58 59static int ss_event, ss_error; 60 61static Display *display; 62static Window root, saver; 63static int screen; 64static int scr_wid, scr_hei; 65static Colormap cmap; 66static GC gc, black_gc, erase_gc; 67static int screen_saved; 68static XtAppContext app_con; 69static GC bit_1_gc, bit_0_gc; 70static Bool filled = False; 71 72#define MAX_POINTS 16 73 74typedef struct _moving { 75 int x, y, dx, dy; 76} Moving; 77 78static Moving p[MAX_POINTS]; 79 80#define NUM_HISTORY 32 81 82static XPoint history[NUM_HISTORY][MAX_POINTS]; 83static Pixmap old_pixmaps[NUM_HISTORY]; 84static unsigned long old_pixels[NUM_HISTORY]; 85static int num_points = 3; 86static int history_head, history_tail; 87#define hist_bump(h) ((++(h) == NUM_HISTORY) ? ((h) = 0) : 0) 88 89#define NUM_COLORS 64 90 91static unsigned long black_pixel; 92static unsigned long pixels[NUM_COLORS]; 93static int cur_pen = 0; 94 95static void 96AllocateColors (void) 97{ 98 double angle; 99 double step; 100 XcmsColor cms_color; 101 int i; 102 XColor hard, exact; 103 104 XAllocNamedColor (display, cmap, "black", &hard, &exact); 105 black_pixel = hard.pixel; 106 step = 360.0 / NUM_COLORS; 107 for (i = 0; i < NUM_COLORS; i++) { 108 angle = i * step; 109 cms_color.spec.TekHVC.H = angle; 110 cms_color.spec.TekHVC.V = 75.0; 111 cms_color.spec.TekHVC.C = 75.0; 112 cms_color.format = XcmsTekHVCFormat; 113 XcmsAllocColor (display, cmap, &cms_color, XcmsRGBFormat); 114 pixels[i] = cms_color.pixel; 115 } 116} 117 118 119static void 120StepPen (void) 121{ 122 XSetForeground (display, gc, pixels[cur_pen]); 123 cur_pen++; 124 if (cur_pen == NUM_COLORS) 125 cur_pen = 0; 126} 127 128static void 129DrawPoints (Drawable draw, GC gc, XPoint *p, int n) 130{ 131 XPoint xp[MAX_POINTS + 1]; 132 int i; 133 134 switch (n) { 135 case 1: 136 XDrawPoint (display, draw, gc, p->x, p->y); 137 break; 138 case 2: 139 XDrawLine (display, draw, gc, p[0].x, p[0].y, p[1].x, p[1].y); 140 break; 141 default: 142 for (i = 0; i < n; i++) { 143 xp[i].x = p[i].x; xp[i].y = p[i].y; 144 } 145 xp[i].x = p[0].x; xp[i].y = p[0].y; 146 if (filled) 147 XFillPolygon (display, draw, gc, xp, i+1, Complex, CoordModeOrigin); 148 else 149 XDrawLines (display, draw, gc, xp, i + 1, CoordModeOrigin); 150 } 151} 152 153static void 154Draw (Moving *p, int n) 155{ 156 XPoint xp[MAX_POINTS]; 157 int i; 158 for (i = 0; i < n; i++) 159 { 160 xp[i].x = p[i].x; xp[i].y = p[i].y; 161 } 162 old_pixels[history_head] = pixels[cur_pen]; 163 StepPen (); 164 DrawPoints (saver, gc, xp, n); 165 if (filled) 166 { 167 XFillRectangle (display, old_pixmaps[history_head], bit_0_gc, 168 0, 0, scr_wid, scr_hei); 169 DrawPoints (old_pixmaps[history_head], bit_1_gc, xp, n); 170 for (i = history_tail; i != history_head; hist_bump(i)) 171 DrawPoints (old_pixmaps[i], bit_0_gc, xp, n); 172 } 173} 174 175static void 176Erase (XPoint *p, int n) 177{ 178 if (filled) { 179 XSetForeground (display, erase_gc, black_pixel ^ old_pixels[history_tail]); 180 XCopyPlane (display, old_pixmaps[history_tail], saver, erase_gc, 181 0, 0, scr_wid, scr_hei, 0, 0, 1); 182 } 183 else 184 DrawPoints (saver, black_gc, p, n); 185} 186 187#define STEP_MAX 32 188 189static int 190RandomStep (void) 191{ 192 return (rand () % STEP_MAX) + 1; 193} 194 195static void 196StepMoving (Moving *m) 197{ 198 int maxx, maxy; 199 200 maxx = DisplayWidth (display, screen); 201 maxy = DisplayHeight (display, screen); 202 m->x += m->dx; 203 if (m->x <= 0) { 204 m->x = 0; 205 m->dx = RandomStep (); 206 } 207 if (m->x >= maxx) { 208 m->x = maxx - 1; 209 m->dx = -RandomStep (); 210 } 211 m->y += m->dy; 212 if (m->y <= 0) { 213 m->y = 0; 214 m->dy = RandomStep (); 215 } 216 if (m->y >= maxy) { 217 m->y = maxy - 1; 218 m->dy = -RandomStep (); 219 } 220} 221 222static void 223StepPoints (void) 224{ 225 int i; 226 227 for (i = 0; i < num_points; i++) 228 StepMoving (&p[i]); 229 hist_bump(history_head); 230 if (history_tail == history_head) 231 { 232 Erase (history[history_tail], num_points); 233 hist_bump(history_tail); 234 } 235 Draw (p, num_points); 236 for (i = 0; i < num_points; i++) 237 { 238 history[history_head][i].x = p[i].x; 239 history[history_head][i].y = p[i].y; 240 } 241} 242 243static void 244StartPoints (void) 245{ 246 history_head = history_tail = 0; 247} 248 249static void 250Timeout (XtPointer closure, XtIntervalId *id) 251{ 252 if (screen_saved) 253 { 254 StepPoints (); 255 (void) XtAppAddTimeOut (app_con, 50, Timeout, NULL); 256 } 257} 258 259static void 260StartSaver (void) 261{ 262 if (screen_saved) 263 return; 264 screen_saved = True; 265 StartPoints (); 266 StepPoints (); 267 (void) XtAppAddTimeOut (app_con, 50, Timeout, NULL); 268} 269 270static void 271StopSaver (void) 272{ 273 if (!screen_saved) 274 return; 275 screen_saved = False; 276} 277 278static int 279ignoreError (Display *display, XErrorEvent *error) 280{ 281 return 0; 282} 283 284int 285main(int argc, char *argv[]) 286{ 287 Widget toplevel; 288 XEvent event; 289 XScreenSaverNotifyEvent *sevent; 290 XSetWindowAttributes attr; 291 XScreenSaverInfo *info; 292 unsigned long mask; 293 Pixmap blank_pix; 294 XColor dummyColor; 295 XID kill_id; 296 Atom kill_type; 297 int i; 298 int (*oldHandler)(Display*, XErrorEvent*); 299 Window r; 300 int x, y; 301 unsigned int w, h, b, d; 302 Status s; 303 304#if !defined(X_NOT_POSIX) 305 srand((int)time((time_t *)NULL)); 306#else 307 srand((int)time((int *)NULL)); 308#endif 309 310 toplevel = XtAppInitialize (&app_con, "Beforelight", NULL, ZERO, 311 &argc, argv, NULL, NULL, ZERO); 312 display = XtDisplay (toplevel); 313 root = DefaultRootWindow (display); 314 screen = DefaultScreen (display); 315 scr_wid = DisplayWidth (display, screen); 316 scr_hei = DisplayHeight (display, screen); 317 if (!XScreenSaverQueryExtension (display, &ss_event, &ss_error)) 318 exit (1); 319#ifdef NOTDEF 320 XtAppAddActions (app_con, beforedark_actions, XtNumber(beforedark_actions)); 321 322 /* 323 * This is a hack so that f.delete will do something useful in this 324 * single-window application. 325 */ 326 XtOverrideTranslations(toplevel, 327 XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); 328 329 XtCreateManagedWidget ("label", labelWidgetClass, toplevel, NULL, ZERO); 330 XtRealizeWidget (toplevel); 331 wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", 332 False); 333 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 334 &wm_delete_window, 1); 335 336#endif 337 oldHandler = XSetErrorHandler (ignoreError); 338 if (XScreenSaverGetRegistered (display, screen, &kill_id, &kill_type)) { 339 s = XGetGeometry(display, kill_id, &r, &x, &y, &w, &h, &b, &d); 340 if (s == True && r == root && w == 1 && h == 1 && d == 1) { 341 /* Try to clean up existing saver & resources */ 342 XKillClient (display, kill_id); 343 XScreenSaverUnregister(display, screen); 344 } 345 } 346 XSync(display, FALSE); 347 XSetErrorHandler(oldHandler); 348 XScreenSaverSelectInput (display, root, ScreenSaverNotifyMask); 349#ifdef NOTDEF 350 cmap = XCreateColormap (display, root, DefaultVisual (display, screen), AllocNone); 351#else 352 cmap = DefaultColormap (display, screen); 353#endif 354 AllocateColors(); 355 blank_pix = XCreatePixmap (display, root, 1, 1, 1); 356 XScreenSaverRegister (display, screen, (XID) blank_pix, XA_PIXMAP); 357 bit_0_gc = XCreateGC (display, blank_pix, 0, NULL); 358 XSetForeground (display, bit_0_gc, 0); 359 bit_1_gc = XCreateGC (display, blank_pix, 0, NULL); 360 XSetForeground (display, bit_1_gc, ~0); 361 XFillRectangle (display, blank_pix, bit_0_gc, 0, 0, 1, 1); 362 info = XScreenSaverAllocInfo (); 363 XScreenSaverQueryInfo (display, root, info); 364 mask = 0; 365 attr.colormap = cmap; 366 mask |= CWColormap; 367 attr.background_pixel = black_pixel; 368 mask |= CWBackPixel; 369 attr.cursor = XCreatePixmapCursor (display, blank_pix, blank_pix, &dummyColor, &dummyColor, 0, 0); 370 mask |= CWCursor; 371 XScreenSaverSetAttributes (display, root, 0, 0, 372 DisplayWidth (display, screen), DisplayHeight(display, screen), 0, 373 CopyFromParent, CopyFromParent, (Visual *)CopyFromParent, mask, &attr); 374 XSync (display, False); 375 gc = XCreateGC (display, root, 0, NULL); 376 black_gc = XCreateGC (display, root, 0, NULL); 377 XSetForeground (display, black_gc, black_pixel); 378 if (filled) 379 { 380 erase_gc = XCreateGC (display, root, 0, NULL); 381 XSetBackground (display, erase_gc, 0); 382 XSetFunction (display, erase_gc, GXxor); 383 XSetGraphicsExposures (display, erase_gc, False); 384 for (i = 0; i < NUM_HISTORY; i++) 385 old_pixmaps[i] = XCreatePixmap (display, root, scr_wid, scr_hei, 1); 386 } 387 XSetErrorHandler (ignoreError); 388 saver = info->window; 389 if (info->state == ScreenSaverOn) 390 { 391 if (info->kind != ScreenSaverExternal) 392 { 393 XResetScreenSaver (display); 394 XActivateScreenSaver (display); 395 } 396 StartSaver (); 397 } 398 for (;;) 399 { 400 XtAppNextEvent (app_con, &event); 401 if (event.type == ss_event) { 402 sevent = (XScreenSaverNotifyEvent *) &event; 403 if (sevent->state == ScreenSaverOn) { 404 if (sevent->kind != ScreenSaverExternal) { 405 XResetScreenSaver (display); 406 XActivateScreenSaver (display); 407 } else { 408 StartSaver (); 409 } 410 } else if (sevent->state == ScreenSaverOff) { 411 StopSaver (); 412 } 413 } else { 414 XtDispatchEvent(&event); 415 } 416 } 417} 418 419#ifdef NOTDEF 420static void 421quit (Widget w, XEvent *event, String *params, Cardinal *num_params) 422{ 423 if (event->type == ClientMessage && 424 event->xclient.data.l[0] != wm_delete_window) { 425 XBell (XtDisplay(w), 0); 426 return; 427 } 428 XCloseDisplay (XtDisplay(w)); 429 exit (0); 430} 431#endif 432