diff options
Diffstat (limited to 'b4light.c')
-rw-r--r-- | b4light.c | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/b4light.c b/b4light.c new file mode 100644 index 0000000..18263cd --- /dev/null +++ b/b4light.c @@ -0,0 +1,426 @@ +/* + * $XConsortium: b4light.c,v 1.3 94/04/17 20:59:38 rws Exp $ + * +Copyright (c) 1992 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Keith Packard, MIT X Consortium + */ +/* $XFree86: xc/programs/beforelight/b4light.c,v 3.6 2003/02/17 23:43:25 herrb Exp $ */ + +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Cardinals.h> +#include <X11/extensions/scrnsaver.h> +#include <X11/Xcms.h> +#include <stdlib.h> +#include <time.h> + +#ifdef NOTDEF +static void quit (Widget w, XEvent *event, + String *params, Cardinal *num_params); + +static XtActionsRec beforedark_actions[] = { + { "quit", quit }, +}; + +static Atom wm_delete_window; +#endif + +static int ss_event, ss_error; + +static Display *display; +static Window root, saver; +static int screen; +static int scr_wid, scr_hei; +static Colormap cmap; +static GC gc, black_gc, erase_gc; +static int screen_saved; +static XtAppContext app_con; +static XtIntervalId interval; +static GC bit_1_gc, bit_0_gc; +static Bool filled = False; + +#define MAX_POINTS 16 + +typedef struct _moving { + int x, y, dx, dy; +} Moving; + +static Moving p[MAX_POINTS]; + +#define NUM_HISTORY 32 + +static XPoint history[NUM_HISTORY][MAX_POINTS]; +static Pixmap old_pixmaps[NUM_HISTORY]; +static unsigned long old_pixels[NUM_HISTORY]; +static int num_points = 3; +static int history_head, history_tail; +#define hist_bump(h) ((++(h) == NUM_HISTORY) ? ((h) = 0) : 0) + +#define NUM_COLORS 64 + +static unsigned long black_pixel; +static unsigned long pixels[NUM_COLORS]; +static int cur_pen = 0; + +static void +AllocateColors (void) +{ + double angle; + double step; + XcmsColor cms_color; + int i; + XColor hard, exact; + + XAllocNamedColor (display, cmap, "black", &hard, &exact); + black_pixel = hard.pixel; + step = 360.0 / NUM_COLORS; + for (i = 0; i < NUM_COLORS; i++) { + angle = i * step; + cms_color.spec.TekHVC.H = angle; + cms_color.spec.TekHVC.V = 75.0; + cms_color.spec.TekHVC.C = 75.0; + cms_color.format = XcmsTekHVCFormat; + XcmsAllocColor (display, cmap, &cms_color, XcmsRGBFormat); + pixels[i] = cms_color.pixel; + } +} + + +static void +StepPen (void) +{ + XSetForeground (display, gc, pixels[cur_pen]); + cur_pen++; + if (cur_pen == NUM_COLORS) + cur_pen = 0; +} + +static void +DrawPoints (Drawable draw, GC gc, XPoint *p, int n) +{ + XPoint xp[MAX_POINTS + 1]; + int i; + + switch (n) { + case 1: + XDrawPoint (display, draw, gc, p->x, p->y); + break; + case 2: + XDrawLine (display, draw, gc, p[0].x, p[0].y, p[1].x, p[1].y); + break; + default: + for (i = 0; i < n; i++) { + xp[i].x = p[i].x; xp[i].y = p[i].y; + } + xp[i].x = p[0].x; xp[i].y = p[0].y; + if (filled) + XFillPolygon (display, draw, gc, xp, i+1, Complex, CoordModeOrigin); + else + XDrawLines (display, draw, gc, xp, i + 1, CoordModeOrigin); + } +} + +static void +Draw (Moving *p, int n) +{ + XPoint xp[MAX_POINTS]; + int i; + for (i = 0; i < n; i++) + { + xp[i].x = p[i].x; xp[i].y = p[i].y; + } + old_pixels[history_head] = pixels[cur_pen]; + StepPen (); + DrawPoints (saver, gc, xp, n); + if (filled) + { + XFillRectangle (display, old_pixmaps[history_head], bit_0_gc, + 0, 0, scr_wid, scr_hei); + DrawPoints (old_pixmaps[history_head], bit_1_gc, xp, n); + for (i = history_tail; i != history_head; hist_bump(i)) + DrawPoints (old_pixmaps[i], bit_0_gc, xp, n); + } +} + +static void +Erase (XPoint *p, int n) +{ + if (filled) { + XSetForeground (display, erase_gc, black_pixel ^ old_pixels[history_tail]); + XCopyPlane (display, old_pixmaps[history_tail], saver, erase_gc, + 0, 0, scr_wid, scr_hei, 0, 0, 1); + } + else + DrawPoints (saver, black_gc, p, n); +} + +#define STEP_MAX 32 + +static int +RandomStep (void) +{ + return (rand () % STEP_MAX) + 1; +} + +static void +StepMoving (Moving *m) +{ + int maxx, maxy; + + maxx = DisplayWidth (display, screen); + maxy = DisplayHeight (display, screen); + m->x += m->dx; + if (m->x <= 0) { + m->x = 0; + m->dx = RandomStep (); + } + if (m->x >= maxx) { + m->x = maxx - 1; + m->dx = -RandomStep (); + } + m->y += m->dy; + if (m->y <= 0) { + m->y = 0; + m->dy = RandomStep (); + } + if (m->y >= maxy) { + m->y = maxy - 1; + m->dy = -RandomStep (); + } +} + +static void +StepPoints (void) +{ + int i; + + for (i = 0; i < num_points; i++) + StepMoving (&p[i]); + hist_bump(history_head); + if (history_tail == history_head) + { + Erase (history[history_tail], num_points); + hist_bump(history_tail); + } + Draw (p, num_points); + for (i = 0; i < num_points; i++) + { + history[history_head][i].x = p[i].x; + history[history_head][i].y = p[i].y; + } +} + +static void +StartPoints (void) +{ + history_head = history_tail = 0; +} + +static void +Timeout (XtPointer closure, XtIntervalId *id) +{ + if (screen_saved) + { + StepPoints (); + interval = XtAppAddTimeOut (app_con, 50, Timeout, NULL); + } +} + +static void +StartSaver (void) +{ + if (screen_saved) + return; + screen_saved = True; + StartPoints (); + StepPoints (); + interval = XtAppAddTimeOut (app_con, 50, Timeout, NULL); +} + +static void +StopSaver (void) +{ + if (!screen_saved) + return; + screen_saved = False; +} + +static int +ignoreError (Display *display, XErrorEvent *error) +{ + return 0; +} + +int +main(int argc, char *argv[]) +{ + Widget toplevel; + XEvent event; + XScreenSaverNotifyEvent *sevent; + XSetWindowAttributes attr; + XScreenSaverInfo *info; + unsigned long mask; + Pixmap blank_pix; + XColor dummyColor; + XID kill_id; + Atom kill_type; + int i; + int (*oldHandler)(); + Window r; + int x, y; + unsigned int w, h, b, d; + Status s; + +#if !defined(X_NOT_POSIX) + srand((int)time((time_t *)NULL)); +#else + srand((int)time((int *)NULL)); +#endif + + toplevel = XtAppInitialize (&app_con, "Beforelight", NULL, ZERO, + &argc, argv, NULL, NULL, ZERO); + display = XtDisplay (toplevel); + root = DefaultRootWindow (display); + screen = DefaultScreen (display); + scr_wid = DisplayWidth (display, screen); + scr_hei = DisplayHeight (display, screen); + if (!XScreenSaverQueryExtension (display, &ss_event, &ss_error)) + exit (1); +#ifdef NOTDEF + XtAppAddActions (app_con, beforedark_actions, XtNumber(beforedark_actions)); + + /* + * This is a hack so that f.delete will do something useful in this + * single-window application. + */ + XtOverrideTranslations(toplevel, + XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()")); + + XtCreateManagedWidget ("label", labelWidgetClass, toplevel, NULL, ZERO); + XtRealizeWidget (toplevel); + wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", + False); + (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), + &wm_delete_window, 1); + +#endif + oldHandler = XSetErrorHandler (ignoreError); + if (XScreenSaverGetRegistered (display, screen, &kill_id, &kill_type)) { + s = XGetGeometry(display, kill_id, &r, &x, &y, &w, &h, &b, &d); + if (s == True && r == root && w == 1 && h == 1 && d == 1) { + /* Try to clean up existing saver & resources */ + XKillClient (display, kill_id); + XScreenSaverUnregister(display, screen); + } + } + XSync(display, FALSE); + XSetErrorHandler(oldHandler); + XScreenSaverSelectInput (display, root, ScreenSaverNotifyMask); +#ifdef NOTDEF + cmap = XCreateColormap (display, root, DefaultVisual (display, screen), AllocNone); +#else + cmap = DefaultColormap (display, screen); +#endif + AllocateColors(); + blank_pix = XCreatePixmap (display, root, 1, 1, 1); + XScreenSaverRegister (display, screen, (XID) blank_pix, XA_PIXMAP); + bit_0_gc = XCreateGC (display, blank_pix, 0, 0); + XSetForeground (display, bit_0_gc, 0); + bit_1_gc = XCreateGC (display, blank_pix, 0, 0); + XSetForeground (display, bit_1_gc, ~0); + XFillRectangle (display, blank_pix, bit_0_gc, 0, 0, 1, 1); + info = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (display, root, info); + mask = 0; + attr.colormap = cmap; + mask |= CWColormap; + attr.background_pixel = black_pixel; + mask |= CWBackPixel; + attr.cursor = XCreatePixmapCursor (display, blank_pix, blank_pix, &dummyColor, &dummyColor, 0, 0); + mask |= CWCursor; + XScreenSaverSetAttributes (display, root, 0, 0, + DisplayWidth (display, screen), DisplayHeight(display, screen), 0, + CopyFromParent, CopyFromParent, CopyFromParent, mask, &attr); + XSync (display, False); + gc = XCreateGC (display, root, 0, 0); + black_gc = XCreateGC (display, root, 0, 0); + XSetForeground (display, black_gc, black_pixel); + if (filled) + { + erase_gc = XCreateGC (display, root, 0, 0); + XSetBackground (display, erase_gc, 0); + XSetFunction (display, erase_gc, GXxor); + XSetGraphicsExposures (display, erase_gc, False); + for (i = 0; i < NUM_HISTORY; i++) + old_pixmaps[i] = XCreatePixmap (display, root, scr_wid, scr_hei, 1); + } + XSetErrorHandler (ignoreError); + saver = info->window; + if (info->state == ScreenSaverOn) + { + if (info->kind != ScreenSaverExternal) + { + XResetScreenSaver (display); + XActivateScreenSaver (display); + } + StartSaver (); + } + for (;;) + { + XtAppNextEvent (app_con, &event); + if (event.type == ss_event) { + sevent = (XScreenSaverNotifyEvent *) &event; + if (sevent->state == ScreenSaverOn) { + if (sevent->kind != ScreenSaverExternal) { + XResetScreenSaver (display); + XActivateScreenSaver (display); + } else { + StartSaver (); + } + } else if (sevent->state == ScreenSaverOff) { + StopSaver (); + } + } else { + XtDispatchEvent(&event); + } + } +} + +#ifdef NOTDEF +static void +quit (Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + if (event->type == ClientMessage && + event->xclient.data.l[0] != wm_delete_window) { + XBell (XtDisplay(w), 0); + return; + } + XCloseDisplay (XtDisplay(w)); + exit (0); +} +#endif |