butterwo@cs.unc.edu (Jeff Butterworth) (02/01/91)
Submitted-by: butterwo@cs.unc.edu (Jeff Butterworth) Posting-number: Volume 11, Issue 12 Archive-name: xswarm/part01 This program animates a bunch of little line segments chasing a randomly accelerating line segment. The concept is simple, but the effect is pretty cute. By default, it comes up in a window, but it can be put in the root window too. In order to make it usable as a screen background, you can alter the delay between updates, making it use very little cpu time. One of the reasons why it doesn't use much cpu time is that it only uses integer arithmetic. This program has been tested successfully on a Sun4's, DECStation 3100's, and DECStation 5000's. The only thing you will probably have to change in the Makefile is the location of X include files. Try xswarm -h for help. Fiddle with the parameters. You can get really different effects! #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: xswarm.c xswarm.h vroot.h patchlevel.h Makefile Imakefile # xswarm.6 README # Wrapped by butterwo@oscar on Wed Jan 30 07:47:16 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'xswarm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xswarm.c'\" else echo shar: Extracting \"'xswarm.c'\" \(29074 characters\) sed "s/^X//" >'xswarm.c' <<'END_OF_FILE' X/* X** XSwarm X** ====== X** X** Purpose: Display a swarm of bees chasing a wasp. X** X** Features: uses only integer math X** can be put in the root window X** uses non-blocking delays to decrease cpu usage X** has no redeeming social value X** X** Comments: I used psychoII (I assume it's a derivative of ico.) as an X** an example of how to open up a window and draw some lines. X** Most of this program is now totally rewritten by me, but the X** initial window manager hints stuff is left over from the older X** program. X** X** The program meltdown was handy for learning how to take over X** the screen. X** X** Any comments, enhances, or fixes are welcome! X** X** Created: by Jeff Butterworth on 7/11/90 X** butterwo@cs.unc.edu X** X** Updated: by Jeff Butterworth on 1/4/91 X** X*/ X X/* These are needed for the nap function. */ X#include <sys/time.h> X#include <signal.h> X X/* X Includes */ X#include <X11/Xlib.h> X#include <X11/Xatom.h> X#include <X11/Xutil.h> X X/* This makes it work with virtual root window managers. */ X#include "vroot.h" X X/* Standard Includes */ X#include <stdio.h> X X/* For those of you who want to know what version you are using. */ X#include "patchlevel.h" X X/* Includes for this project. */ X#include "xswarm.h" X X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char *geometry = NULL; X X X Initialize(); X X Parse_Arguments(argc, argv, &geometry); X X /* The program acts as a screen saver if timeout is non-zero. */ X if (!timeout) X { X Create_Window(geometry); X Animate(); X } X else X { X Change_Screen_Saver(False); X while(TRUE) X { X Wait_For_Idleness(); X Create_Big_Window(); X Animate(); X } X } X} X X Xvoid XQuit(signal, code, scp, address) Xint signal, code; Xstruct sigcontext *scp; Xchar *address; X{ X if (timeout) X { X fprintf(stderr, "Restoring screen saver state.\n"); X Change_Screen_Saver(True); X } X X fprintf(stderr, "Terminating because of signal %d. ", signal); X switch (signal) X { X case SIGHUP: fprintf(stderr, "(Hangup)\n"); break; X case SIGINT: fprintf(stderr, "(Interrupt)\n"); break; X case SIGQUIT: fprintf(stderr, "(Quit)\n"); break; X case SIGILL: fprintf(stderr, "(Illegal Instruction)\n"); break; X case SIGFPE: fprintf(stderr, "(Floating Point Exception)\n"); break; X case SIGKILL: fprintf(stderr, "(Kill)\n"); break; X case SIGBUS: fprintf(stderr, "(Bus Error)\n"); break; X case SIGSEGV: fprintf(stderr, "(Segmentation Violation)\n"); break; X case SIGSYS: fprintf(stderr, "(Bad Argument to Sys Call)\n"); break; X case SIGTERM: fprintf(stderr, "(Termination from Kill)\n"); break; X case SIGSTOP: fprintf(stderr, "(Stop not from tty)\n"); break; X case SIGTSTP: fprintf(stderr, "(Stop from tty)\n"); break; X case SIGXCPU: fprintf(stderr, "(Exceeded CPU Time Limit)\n"); break; X default: fprintf(stderr, "(Unexpected Signal)\n"); X } X X exit(-signal); X} X X Xvoid XInitialize() X{ X signal(SIGHUP, Quit); X signal(SIGINT, Quit); X signal(SIGQUIT, Quit); X signal(SIGILL, Quit); X signal(SIGFPE, Quit); X signal(SIGKILL, Quit); X signal(SIGBUS, Quit); X signal(SIGSEGV, Quit); X signal(SIGSYS, Quit); X signal(SIGTERM, Quit); X signal(SIGSTOP, Quit); X if (timeout) signal(SIGTSTP, Quit); X signal(SIGXCPU, Quit); X} X X X/* Parse_Arguments() */ X/* Analyze command line arguments and set variables accordingly. */ X Xvoid XParse_Arguments(argc, argv, geometry) Xint argc; Xchar **argv; Xchar **geometry; X{ X /* These variables are used to analyze the command line parameters. */ X int option; X extern int optind; X extern char *optarg; X X int bits; /* Used to set window geometry. */ X X X /* Check the command line. */ X while ((option = getopt(argc,argv,"hq?vprVxt:d:g:D:b:a:s:A:S:B:w:c:C:")) X != EOF) X { X switch (option) X { X case 'v': X verbose = TRUE; X break; X case 'p': X pointer = TRUE; X break; X case 'V': X stay_in_front = TRUE; X break; X case 'r': X root = TRUE; X break; X case 'x': X xor = TRUE; X break; X case 't': X timeout = atoi(optarg); X break; X case 'g': X *geometry = optarg; X break; X case 'd': X display.dname = optarg; X break; X case 'b': X bees = atoi(optarg); X break; X case 'a': X bee_acc = atoi(optarg); X break; X case 's': X bee_vel = atoi(optarg); X break; X case 'A': X wasp_acc = atoi(optarg); X break; X case 'S': X wasp_vel = atoi(optarg); X break; X case 'D': X delay = atoi(optarg) * 1000; /* convert to microseconds */ X break; X case 'B': X border = atoi(optarg); X break; X case 'w': X wasp_color = optarg; X break; X case 'c': X bee_color = optarg; X break; X case 'C': X bg_color = optarg; X break; X case 'h': X case 'q': X case '?': X Usage(*argv); X HandleError("The command line parameters were incorrect.", X FATAL); X break; X } X } X X /* Display the arguments. */ X if (verbose) X { X printf("Here are the current settings...\n"); X if (xor) X printf("The logical raster operation GXxor is being used.\n"); X else X printf("The logical raster operation GXcopy is being used.\n"); X if (stay_in_front) X printf("The bees will try to stay in the clear area of the screen.\n"); X printf("There are %d bees.\n", bees); X printf("Bee acceleration is %d pixels per frame per frame.\n",bee_acc); X printf("Bee speed limit is %d pixels per frame.\n", bee_vel); X printf("Wasp acceleration is %d pixels per frame per frame.\n", X wasp_acc); X printf("Wasp speed limit is %d pixels per frame.\n", wasp_vel); X printf("The non-blocking delay is %d milliseconds per frame.\n", X delay / 1000); X if (timeout) printf("Screen saved after %d seconds.\n", timeout); X printf("The wasp can't go within %d pixels of the window edge.\n", X border); X printf("The wasp color is \"%s\"\n", wasp_color); X printf("The bee color is \"%s\"\n", bee_color); X printf("The background color is \"%s\"\n", bg_color); X } X X /* Open the display. */ X if (!(display.dpy = XOpenDisplay(display.dname))) X { X HandleError("Cannot open display.\n"); X exit(-1); X } X X /* Record the screen number and root window. */ X display.screen = DefaultScreen(display.dpy); X display.root = RootWindow(display.dpy, display.screen); X X /* Set the colors. */ X display.cmap = XDefaultColormap(display.dpy, display.screen); X if (!display.cmap) HandleError("There was no default colormap!", FATAL); X X if (wasp_color == NULL) X display.wasp =WhitePixel(display.dpy, display.screen); X else X display.wasp = GetColor(&display, wasp_color, NULL); X X if (bee_color == NULL) X display.bee =WhitePixel(display.dpy, display.screen); X else X display.bee = GetColor(&display, bee_color, NULL); X X if (bg_color == NULL) X display.bg = BlackPixel(display.dpy, display.screen); X else X display.bg = GetColor(&display, bg_color, &(display.bg_xcolor)); X X /* Set up window size. */ X if (!root && !timeout) X { X winW = WINWIDTH; X winH = WINHEIGHT; X winX = (DisplayWidth(display.dpy, display.screen) X - winW) / 2; X winY = (DisplayHeight(display.dpy, display.screen) X - winH) / 2; X if (*geometry != NULL) X XParseGeometry(*geometry, &winX, &winY, &winW, &winH); X } X else X { X winW = DisplayWidth(display.dpy, display.screen); X winH = DisplayHeight(display.dpy, display.screen); X winX = 0; X winY = 0; X } X X /* If screen saving is on, then watch for events everywhere. */ X /* Traverse the window tree. */ X if (timeout) Traverse_Tree(display.dpy, display.root); X} X X X/* Change_Screen_Saver() */ X/* Turn the server's screen saver on or off. */ X/* This routine should be called with on=False before it is called */ X/* with on=True. */ X Xvoid XChange_Screen_Saver(on) Xint on; /* True or False */ X{ X static int timeout, interval, blanking, exposures; X static int set_yet = FALSE; X X if (on) X { X if (set_yet) X { X /* Restore the old settings. */ X XSetScreenSaver(display.dpy, timeout, interval, blanking,exposures); X XActivateScreenSaver(display.dpy); X XResetScreenSaver(display.dpy); X XSync(display.dpy, False); X } X } X else X { X /* Save the old settings and turn off the server's screen saver. */ X XGetScreenSaver(display.dpy, &timeout, &interval, &blanking,&exposures); X XSetScreenSaver(display.dpy, 0, 0, DefaultBlanking, DefaultExposures); X XResetScreenSaver(display.dpy); X set_yet = TRUE; X } X} X X X/* Traverse_Tree() */ X/* Select some events from every single window that is a decendent */ X/* of "current". */ X Xvoid XTraverse_Tree(display, current) XDisplay *display; XWindow current; X{ X Window my_root, parent, *children; X unsigned int num_children; X int i; X X X /* Watch for signs of life from the user in this window. */ X XSelectInput(display, current, ALIVE_MASK); X X /* Who are my kids? */ X XQueryTree(display, current, &my_root, &parent, &children, X &num_children); X X /* Examine all of the children too. */ X for (i = 0 ; i < num_children ; i++) X Traverse_Tree( display, children[i] ); X X /* Let's not waste any memory. */ X XFree( (char *) children); X} X X X/* Wait_For_Idleness() */ X/* Wait for "timeout" seconds of user inactivity. */ X Xvoid XWait_For_Idleness() X{ X int watching = TRUE; X int found; X int timer = 0; X XEvent event; X X while( watching ) X { X if (timer >= timeout) return; X X sleep(1); X timer++; X X found = XCheckIfEvent(display.dpy, &event, Dummy_Predicate, NULL); X if (found) timer = 0; X X /* Flush events. */ X while (found) X { X switch (event.type) X { X /* Watch for events in new windows too. */ X case CreateNotify: X { X XCreateWindowEvent *ev = (XCreateWindowEvent *) &event; X X XSelectInput(display.dpy, ev->window, ALIVE_MASK); X Traverse_Tree(display.dpy, ev->window); X } X break; X default: X break; X } X /* Check for the existence of more events. */ X found = XCheckIfEvent(display.dpy, &event, Dummy_Predicate, NULL); X } X } X} X X XBool XDummy_Predicate(display, event, arg) XDisplay *display; XXEvent *event; Xchar *arg; X{ X return(True); X} X X Xvoid XCreate_Big_Window() X{ X /* Window Attributes */ X unsigned long valuemask; X XSetWindowAttributes xswa; X X XSizeHints sizehint; X XWMHints wmhints; X unsigned char wname[32]; /* Window Name */ X X /* First time. */ X static int first = TRUE; X X /* Cursor Stuff */ X static Cursor cursor; X X X /* Turn the cursor the color of the background. (Invisible) */ X if (first) X { X /* I don't care which cursor I get. */ X cursor = XCreateFontCursor(display.dpy, 0); X X XRecolorCursor(display.dpy, cursor, &(display.bg_xcolor), X &(display.bg_xcolor)); X first = FALSE; X } X X /* Create a screen sized window. */ X xswa.cursor = cursor; X xswa.background_pixel = display.bg; X xswa.override_redirect = True; X xswa.do_not_propagate_mask = KeyPressMask | KeyReleaseMask | X ButtonPressMask | ButtonReleaseMask; X valuemask = CWCursor | CWBackPixel | CWOverrideRedirect | CWDontPropagate; X display.win = XCreateWindow(display.dpy, display.root, X 0, 0, X winW, winH, 0, X DefaultDepth(display.dpy, display.screen), X InputOutput, DefaultVisual(display.dpy, display.screen), X valuemask, &xswa); X X XMapWindow(display.dpy, display.win); X X /* Event Mask */ X XSelectInput(display.dpy, display.win, KeyPressMask | PointerMotionMask); X X /* Set up the bees' graphics context. */ X display.bee_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XSetForeground(display.dpy, display.bee_gc, display.bee); X XSetBackground(display.dpy, display.bee_gc, display.bg); X X /* Set up the wasp's graphics context. */ X display.wasp_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XSetForeground(display.dpy, display.wasp_gc, display.wasp); X XSetBackground(display.dpy, display.wasp_gc, display.bg); X X /* Set up an erasing graphics context. */ X display.erase_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XCopyGC(display.dpy, display.bee_gc, 0xffffffff, display.erase_gc); X XSetForeground(display.dpy, display.erase_gc, display.bg); X X /* Set up an xor wasp graphics context. */ X display.wasp_xor_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XCopyGC(display.dpy, display.wasp_gc, 0xffffffff, display.wasp_xor_gc); X XSetFunction(display.dpy, display.wasp_xor_gc, GXxor); X XSetForeground(display.dpy, display.wasp_xor_gc, display.bg); X X /* Set up an xor bee graphics context. */ X display.bee_xor_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XCopyGC(display.dpy, display.bee_gc, 0xffffffff, display.bee_xor_gc); X XSetFunction(display.dpy, display.bee_xor_gc, GXxor); X XSetForeground(display.dpy, display.bee_xor_gc, display.bg); X X /* Clear the background. */ X XFillRectangle(display.dpy, display.win, display.erase_gc, X 0,0, winW, winH); X} X X X X/* Create_Window() */ X/* Create the window, making sure to set it up correctly. */ X Xvoid XCreate_Window(geometry) Xchar *geometry; X{ X XSetWindowAttributes xswa; X XSizeHints sizehint; X XWMHints wmhints; X unsigned char wname[256]; /* Window Name */ X X X if (!root) X { X xswa.event_mask = 0; X xswa.background_pixel = display.bg; X display.win = XCreateWindow(display.dpy, display.root, X winX, winY, X winW, winH, 0, X DefaultDepth(display.dpy, display.screen), X InputOutput, DefaultVisual(display.dpy, display.screen), X CWEventMask | CWBackPixel , &xswa); X X sizehint.x = winX; X sizehint.y = winY; X sizehint.width = winW; X sizehint.height = winH; X sizehint.min_width = 2*border + 20; X sizehint.min_height = 2*border + 20; X if (geometry != NULL) X sizehint.flags = USPosition | USSize | PMinSize; X else X sizehint.flags = PPosition | PSize | PMinSize; X XSetNormalHints(display.dpy, display.win, &sizehint); X X display.protocol_atom = XInternAtom(display.dpy, "WM_PROTOCOLS", False); X display.kill_atom = XInternAtom(display.dpy, "WM_DELETE_WINDOW", False); X#ifdef X11R4 X XSetWMProtocols(display.dpy, display.win, &display.kill_atom, 1); X#endif X X /* Title */ X sprintf( (char *) wname, "XSwarm, Version %s, by Jeff Butterworth", X VERSION); X XChangeProperty(display.dpy, display.win, X XA_WM_NAME, XA_STRING, 8, PropModeReplace, wname, X strlen(wname)); X X /* Window Manager Hints (This is supposed to make input work.) */ X wmhints.flags = InputHint; X wmhints.input = True; X XSetWMHints(display.dpy, display.win, &wmhints); X X XMapWindow(display.dpy, display.win); X } X else X { X display.win = display.root; X xswa.backing_store = Always; X XChangeWindowAttributes(display.dpy, display.win, X CWBackingStore, &xswa); X } X X /* Event Mask */ X if (root) X XSelectInput(display.dpy, display.win, X KeyPressMask | StructureNotifyMask); X else X XSelectInput(display.dpy, display.win, X KeyPressMask | ButtonPressMask | StructureNotifyMask); X X /* Set up the bees' graphics context. */ X display.bee_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XSetForeground(display.dpy, display.bee_gc, display.bee); X XSetBackground(display.dpy, display.bee_gc, display.bg); X X /* Set up the wasp's graphics context. */ X display.wasp_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XSetForeground(display.dpy, display.wasp_gc, display.wasp); X XSetBackground(display.dpy, display.wasp_gc, display.bg); X X /* Set up an erasing graphics context. */ X display.erase_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XCopyGC(display.dpy, display.bee_gc, 0xffffffff, display.erase_gc); X XSetForeground(display.dpy, display.erase_gc, display.bg); X X /* Set up an xor wasp graphics context. */ X display.wasp_xor_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XCopyGC(display.dpy, display.wasp_gc, 0xffffffff, display.wasp_xor_gc); X XSetFunction(display.dpy, display.wasp_xor_gc, GXxor); X XSetForeground(display.dpy, display.wasp_xor_gc, display.bg); X X /* Set up an xor bee graphics context. */ X display.bee_xor_gc = XCreateGC(display.dpy, display.win, 0, NULL); X XCopyGC(display.dpy, display.bee_gc, 0xffffffff, display.bee_xor_gc); X XSetFunction(display.dpy, display.bee_xor_gc, GXxor); X XSetForeground(display.dpy, display.bee_xor_gc, display.bg); X X /* Clear the background. */ X if (!xor) X { X XSetWindowBackground(display.dpy, display.win, display.bg); X XFillRectangle(display.dpy, display.win, display.erase_gc, X 0,0, winW, winH); X } X} X X X/* Animate() */ X/* Move the swarm around. */ X Xvoid XAnimate() X{ X register int b; /* bee index */ X XSegment *segs; /* bee lines */ X XSegment *old_segs; /* old bee lines */ X int *x, *y; /* bee positions x[time][bee#] */ X int *xv, *yv; /* bee velocities xv[bee#] */ X int wx[3], wy[3]; /* wasp positions */ X int wxv, wyv; /* wasp velocity */ X XEvent xev; X int dx,dy,distance; X int init = TRUE; X X /* These variables are related to bouncing off of other windows. */ X int testx, testy; X int BehindWindow; /* TRUE if wasp is behind a window. */ X Window child; X X /* These variables are related to mouse control of the wasp. */ X int garbage_int; /* for XQueryPointer */ X Window garbage_win; /* ...likewise */ X X X X /* Get the random number generator ready. */ X srandom(getpid()); X X /* Allocate memory. */ X segs = (XSegment *) malloc(sizeof(XSegment) * bees); X old_segs = (XSegment *) malloc(sizeof(XSegment) * bees); X x = (int *) malloc(sizeof(int) * bees * times); X y = (int *) malloc(sizeof(int) * bees * times); X xv = (int *) malloc(sizeof(int) * bees); X yv = (int *) malloc(sizeof(int) * bees); X X /* Initialize point positions, velocities, etc. */ X X /* wasp */ X if (pointer) X { X XQueryPointer(display.dpy, display.win, &garbage_win, X &garbage_win, &garbage_int, &garbage_int, X &(wx[0]), &(wy[0]), (unsigned int *) &garbage_int); X } X else X { X wx[0] = BORDER + random() % (winW - 2*BORDER); X wy[0] = BORDER + random() % (winH - 2*BORDER); X } X wx[1] = wx[0]; X wy[1] = wy[0]; X wxv = 0; X wyv = 0; X X /* bees */ X for (b = 0 ; b < bees ; b++) X { X X(0,b) = random() % winW; X X(1,b) = X(0,b); X Y(0,b) = random() % winH; X Y(1,b) = Y(0,b); X xv[b] = RAND(7); X yv[b] = RAND(7); X } X X /* This checks to see if we've gone behind a window. */ X if (stay_in_front) X { X XTranslateCoordinates(display.dpy, display.win, display.win, X wx[0], wy[0], &testx, &testy, &child); X BehindWindow = (child != 0); X } X X /* Seemingly endless loop. */ X while (TRUE) X { X /* <=- Wasp -=> */ X /* Age the position arrays. */ X wx[2] = wx[1]; X wx[1] = wx[0]; X wy[2] = wy[1]; X wy[1] = wy[0]; X X if (pointer) X { X XQueryPointer(display.dpy, display.win, &garbage_win, X &garbage_win, &garbage_int, &garbage_int, X &wx[0], &wy[0], (unsigned int *) &garbage_int); X } X else X { X /* Accelerate */ X wxv += RAND(wasp_acc); X wyv += RAND(wasp_acc); X X /* Speed Limit Checks */ X if (wxv > wasp_vel) wxv = wasp_vel; X if (wxv < -wasp_vel) wxv = -wasp_vel; X if (wyv > wasp_vel) wyv = wasp_vel; X if (wyv < -wasp_vel) wyv = -wasp_vel; X X /* Move */ X wx[0] = wx[1] + wxv; X wy[0] = wy[1] + wyv; X X Bounce_Against_Windows(wx, wy, &wxv, &wyv, BehindWindow); X X /* Bounce Checks */ X if ((wx[0] < border) || (wx[0] > winW-border-1)) X { X wxv = -wxv; X wx[0] += wxv<<1; X } X if ((wy[0] < border) || (wy[0] > winH-border-1)) X { X wyv = -wyv; X wy[0] += wyv<<1; X } X } X X /* Don't let things settle down. */ X xv[random() % bees] += RAND(3); X yv[random() % bees] += RAND(3); X X /* <=- Bees -=> */ X for (b = 0 ; b < bees ; b++) X { X /* Age the arrays. */ X X(2,b) = X(1,b); X X(1,b) = X(0,b); X Y(2,b) = Y(1,b); X Y(1,b) = Y(0,b); X X /* Accelerate */ X dx = wx[1] - X(1,b); X dy = wy[1] - Y(1,b); X distance = abs(dx)+abs(dy); /* approximation */ X if (distance == 0) distance = 1; X xv[b] += (dx*bee_acc)/distance; X yv[b] += (dy*bee_acc)/distance; X X /* Speed Limit Checks */ X if (xv[b] > bee_vel) xv[b] = bee_vel; X if (xv[b] < -bee_vel) xv[b] = -bee_vel; X if (yv[b] > bee_vel) yv[b] = bee_vel; X if (yv[b] < -bee_vel) yv[b] = -bee_vel; X X /* Move */ X X(0,b) = X(1,b) + xv[b]; X Y(0,b) = Y(1,b) + yv[b]; X X /* Fill the segment lists. */ X segs[b].x1 = X(0,b); X segs[b].y1 = Y(0,b); X segs[b].x2 = X(1,b); X segs[b].y2 = Y(1,b); X old_segs[b].x1 = X(1,b); X old_segs[b].y1 = Y(1,b); X old_segs[b].x2 = X(2,b); X old_segs[b].y2 = Y(2,b); X } X X /* Erase previous, draw current, sync for smoothness. */ X X /* Again check to see if the wasp is behind a window. */ X if (stay_in_front) X { X XTranslateCoordinates(display.dpy, display.win, display.win, X wx[0], wy[0], X &testx, &testy, &child); X BehindWindow = (child != 0); X } X X /* Wasp */ X if (xor) X { X if (init == FALSE) X XDrawLine(display.dpy, display.win, display.wasp_xor_gc, X wx[1], wy[1], wx[2], wy[2]); X XDrawLine(display.dpy, display.win, display.wasp_xor_gc, X wx[0], wy[0], wx[1], wy[1]); X } X else X { X if (init == FALSE) X XDrawLine(display.dpy, display.win, display.erase_gc, X wx[1], wy[1], wx[2], wy[2]); X XDrawLine(display.dpy, display.win, display.wasp_gc, X wx[0], wy[0], wx[1], wy[1]); X } X X /* Bees */ X if (xor) X { X if (init == FALSE) X XDrawSegments(display.dpy, display.win, display.bee_xor_gc, X old_segs, bees); X else X init = FALSE; X XDrawSegments(display.dpy, display.win, display.bee_xor_gc, X segs, bees); X } X else X { X if (init == FALSE) X XDrawSegments(display.dpy, display.win, display.erase_gc, X old_segs, bees); X else X init = FALSE; X XDrawSegments(display.dpy, display.win, display.bee_gc, segs, bees); X } X X XSync(display.dpy, False); X X /* Check for events. */ X if (XPending(display.dpy)) X { X XNextEvent(display.dpy, &xev); X HandleEvent(&xev); X X /* Make sure the wasp is within the window. */ X if (wx[0] < border) wx[0] = border; X if (wx[0] > winW-border-1) wx[0] = winW-border-1; X if (wy[0] < border) wy[0] = border; X if (wy[0] > winH-border-1) wy[0] = winH-border-1; X } X X /* Clean up and shut down. */ X if (stop) X { X stop = FALSE; /* reset the "stop" variable */ X X if (xor) X { X XDrawSegments(display.dpy, display.win, display.bee_xor_gc, X segs, bees); X XDrawLine(display.dpy, display.win, display.wasp_xor_gc, X wx[0], wy[0], wx[1], wy[1]); X } X else X XFillRectangle(display.dpy, display.win, display.erase_gc, X 0,0, winW, winH); X XSync(display.dpy, 0); X X if (!root) X { X int xc, yc; X unsigned int width, height, border_width, depth; X Window root_window; X X /* This is for debugging. */ X /* I was finding that when using xswarm as a screen */ X /* saver, I would come back after an hour, and it */ X /* would be in a little shriveled window in the */ X /* corner. */ X#ifdef DEBUG X XGetGeometry(display.dpy, display.win, &root_window, X &xc, &yc, &width, &height, &border_width, &depth); X printf("Window info: x,y,width,height,border,depth\n"); X printf("%d,%d %d,%d %d %d\n",xc,yc,width,height, X border_width,depth); X printf("Wasp x,y xv,yv: %d,%d %d,%d\n",wx[0],wy[0],wxv,wyv); X printf("Bee 1 x,y xv,yv: %d %d %d %d\n", X X(0,1),Y(0,1), X *(xv+1),yv[1]); X#endif X X XDestroyWindow(display.dpy, display.win); X } X X return; X } X X /* Delay so we don't use all of the cpu time. */ X#ifdef HP_UX X if (delay != 0) usleep(delay); X#else X if (delay != 0) nap(0,delay); X#endif X } X} X X XBounce_Against_Windows(wx, wy, wxv, wyv, BehindWindow) Xint wx[3], wy[3]; Xint *wxv, *wyv; Xint BehindWindow; X{ X int testx, testy; X Window child; X X X /* This makes the wasp avoid moving behind windows. */ X if (root && stay_in_front && !BehindWindow) X { X XTranslateCoordinates(display.dpy, display.win, display.win, X wx[0], wy[0], &testx, &testy, &child); X if (child != 0) X { X XTranslateCoordinates(display.dpy, display.win, display.win, X wx[0] - (*wxv), wy[0], &testx, &testy, &child); X if (child == 0) /* vertical surface */ X { X wx[0] = wx[1] - (*wxv); /* undo the jump into the window */ X *wxv = -(*wxv); /* bounce in x direction */ X } X else X { X XTranslateCoordinates(display.dpy, display.win,display.win, X wx[0], wy[0] - (*wyv), &testx, &testy, &child); X if (child == 0) /* horizontal surface */ X { X wy[0] = wy[1] - (*wyv); /* undo the jump into the window */ X *wyv = - (*wyv); /* bounce in y direction */ X } X else X { /* concave corner */ X wx[0] = wx[1] - (*wxv); /* undo the jump into the corner */ X wy[0] = wy[1] - (*wyv); X *wxv = - (*wxv); /* reverse direction */ X *wyv = - (*wyv); X } X } X } X } X} X X X/* X** HandleEvent() X** X** process X events X*/ X XHandleEvent(event) XXEvent *event; X{ X /* If the screen saver is on, then watch for signs of activity. */ X if (((event->type == KeyPress) || (event->type == MotionNotify)) && X (timeout)) stop = TRUE; X X switch (event->type) X { X case ClientMessage: /* sent by f.delete from twm */ X { X XClientMessageEvent *ev = (XClientMessageEvent *) event; X X printf("Client message received.\n"); X if (ev->message_type == display.protocol_atom && X ev->data.l[0] == display.kill_atom) X stop = TRUE; X } X break; X case ConfigureNotify: X { X XConfigureEvent *ev = (XConfigureEvent *) event; X winW = ev->width; X winH = ev->height; X winX = ev->x; X winY = ev->y; X }; X break; X case KeyPress: X { X XKeyEvent *key_event = (XKeyEvent *) event; X char buf[128]; X KeySym ks; X XComposeStatus status; X X XLookupString(key_event,buf,128,&ks,&status); X if (buf[0]=='q' || buf[0]=='Q') X stop = TRUE; X } X break; X case ButtonPress: X pointer = !pointer; X break; X default: X break; X } X} X X X#ifndef HP_UX X X/* Put the process to sleep for a while. */ Xvoid nap(sec,usec) Xlong sec, usec; X{ X static struct timeval tv; X X tv.tv_sec = sec; X tv.tv_usec = usec; X select(0, 0, 0, 0, &tv); X} X X#else X Xstatic void alarmhandler() X{ X} X Xsleepms(msec) Xint msec; X{ X struct itimerval value,ovalue; X struct sigvec vec; X long savemask, sigblock(), sigpause(); X X vec.sv_handler = alarmhandler; X vec.sv_mask = 0x0; X vec.sv_flags = 0; X sigvector(SIGALRM, &vec, &vec); /* Set up alarmhandler for SIGALRM */ X savemask = sigblock((long)(1L << (SIGALRM - 1))); X X value.it_interval.tv_sec = 0; X value.it_interval.tv_usec = 0; X value.it_value.tv_sec = msec/1000; X value.it_value.tv_usec = (msec%1000)*1000; X setitimer(ITIMER_REAL,&value,&ovalue); X X (void)sigpause(0L); X (void)sigsetmask(savemask); X X sigvector(SIGALRM, &vec, NULL); /* Restore previous signal handler */ X} X Xusleep(us) Xlong us; X{ X sleepms(us / 1000); X} X X#endif X X Xvoid XUsage(program) Xchar *program; X{ X printf("%s [options] where options are listed below\n", program); X printf("-h|q|? display this message\n"); X printf("-v give verbose list of current settings\n"); X printf("-p use mouse (pointer) button to control wasp\n"); X printf("-r use root window\n"); X printf("-V stay in clear area of the screen (only with -r)\n"); X printf("-x use the logical xor raster operation (saves the root bitmap)\n"); X printf("-g geometry window geometry\n"); X printf("-d host:display X server to connect to\n"); X printf("-t timeout screen saved after 'timeout' seconds\n"); X printf("-D delay non-blocking delay between updates (milliseconds)\n"); X printf("-b bees number of bees\n"); X printf("-a bee_acc bee acceleration in pixels per frame per frame\n"); X printf("-s bee_vel bee speed limit in pixels per frame\n"); X printf("-A wasp_acc wasp max acceleration in pixels per frame per frame\n"); X printf("-S wasp_vel wasp speed limit in pixels per frame\n"); X printf("-B width border width that wasp can't cross\n"); X printf("-w wasp_clr wasp color\n"); X printf("-c bee_clr bee color\n"); X printf("-C bg_color background color\n"); X printf("\nPress any mouse button in the window to grab/release the wasp.\n"); X printf("\nPress q in the window to stop the insanity.\n\n"); X} X X Xvoid XHandleError(description, degree) Xchar *description; Xint degree; X{ X fprintf(stderr, "An error has occurred. The description is below...\n"); X fprintf(stderr, "%s\n", description); X X if (degree == FATAL) X { X fprintf(stderr, "Program aborting...\n"); X exit(-1); X } X} X Xlong XGetColor(display, color, final_color) Xdisp *display; Xchar *color; XXColor *final_color; X{ X XColor cdef; X char error_str[STD_STR]; X X if (!XParseColor(display->dpy, display->cmap, color, &cdef) || X !XAllocColor(display->dpy, display->cmap, &cdef)) X { X sprintf(error_str, "Color \"%s\" wasn't found.", color); X HandleError(error_str, FATAL); X } X X /* Copy the final color. */ X if (final_color != NULL) *final_color = cdef; X X return(cdef.pixel); X} END_OF_FILE if test 29074 -ne `wc -c <'xswarm.c'`; then echo shar: \"'xswarm.c'\" unpacked with wrong size! fi # end of 'xswarm.c' fi if test -f 'xswarm.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xswarm.h'\" else echo shar: Extracting \"'xswarm.h'\" \(2970 characters\) sed "s/^X//" >'xswarm.h' <<'END_OF_FILE' X/* Constants */ X#define TRUE 1 X#define FALSE 0 X#define STD_STR 100 X#define BEES 20 /* number of bees */ X#define TIMES 3 /* number of time positions recorded */ X#define BEEACC 3 /* acceleration of bees */ X#define WASPACC 5 /* maximum acceleration of wasp */ X#define BEEVEL 11 /* maximum bee velocity */ X#define WASPVEL 12 /* maximum wasp velocity */ X#define DELAY 40000 /* microsecond delay between updates */ X#define WINWIDTH 512 /* default window width */ X#define WINHEIGHT 512 /* default window height */ X#define BORDER 50 /* wasp won't go closer than this to the edges */ X#define ALIVE_MASK (SubstructureNotifyMask | KeyPressMask | PointerMotionMask) X X/* Error Codes */ X#define FATAL -1 X#define WARNING -2 X X/* Macros */ X#define X(t,b) (x[t*bees + b]) /* addressing into dynamic array */ X#define Y(t,b) (y[t*bees + b]) /* addressing into dynamic array */ X#define RAND(v) ((random() % v) - (v/2)) /* random number around 0 */ X X/* Type Definitions */ Xtypedef struct _disp X{ X Window win; X Display *dpy; X int screen; X Window root; X char *dname; X long wasp, bee, bg; /* colors */ X XColor bg_xcolor; X GC wasp_gc; X GC bee_gc; X GC erase_gc; X GC wasp_xor_gc; X GC bee_xor_gc; X Atom kill_atom, protocol_atom; X Colormap cmap; X} disp; X X X/*--------------------------- Function Prototypes ---------------------------*/ Xvoid nap(); Xvoid Usage(); Xvoid HandleError(); X Xvoid Initialize(); X Xvoid XQuit( X#ifdef USE_PROTOTYPES Xint, Xint, Xstruct sigcontext *, Xchar * X#endif X); X Xvoid XChange_Screen_Saver( X#ifdef USE_PROTOTYPES Xint X#endif X); X Xlong XGetColor( X#ifdef USE_PROTOTYPES Xdisp *, Xchar *, XXColor * X#endif X); X Xvoid XParse_Arguments( X#ifdef USE_PROTOTYPES Xint, Xchar **, Xchar * X#endif X); X Xvoid XCreate_Window( X#ifdef USE_PROTOTYPES Xchar * X#endif X); X Xvoid Animate(); X Xvoid XTraverse_Tree( X#ifdef USE_PROTOTYPES XDisplay *, XWindow X#endif X); X Xvoid Wait_For_Idleness(); X XBool XDummy_Predicate( X#ifdef USE_PROTOTYPES XDisplay *, XXEvent *, Xchar * X#endif X); X Xvoid Create_Big_Window(); X X X/*----------------------------- Global Variables ----------------------------*/ X X/* X related */ Xint winX, winY; Xunsigned int winW, winH; Xdisp display; X X/* animation related */ Xint times = TIMES; /* number of time steps recorded */ Xint bees = BEES; /* number of bees */ Xint wasp_vel = WASPVEL; /* maximum wasp speed */ Xint bee_vel = BEEVEL; /* maximum bee speed */ Xint wasp_acc = WASPACC; /* maximum wasp acceleration */ Xint bee_acc = BEEACC; /* bee acceleration */ Xint delay = DELAY; /* delay between updates, in microseconds */ Xint timeout = 0; /* time in seconds before screen saving */ Xint border = BORDER; /* border limiting wasp travel */ Xchar *wasp_color = NULL; Xchar *bee_color = NULL; Xchar *bg_color = NULL; Xchar stop = FALSE; Xint xor = FALSE; /* use GXxor if TRUE */ Xint verbose = FALSE; /* display settings if TRUE */ Xint stay_in_front = FALSE; /* Try to stay in clear area of the screen. */ Xint root = FALSE; /* display in root window */ Xint pointer = FALSE; /* control wasp with mouse */ X X END_OF_FILE if test 2970 -ne `wc -c <'xswarm.h'`; then echo shar: \"'xswarm.h'\" unpacked with wrong size! fi # end of 'xswarm.h' fi if test -f 'vroot.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'vroot.h'\" else echo shar: Extracting \"'vroot.h'\" \(2198 characters\) sed "s/^X//" >'vroot.h' <<'END_OF_FILE' X/* X * vroot.h -- Virtual Root Window handling header file X * X * This header file redefines the X11 macros RootWindow and DefaultRootWindow, X * making them look for a virtual root window as provided by certain `virtual' X * window managers like swm and tvtwm. If none is found, the ordinary root X * window is returned, thus retaining backward compatibility with standard X * window managers. X * The function implementing the virtual root lookup remembers the result of X * its last invocation to avoid overhead in the case of repeated calls X * on the same display and screen arguments. X * The lookup code itself is taken from Tom LaStrange's ssetroot program. X * X * Most simple root window changing X programs can be converted to using X * virtual roots by just including X * X * #include "vroot.h" X * X * after all the X11 header files. It has been tested on such popular X * X clients as xphoon, xfroot, xloadimage, and xaqua. X * X * Andreas Stolcke (stolcke@ICSI.Berkeley.EDU), 9/7/90 X */ X X#include <X11/X.h> X#include <X11/Xatom.h> X Xstatic Window XVirtualRootWindow(dpy, screen) XDisplay *dpy; X{ X static Display *save_dpy = (Display *)0; X static int save_screen = -1; X static Window root = (Window)0; X X Atom __SWM_VROOT = None; X int i; X Window rootReturn, parentReturn, *children; X unsigned int numChildren; X X if ( dpy != save_dpy || screen != save_screen ) { X root = RootWindow(dpy, screen); X X /* go look for a virtual root */ X __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False); X XQueryTree(dpy, root, &rootReturn, &parentReturn, X &children, &numChildren); X for (i = 0; i < numChildren; i++) { X Atom actual_type; X int actual_format; X long nitems, bytesafter; X Window *newRoot = (Window)0; X X if (XGetWindowProperty(dpy, children[i], __SWM_VROOT, X 0, 1, False, XA_WINDOW, X &actual_type, &actual_format, X &nitems, &bytesafter, X (unsigned char **) &newRoot) == Success X && newRoot) { X root = *newRoot; X break; X } X } X X save_dpy = dpy; X save_screen = screen; X } X X return root; X} X X#undef DefaultRootWindow X#define DefaultRootWindow(dpy) RootWindow(dpy, DefaultScreen(dpy)) X X#undef RootWindow X#define RootWindow(dpy,screen) VirtualRootWindow(dpy,screen) X END_OF_FILE if test 2198 -ne `wc -c <'vroot.h'`; then echo shar: \"'vroot.h'\" unpacked with wrong size! fi # end of 'vroot.h' fi if test -f 'patchlevel.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'patchlevel.h'\" else echo shar: Extracting \"'patchlevel.h'\" \(387 characters\) sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE' X/* Version 1.0 was cute, but it hadn't quite a few little bugs. */ X/* For a list of nifty features in the current version, see the */ X/* manual page. */ X X/* For version 2.* patches have not been released, because the changes */ X/* were often fairly significant. After I've sent out a patch, I'll */ X/* increment PATCHLEVEL. */ X X#define VERSION "2.1" X#define PATCHLEVEL 0 END_OF_FILE if test 387 -ne `wc -c <'patchlevel.h'`; then echo shar: \"'patchlevel.h'\" unpacked with wrong size! fi # end of 'patchlevel.h' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(717 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# Gcc usually works better if you have it. XCC = gcc X#CC = cc X X# If the path to Xlib.h needs to be set explicitly... X#XINC = -I/usr1/butterwo/X11R4/include X X# If you are on a Stardent Titan, then this will help it find random(). X#BSD = -43 X X# If you are using a compiler that supports prototypes then uncomment this. X# (Only little girlie men don't use prototypes. :-) ) X#PROTO = -DUSE_PROTOTYPES X XSRCS = xswarm.c XOBJS = xswarm.o XHEADERS = xswarm.h vroot.h patchlevel.h XPROGRAM = xswarm X XCFLAGS = $(BSD) $(PROTO) $(XINC) X XLIBS = -lX11 -lm X X$(PROGRAM): $(SRCS) $(HEADERS) Makefile X $(CC) $(CFLAGS) -o $(PROGRAM) $(SRCS) $(LIBS) X Xdistribution: X shar -o xswarm.shar $(SRCS) $(HEADERS) Makefile Imakefile xswarm.6 README X END_OF_FILE if test 717 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'Imakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Imakefile'\" else echo shar: Extracting \"'Imakefile'\" \(124 characters\) sed "s/^X//" >'Imakefile' <<'END_OF_FILE' XIMAKE_DEFINES= -DManSuffix=6 X XDEFINES = -DX11R4 XDEPLIBS = $(DEPXLIB) XLOCAL_LIBRARIES = $(XLIB) X XSimpleProgramTarget(xswarm) END_OF_FILE if test 124 -ne `wc -c <'Imakefile'`; then echo shar: \"'Imakefile'\" unpacked with wrong size! fi # end of 'Imakefile' fi if test -f 'xswarm.6' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xswarm.6'\" else echo shar: Extracting \"'xswarm.6'\" \(6831 characters\) sed "s/^X//" >'xswarm.6' <<'END_OF_FILE' X.TH XSWARM 6 "January 30, 1991" X.UC 4 X.SH NAME XXswarm Version 2.2 \- X11 animated toy X.SH SYNOPSIS X.B xswarm X.B \[\-hq?vprVx\] X.B \[\-t X.I timeout\] X.B \[\-D X.I delay\] X.B \[\-g X.I geometry\] X.B \[\-d X.I host:display\] X.B \[\-b X.I bees\] X.B \[\-a X.I bee-acceleration\] X.B \[\-s X.I bee-velocity\] X.B \[\-A X.I wasp-acceleration\] X.B \[\-S X.I wasp-velocity\] X.B \[\-B X.I border-width\] X.B \[\-w X.I wasp-color\] X.B \[\-c X.I bee-color\] X.B \[\-C X.I background-color\] X.SH DESCRIPTION X.I Xswarm Xis an X11 client that animates a group of line segments. One line is Xcalled the wasp and the others are the bees. The bees constantly accelerate Xtoward the wasp, forming a cute pattern that continually changes. Because X.I Xswarm Xis commonly left running in the root window, it was made possible to control Xhow much cpu time it uses with the -d option. X.LP XIf a mouse button is pressed while the pointer is in the xswarm window, Xthe wasp becomes controlled by the mouse. Control is released when the Xmouse button is pressed again. To kill X.I Xswarm X, press q in it's window. X.LP XThe parameters that affect behavior of the swarm are controllable by the user Xthrough command line parameters. Some of the niftier features are controlling Xthe wasp with the mouse, putting it in the root window, using it as a screen Xsaver, and making the swarm fly "above" a background bitmap. X.LP XAfter playing with X.I Xswarm Xinteractively, one of it's common uses is in the root Xwindow where it helps break the monotony of X. When putting it there, don't Xforget to play with the -V and -x options! X.LP XOne of the recently added capabilities of X.I Xswarm Xis screen saving. If a non-zero timeout is given with the -t option, the Xscreen will be cleared after the given amount of idle time and the swarm will Xanimate until a key is pressed or the mouse is moved. As far as I know, Xthis is the first example of an X.I X Xscreen saver other than the one built into the server. By screen saver, I Xmean a program that does not require a signal from the user to take over the Xscreen. X.PP X.SH OPTIONS X.I Xswarm Xhas the following options: X.TP X.B "\-h, \-q, \-?" XDisplay usage message and exit. X.TP X.B "-v" XDisplay verbose information about the current settings. X.TP X.B "-p" XUse the mouse (pointer) button to control the wasp. This can be turned on Xand off at any time by pressing a button in the window. X.TP X.B "-r" XUse root window. X.TP X.B "-V" XStay in the clear area of the root window. (Only useful with -r.) X.TP X.B "-x" XUse xor raster operation so that the bees don't destroy the root bitmap. X(Only useful with -r.) X.TP X.BI \-t " timeout" XThis is the number of seconds of idle time to wait before clearing the Xscreen. The idle swarm disappears when a key is pressed or the mouse is Xmoved. X.TP X.BI \-D " delay" XThis is the non-blocking delay between frames. (in milliseconds) X.TP X.BI \-g " geometry" Xlike -g 500x450+100+200 X.TP X.BI \-d " host:display" Xlike -d spacsun:0.0 or -d unix:0.0 X.TP X.BI \-b " bees" XThis is the number of bees that will be flying around. X.TP X.BI \-a " bee-acceleration" XThis is measured in pixels per frame per frame. (try 2-10) X.TP X.BI \-s " bee-velocity" XThis is measured in pixels per frame. (try 5-20) X.TP X.BI \-A " wasp-acceleration" XThis is measured in pixels per frame per frame. (try 2-10) X.TP X.BI \-S " wasp-velocity" XThis is measured in pixels per frame. (try 5-20) X.TP X.BI \-w " wasp-color" XOne of the colors in .../lib/X11/rgb.txt or a color of the form #rrggbb in Xhexadecimal. For instance, #ef9595 is sort of a flesh tone. r stands for red, Xg stands for green, and b stands for blue. X.TP X.BI \-c " bee-color" X.TP X.BI \-C " background-color" XIf you are using -x, then you may have to twiddle with this color in order Xto get the bees to show up. (-x works well with black and white) X.SH EXAMPLES XFor a swarm that doesn't stick so tightly to the wasp, try a larger Xspeed limit for the bees, like this... X.LP Xxswarm -s 16 X.LP XFor a wasp that gets away more often, give the wasp a higher speed limit Xand better acceleration, like this... X.LP Xxswarm -A 7 -S 20 X.LP XTo put the swarm in you background without harming your root bitmap, Xdo this... X.LP Xxswarm -r -x -V X.LP XYou may need to fiddle with -w, -c, and -C to make the swarm visible... X.LP Xxswarm -r -x -V -w red -c blue -C green X.LP XTo speed up the swarm, decrease the delay between frames... X.LP Xxswarm -D 10 (Try taking control with the mouse button.) X.LP XTo use xswarm as a screen saver, put a line like this in your X startup Xscript... X.LP Xxswarm -t 300 -w red -c blue X.LP X.SH BUGS XI still haven't gotten backing store to work perfectly in the root window Xwith the xor raster operation. Occasionally, the swarm leaves a semi-permanent Xmark on the root window. If anyone is interested in fixing up any part of Xxswarm, then please feel free, but I would like a copy of the changes. X.LP XPlease let me know if you have any problems with the screen saver Xfeature. It seems to work just fine on the Sun-4's that I use, but it Xoccasionally flakes out on the DecStation 3100's. X.SH MISCELLANEOUS RAMBLINGS XImplementing the screen saver feature took alot of thinking. I would be X.I VERY Xinterested in hearing of any other schemes for detecting user inactivity. XThe way I did it seems a little messy to me, but here it is. Initially, XI traverse the entire window hierarchy. As I get to each window, I do an XXSelectInput() on it. Then when I want to watch for user activity, I Xincrement a timer and check for events. If there are any events, then I Xzero the timer. If the timer exceeds whatever the timeout is, then I toss Xup the screen saver window. Does anyone have better ideas on how to watch Xfor user activity in ALL windows other than the way I described? X.LP XI admit that I've gotten many ideas from public domain software, but I've Xtried to give credit to the original authors at least in the documentation. XIf you use any part of xswarm or the swarm animation algorithm, then please Xinclude my name in your man page/documentation somewhere. X.SH AUTHOR XXswarm's author is Jeff Butterworth (butterwo@cs.unc.edu). X.LP XLooking at the source code to X.I psychoII Xhelped me learn how to open a window. XTaking over the screen was surprisingly simple once I looked at the source Xcode for X.I meltdown Xwritten by Dave Lemke (lemke@ncd.com). XThe following people have helped immensely with bug fixes and suggestions: X.TP X.nf X\ \ XDavid Elliott: tips for SYSV nap() and the sizehints structure XKarl Fox: improved the backing store problem XArne Helme: fixed "nap" function for HP machines XCasey Leedom: supplied a simple imakefile and man page XRob Nelson: added correct resizing XAndreas ?Stolcke?: fixed -g option, added virtual root XBill Trost: explained the race condition in nap(), added mouse control XJon Webb: bouncing against windows while in the root window X.fi END_OF_FILE if test 6831 -ne `wc -c <'xswarm.6'`; then echo shar: \"'xswarm.6'\" unpacked with wrong size! fi # end of 'xswarm.6' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(927 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XThis program animates a bunch of little line segments chasing a randomly Xaccelerating line segment. The concept is simple, but the effect is pretty Xcute. By default, it comes up in a window, but it can be put in the root Xwindow too. In order to make it usable as a screen background, you can Xalter the delay between updates, making it use very little cpu time. One of Xthe reasons why it doesn't use much cpu time is that it only uses integer Xarithmetic. X XThis program has been tested successfully on a Sun4's, DECStation 3100's, Xand DECStation 5000's. X XThe only thing you will probably have to change in the Makefile is the Xlocation of X include files. X XTry xswarm -h for help. Fiddle with the parameters. You can get really Xdifferent effects! X X XJeff Butterworth X XHome: 100-G Misty Woods Cir., Chapel Hill, NC 27514 (919) 967-7359 XSchool: 235 Sitterson, UNC-Chapel Hill, NC 27599 (919) 962-1719 X butterwo@cs.unc.edu X END_OF_FILE if test 927 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi echo shar: End of shell archive. exit 0 -- dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.