#! /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:  Imakefile README patchlevel.h unclutter.c unclutter.man
#   vroot.h
# Wrapped by mycroft@hal.gnu.ai.mit.edu on Mon Sep 28 11:18:15 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(59 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
XLOCAL_LIBRARIES = $(XLIB)
X
XSimpleProgramTarget(unclutter)
X
END_OF_FILE
if test 59 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1681 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Xunclutter is a program which runs permanently in the background of an X11
Xsession.  It checks on the X11 pointer (cursor) position every few
Xseconds, and when it finds it has not moved (and no buttons
Xare pressed on the mouse, and the cursor is not in the root window)
Xit creates a small sub-window as a child of the window the cursor is in.
XThe new window installs a cursor of size 1x1 but a mask of
Xall 0, ie an invisible cursor.  This allows you to see all the text in
Xan xterm or xedit, for example.  The human factors crowd would agree it
Xshould make things less distracting.
X
XOnce created, the program waits for the pointer to leave the window
Xand then destroys it, restoring the original situation.
XButton events are passed transparently through to the parent window.
XThey will usually cause the cursor to reappear because an active grab
Xwill be made by the program while the button is down, so the pointer
Xwill apparently leave the window, even though its x y position doesnt change.
X
XThe first version of this program used a grab to remove the cursor.
XThis method is still available with a "-grab" option to the program.
X
XThanks for their help with "remote debugging" with xscope of various servers to
X	dave edsall@iastate.edu
X	Roland McGrath <roland@geech.gnu.ai.mit.edu>
X	Rainer Sinkwitz <sinkwitz@ifi.unizh.ch>
X	Michael L. Brown astroatc!ftms!brown@cs.wisc.edu
X	patti@hosehead.hf.intel.com
Xand, for vroot.h, Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>
Xand to all those who tested various development versions sent by mail.
X
XThe program is released into the public domain.  Only the considerate
Xwill leave credit for the author.
X
X	Mark M Martin. mmm@cetia.fr  may 1991.
END_OF_FILE
if test 1681 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
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'\" \(497 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X/*
X * unclutter: 
X * level 0: initial release
X * level 1: -grab option to use old method, new method creates small input
X * only sub-window. (distributed by mail only, not posted)
X * level 2: use Andreas Stolcke's vroot.h for tvtwm and similar winmans.
X * level 3: -not option takes list of windows to avoid and -visible ignores
X *		visibility events for some servers.
X * level 4: check for EnterNotify rather than using XQueryPointer to see if
X *		we caught the pointer.
X */
X#define PATCHLEVEL 4
END_OF_FILE
if test 497 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'unclutter.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unclutter.c'\"
else
echo shar: Extracting \"'unclutter.c'\" \(8694 characters\)
sed "s/^X//" >'unclutter.c' <<'END_OF_FILE'
X/*
X * unclutter: remove idle cursor image from screen so that it doesnt
X * obstruct the area you are looking at.
X * doesn't do it if cursor is in root window or a button is down.
X * Tries to cope with jitter if you have a mouse that twitches.
X * (Could be a little fancier and only do it in particular clients.)
X * Unfortunately, clients like emacs set different text cursor
X * shapes depending on whether they have pointer focus or not.
X * Whereas version 1 did a grab cursor, version 2 creates a small subwindow.
X * This may work better with some window managers.
X * Some servers return a Visibility event when the subwindow is mapped.
X * Sometimes this is Unobscured, or even FullyObscured. Ignore these and
X * rely on LeaveNotify events.
X * Mark M Martin. cetia 1991  mmm@cetia.fr
X */
X
X/*
X**  Version 4 changes by Charles Hannum <mycroft@ai.mit.edu>
X**
X**  * After mapping cursorwindow, check for EnterNotify event rather than
X**    using XQueryPointer to see if pointer is in window; otherwise we get
X**    confused if the pointer was already grabbed by someone.
X**
X**  * Add some debugging code, enabled with -DDEBUG.
X*/
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xproto.h>
X#include <stdio.h>
X#include "vroot.h"
X
Xchar *progname;
Xpexit(str)char *str;{
X    fprintf(stderr,"%s: %s\n",progname,str);
X    exit(1);
X}
Xusage(){
X    pexit("usage:\n\
X	-display <display>\n\
X	-idle <seconds>		time between polls to detect idleness.\n\
X	-jitter <pixels>	pixels mouse can twitch without moving\n\
X	-grab			use grabpointer method not createwindow\n\
X	-reset			reset the timer whenever cursor becomes\n\
X					visible even if it hasn't moved\n\
X 	-root	       		apply to cursor on root window too\n\
X 	-visible       		ignore visibility events\n\
X	-not names...		dont apply to windows whose wm-name begins.\n\
X				(must be last argument)");
X}
X
X#define ALMOSTEQUAL(a,b) (abs(a-b)<=jitter)
X#define ANYBUTTON (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
X
X/* Since the small window we create is a child of the window the pointer is
X * in, it can be destroyed by its adoptive parent.  Hence our destroywindow()
X * can return an error, saying it no longer exists.  Similarly, the parent
X * window can disappear while we are trying to create the child. Trap and
X * ignore these errors.
X */
Xint (*defaulthandler)();
Xint errorhandler(display,error)
XDisplay *display;
XXErrorEvent *error;
X{
X    if(error->error_code!=BadWindow)
X	(*defaulthandler)(display,error);
X}
X
Xchar **names;	/* -> argv list of names to avoid */
X
X/*
X * return true if window has a wm_name and the start of it matches
X * one of the given names to avoid
X */
Xnameinlist(display,window)
XDisplay *display;
XWindow window;
X{
X    char **cpp;
X    char *name;
X
X    if(names==0)return 0;
X    if(XFetchName (display, window, &name)){
X	for(cpp = names;*cpp!=0;cpp++){
X	    if(strncmp(*cpp,name,strlen(*cpp))==0)
X		break;
X	}
X	XFree(name);
X	return(*cpp!=0);
X    }
X    return 0;
X}	
X
Xmain(argc,argv)char **argv;{
X    Display *display;
X    Cursor cursor;
X    int screen,oldx,oldy = -99;
X    int doroot = 0, jitter = 0, idletime = 5, usegrabmethod = 0, waitagain = 0,
X	dovisible = 1;
X    Window root;
X    Pixmap cursormask;
X    XGCValues xgc;
X    GC gc;
X    XColor dummycolour;
X    char *displayname = 0;
X    
X    progname = *argv;
X    argc--;
X    while(argv++,argc-->0){
X	if(strcmp(*argv,"-idle")==0){
X	    argc--,argv++;
X	    if(argc<0)usage();
X	    idletime = atoi(*argv);
X	}else if(strcmp(*argv,"-jitter")==0){
X	    argc--,argv++;
X	    if(argc<0)usage();
X	    jitter = atoi(*argv);
X	}else if(strcmp(*argv,"-root")==0){
X	    doroot = 1;
X	}else if(strcmp(*argv,"-grab")==0){
X	    usegrabmethod = 1;
X	}else if(strcmp(*argv,"-reset")==0){
X	    waitagain = 1;
X	}else if(strcmp(*argv,"-visible")==0){
X	    dovisible = 0;
X	}else if(strcmp(*argv,"-not")==0){
X	    /* take rest of srg list */
X	    names = ++argv;
X	    if(*names==0)names = 0;	/* no args follow */
X	    argc = 0;
X	}else if(strcmp(*argv,"-display")==0){
X	    argc--,argv++;
X	    if(argc<0)usage();
X	    displayname = *argv;
X	}else usage();
X    }
X    display = XOpenDisplay(displayname);
X    if(display==0)pexit("could not open display");
X    screen = DefaultScreen(display);
X    root = VirtualRootWindow(display,screen);
X
X    /* create a small 1x1 cursor with all pixels masked out */
X    cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
X    xgc.function = GXclear;
X    gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
X    XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
X    dummycolour.pixel = 0;
X    dummycolour.red = 0;
X    dummycolour.flags = 04;
X    cursor = XCreatePixmapCursor(display, cursormask, cursormask,
X	      &dummycolour,&dummycolour, 0,0);
X    XFreePixmap(display,cursormask);
X    XFreeGC(display,gc);
X    if(!usegrabmethod)
X	defaulthandler = XSetErrorHandler(errorhandler);
X
X    while(1){
X	Window dummywin,windowin;
X	int rootx,rooty,winx,winy;
X	unsigned int modifs;
X	Window lastwindowavoided = None;
X	
X	/* wait for pointer to not move and no buttons down */
X	while(1){
X	    if(!XQueryPointer(display, root, &dummywin, &windowin,
X			 &rootx, &rooty, &winx, &winy, &modifs)){
X		/* window manager with virtual root may have restarted */
X		root = VirtualRootWindow(display,screen);
X	    }else if((!doroot && windowin==None) || (modifs & ANYBUTTON) ||
X		     !(ALMOSTEQUAL(rootx,oldx) && ALMOSTEQUAL(rooty,oldy))){
X		oldx = rootx, oldy = rooty;
X	    }else if(windowin==None){
X		windowin = root;
X		break;
X	    }else if(windowin!=lastwindowavoided){
X		/* descend tree of windows under cursor to bottommost */
X		Window childin;
X		int toavoid = xFalse;
X		lastwindowavoided = childin = windowin;
X		do{
X		    windowin = childin;
X		    if(nameinlist (display, windowin)){
X			toavoid = xTrue;
X			break;
X		    }
X		}while(XQueryPointer(display, windowin, &dummywin,
X		     &childin, &rootx, &rooty, &winx, &winy, &modifs)
X		       && childin!=None);
X		if(!toavoid){
X		    lastwindowavoided = None;
X		    break;
X		}
X	    }
X	    sleep(idletime);
X	}
X	/* wait again next time */
X	if(waitagain)
X	    oldx = -1-jitter;
X	if(usegrabmethod){
X	    if(XGrabPointer(display, root, 0,
X		    PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
X		    GrabModeAsync, GrabModeAsync, None, cursor,
X		    CurrentTime)==GrabSuccess){
X		/* wait for a button event or large cursor motion */
X		XEvent event;
X		do{
X		    XNextEvent(display,&event);
X		}while(event.type==MotionNotify &&
X		       ALMOSTEQUAL(rootx,event.xmotion.x) &&
X		       ALMOSTEQUAL(rooty,event.xmotion.y));
X		XUngrabPointer(display, CurrentTime);
X	    }
X	}else{
X	    XSetWindowAttributes attributes;
X	    XEvent event;
X	    Window cursorwindow;
X	    
X	    /* create small input-only window under cursor
X	     * as a sub window of the window currently under the cursor
X	     */
X	    attributes.event_mask = EnterWindowMask | LeaveWindowMask |
X			StructureNotifyMask |
X			FocusChangeMask;
X	    if(dovisible)
X		attributes.event_mask |= VisibilityChangeMask;
X	    attributes.override_redirect = True;
X	    attributes.cursor = cursor;
X	    cursorwindow = XCreateWindow
X		(display, windowin,
X		 winx-jitter, winy-jitter,
X		 jitter*2+1, jitter*2+1, 0, CopyFromParent,
X		 InputOnly, CopyFromParent, 
X		 CWOverrideRedirect | CWEventMask | CWCursor,
X		 &attributes);
X	    /* discard old events for previously created windows */
X	    XSync(display,True);
X	    XMapWindow(display,cursorwindow);
X	    XSync(display,False);
X	    /* check that created window captured the pointer */
X	    if(!XCheckTypedWindowEvent(display, cursorwindow, EnterNotify,
X				       &event)){
X		/* failed to catch pointer; probably grabbed by someone */
X#ifdef DEBUG
X		fprintf(stderr, "failed to catch pointer\n");
X#endif
X		oldx = -1-jitter;
X	    }else{
X#ifdef DEBUG
X		fprintf(stderr, "mapped\n");
X#endif
X		/* wait till pointer leaves window */
X		do{
X		    XNextEvent(display,&event);
X#ifdef DEBUG
X		    fprintf(stderr, "event; event.type=%d\n", event.type);
X#endif
X		}while(event.type!=LeaveNotify &&
X		       event.type!=FocusOut &&
X		       event.type!=UnmapNotify &&
X		       event.type!=ConfigureNotify &&
X		       event.type!=CirculateNotify &&
X		       event.type!=ReparentNotify &&
X		       event.type!=DestroyNotify &&
X		       (event.type!=VisibilityNotify ||
X			event.xvisibility.state==VisibilityUnobscured)
X		       );
X		/* check if a second unclutter is running cos they thrash */
X		if(event.type==LeaveNotify &&
X		   event.xcrossing.window==cursorwindow &&
X		   event.xcrossing.detail==NotifyInferior)
X		    pexit("someone created a sub-window to my sub-window! giving up");
X	    }
X	    XDestroyWindow(display, cursorwindow);
X#ifdef DEBUG
X	    fprintf(stderr, "unmapped\n");
X#endif
X	}
X    }
X}
END_OF_FILE
if test 8694 -ne `wc -c <'unclutter.c'`; then
    echo shar: \"'unclutter.c'\" unpacked with wrong size!
fi
# end of 'unclutter.c'
fi
if test -f 'unclutter.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unclutter.man'\"
else
echo shar: Extracting \"'unclutter.man'\" \(2486 characters\)
sed "s/^X//" >'unclutter.man' <<'END_OF_FILE'
X.\"unclutter man
X.TH UNCLUTTER 1X
X.SH NAME
Xunclutter \- remove idle cursor image from screen
X.SH SYNOPSIS
X.B
Xunclutter
X.RB [ -display
X.IR display ]
X.RB [ -idle
X.IR seconds ]
X.RB [ -jitter
X.IR pixels ]
X.RB [ -grab ]
X.RB [ -reset ]
X.RB [ -root ]
X.RB [ -not ]
X.I "name ...
X.SH DESCRIPTION
X.B unclutter
Xremoves the cursor image from the screen so that it does not
Xobstruct the area you are looking at after it has not moved for
Xa given time.
XIt does not do this if the cursor is in the root window or a button is down.
XIt tries to ignore jitter (small movements due to noise)
Xif you have a mouse that twitches.
X.SH OPTIONS
X.TP
X-display
Xis followed by the display to open.
X.TP
X-idle
Xis followed by the number of seconds between polls for idleness.
XThe default is 5.
X.TP
X-jitter
Xis followed by the amount of movement of the pointer that is to be ignored
Xand considered as random noise.
XThe default is 0.
X.TP
X-grab
Xmeans use the original method of grabbing the pointer in order to remove the
Xcursor. 
XThis often doesn't interoperate too well with some window managers.
X.TP
X-reset
Xresets the timeout for idleness after the cursor is restored for some reason
X(such as a window being pushed or popped) even though the x y coordinates
Xof the cursor have not changed.
XNormally, the cursor would immediately be removed again.
X.TP
X-root
Xmeans remove the cursor even if it is on the root background, where in
Xprinciple it should not be obscuring anything useful.
X.TP
X-not
Xis followed by a list of window names where the cursor should not be
Xremoved.
XThe first few characters of the WM_NAME property on the window need
Xto match one the listed names.
XThis argument must be the last on the command line.
X.SH LIMITATIONS
XUnfortunately, clients like emacs set different text cursor
Xshapes depending on whether they have pointer focus or not,
Xand so not only does the cursor pixture go, but the text cursor image changes.
XEven more sadly, some window managers like to remove keyboard focus if pointer
Xfocus is lost.
X.SH DIAGNOSTICS
XThe message
X.sp
X someone created a sub-window to my sub-window!
X.sp 
Xmeans that unclutter thinks a second unclutter is running, and tried
Xto steal the cursor by creating a sub-window to the sub-window already
Xused to steal the cursor.
XThis situation quickly deteriorates into a fight no one can win, so
Xit is detected when possible and the program gives up.
X.SH AUTHOR
XMark M Martin. cetia 24may1991. mmm@cetia.fr
X.sp
XUpdated 28sep1992 by Charles Hannum <mycroft@ai.mit.edu>
END_OF_FILE
if test 2486 -ne `wc -c <'unclutter.man'`; then
    echo shar: \"'unclutter.man'\" unpacked with wrong size!
fi
# end of 'unclutter.man'
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'\" \(2863 characters\)
sed "s/^X//" >'vroot.h' <<'END_OF_FILE'
X/*
X * Article 12523 of comp.windows.x:
X * From: stolcke@ICSI.Berkeley.EDU (Andreas Stolcke)
X * Subject: Converting programs to virtual root
X * Date: 8 Sep 90 02:26:14 GMT
X * 
X * Andreas Stolcke
X * International Computer Science Institute	stolcke@icsi.Berkeley.EDU
X * 1957 Center St., Suite 600, Berkeley, CA 94704	(415) 642-4274 ext. 126
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 * - replaced all NULL's with properly cast 0's, 5/6/91
X * - free children list (suggested by Mark Martin <mmm@cetia.fr>), 5/16/91
X */
X#define DONTOPTIMISE	/* unclutter needs to search from scratch each time */
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#ifdef DONTOPTIMISE
X	{
X#else
X	if (dpy != save_dpy || screen != save_screen) {
X#endif
X		Atom __SWM_VROOT = None;
X		int i;
X		Window rootReturn, parentReturn, *children;
X		unsigned int numChildren;
X
X		root = RootWindow(dpy, screen);
X
X		/* go look for a virtual root */
X		__SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
X		if (XQueryTree(dpy, root, &rootReturn, &parentReturn,
X				 &children, &numChildren)) {
X			for (i = 0; i < numChildren; i++) {
X				Atom actual_type;
X				int actual_format;
X				unsigned long nitems, bytesafter;
X				Window *newRoot = (Window *)0;
X
X				if (XGetWindowProperty(dpy, children[i],
X					__SWM_VROOT, 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			if (children)
X				XFree((char *)children);
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)
END_OF_FILE
if test 2863 -ne `wc -c <'vroot.h'`; then
    echo shar: \"'vroot.h'\" unpacked with wrong size!
fi
# end of 'vroot.h'
fi
echo shar: End of shell archive.
exit 0
