home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / xwatchwin / part01 next >
Encoding:
Text File  |  1989-03-30  |  23.7 KB  |  695 lines

  1. Path: uunet!island!argv
  2. From: argv@island.uu.net (Dan Heller)
  3. Newsgroups: comp.sources.x
  4. Subject: v03i062:  xwatchwin -- watch a window on another X server, Part01/01
  5. Message-ID: <661@island.uu.net>
  6. Date: 31 Mar 89 07:05:10 GMT
  7. Sender: news@island.uu.net
  8. Organization: Island Graphics, Marin County, California
  9. Lines: 683
  10. Approved: island!argv@sun.com
  11.  
  12. Submitted-by: George Drapeau <drapeau@jessica.stanford.edu>
  13. Posting-number: Volume 3, Issue 62
  14. Archive-name: xwatchwin/part01
  15.  
  16. [I generated a README from the man page.  As sent, there were *lots* of
  17. lines that went over 80 chars (many over two or three lines), so I
  18. reformatted much of the code by moving comments above the lines they
  19. commented.  I tried to preserve as much of the original style of the
  20. author as possible.  Please be aware of this when sending articles to
  21. be posted by any newsgroup.  --argv]
  22.  
  23. #! /bin/sh
  24. # This is a shar archive.  Extract with sh, not csh.
  25. #George D. Drapeau            Internet: drapeau@jessica.stanford.edu
  26. #Academic Information Resources
  27. #Stanford University
  28. echo x - Imakefile
  29. cat > Imakefile << '25787!Funky!Stuff!'
  30. #ifdef SunSharedLibs
  31. SYS_LIBRARIES = -lX11
  32. #else
  33. LOCAL_LIBRARIES = $(XLIB)
  34. #endif
  35. SimpleProgramTarget(xwatchwin)
  36. 25787!Funky!Stuff!
  37. echo x - Makefile
  38. cat > Makefile << '25787!Funky!Stuff!'
  39. # Makefile generated by imake - do not edit!
  40. # $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $
  41. #
  42. # The cpp used on this machine replaces all newlines and multiple tabs and
  43. # spaces in a macro expansion with a single space.  Imake tries to compensate
  44. # for this, but is not always successful.
  45. #
  46.  
  47. ###########################################################################
  48. # X Window System Makefile generated from template file Imake.tmpl
  49. # $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $
  50. #
  51. # Do not change the body of the imake template file.  Server-specific
  52. # parameters may be set in the appropriate .macros file; site-specific
  53. # parameters (but shared by all servers) may be set in site.def.  If you
  54. # make any changes, you'll need to rebuild the makefiles using
  55. # "make World" (at best) or "make Makefile; make Makefiles" (at least) in
  56. # the top level directory.
  57. #
  58. # If your C preprocessor doesn't define any unique symbols, you'll need
  59. # to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
  60. # "make Makefile", "make Makefiles", or "make World").
  61. #
  62. # If you absolutely can't get imake to work, you'll need to set the
  63. # variables at the top of each Makefile as well as the dependencies at the
  64. # bottom (makedepend will do this automatically).
  65. #
  66.  
  67. ###########################################################################
  68. # platform-specific configuration parameters - edit Sun.macros to change
  69.  
  70. # platform:  $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $
  71. # operating system:  SunOS 4.0
  72.  
  73. BOOTSTRAPCFLAGS =
  74.              AS = as
  75.              CC = cc
  76.             CPP = /lib/cpp
  77.              LD = ld
  78.            LINT = lint
  79.         INSTALL = install
  80.            TAGS = ctags
  81.              RM = rm -f
  82.              MV = mv
  83.              LN = ln -s
  84.          RANLIB = ranlib
  85. RANLIBINSTFLAGS = -t
  86.              AR = ar clq
  87.              LS = ls
  88.        LINTOPTS = -axz
  89.     LINTLIBFLAG = -C
  90.            MAKE = make
  91. STD_CPP_DEFINES =
  92.     STD_DEFINES =
  93.  
  94. ###########################################################################
  95. # site-specific configuration parameters - edit site.def to change
  96.  
  97. # site:  $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $
  98.  
  99. ###########################################################################
  100. # definitions common to all Makefiles - do not edit
  101.  
  102.           SHELL = /bin/sh
  103.  
  104.         DESTDIR = /usr/local
  105.       USRLIBDIR = $(DESTDIR)/X11R3/lib
  106.          BINDIR = $(DESTDIR)/X11R3/bin
  107.          INCDIR = $(DESTDIR)/include/X11R3
  108.          ADMDIR = $(DESTDIR)/usr/adm
  109.          LIBDIR = $(USRLIBDIR)
  110.      LINTLIBDIR = $(USRLIBDIR)/lint
  111.         FONTDIR = $(LIBDIR)/fonts
  112.        XINITDIR = $(LIBDIR)/xinit
  113.          XDMDIR = $(LIBDIR)/xdm
  114.          UWMDIR = $(LIBDIR)/uwm
  115.          AWMDIR = $(LIBDIR)/awm
  116.          TWMDIR = $(LIBDIR)/twm
  117.         MANPATH = $(DESTDIR)/man
  118.   MANSOURCEPATH = $(MANPATH)/man
  119.          MANDIR = $(MANSOURCEPATH)1
  120.       LIBMANDIR = $(MANSOURCEPATH)3
  121.     XAPPLOADDIR = $(LIBDIR)/app-defaults
  122.  
  123.    INSTBINFLAGS = -sm 0755
  124.    INSTUIDFLAGS = -m 4755
  125.    INSTLIBFLAGS = -m 0664
  126.    INSTINCFLAGS = -m 0444
  127.    INSTMANFLAGS = -m 0444
  128.    INSTAPPFLAGS = -m 0444
  129.   INSTKMEMFLAGS = -g kmem -m 2755
  130.         FCFLAGS = -t
  131.     CDEBUGFLAGS =
  132.  
  133.         PATHSEP = /
  134.          DEPEND = $(DEPENDSRC)/makedepend
  135.           IMAKE = $(IMAKESRC)/imake
  136.             RGB = $(RGBSRC)/rgb
  137.              FC = $(BDFTOSNFSRC)/bdftosnf
  138.       MKFONTDIR = $(MKFONTDIRSRC)/mkfontdir
  139.       MKDIRHIER = $(SCRIPTSSRC)/mkdirhier.sh
  140.  
  141.          CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
  142.       LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
  143.         LDFLAGS = $(CDEBUGFLAGS) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
  144.             TOP = /usr/local/X
  145.       CLIENTSRC = $(TOP)/clients
  146.         DEMOSRC = $(TOP)/demos
  147.          LIBSRC = $(TOP)/lib
  148.         FONTSRC = $(TOP)/fonts
  149.      INCLUDESRC = $(TOP)/X11
  150.       SERVERSRC = $(TOP)/server
  151.         UTILSRC = $(TOP)/util
  152.      SCRIPTSSRC = $(UTILSRC)/scripts
  153.      EXAMPLESRC = $(TOP)/examples
  154.      CONTRIBSRC = $(TOP)/contrib
  155.          DOCSRC = $(TOP)/doc
  156.          RGBSRC = $(TOP)/rgb
  157.       DEPENDSRC = $(UTILSRC)/makedepend
  158.        IMAKESRC = $(UTILSRC)/imake
  159.        IRULESRC = $(UTILSRC)/imake.includes
  160.         XLIBSRC = $(LIBSRC)/X
  161.          XMUSRC = $(LIBSRC)/Xmu
  162.      TOOLKITSRC = $(LIBSRC)/Xt
  163.      AWIDGETSRC = $(LIBSRC)/Xaw
  164.      OLDXLIBSRC = $(LIBSRC)/oldX
  165.     BDFTOSNFSRC = $(FONTSRC)/bdftosnf
  166.    MKFONTDIRSRC = $(FONTSRC)/mkfontdir
  167.    EXTENSIONSRC = $(TOP)/extensions
  168.    EXTENSIONLIB = $(EXTENSIONSRC)/lib/libXext.a
  169.            XLIB = $(XLIBSRC)/libX11.a
  170.          XMULIB = $(XMUSRC)/libXmu.a
  171.         OLDXLIB = $(OLDXLIBSRC)/liboldX.a
  172.        XTOOLLIB = $(TOOLKITSRC)/libXt.a
  173.          XAWLIB = $(AWIDGETSRC)/libXaw.a
  174.        LINTXLIB = $(XLIBSRC)/llib-lX11.ln
  175.         LINTXMU = $(XMUSRC)/llib-lXmu.ln
  176.       LINTXTOOL = $(TOOLKITSRC)/llib-lXt.ln
  177.         LINTXAW = $(AWIDGETSRC)/llib-lXaw.ln
  178.        INCLUDES = -I$(TOP)
  179.       MACROFILE = Sun.macros
  180.    ICONFIGFILES = $(IRULESRC)/Imake.tmpl \
  181.             $(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def
  182.   IMAKE_DEFINES =
  183.       IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \
  184.             -s Makefile $(IMAKE_DEFINES)
  185.          RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
  186.             .emacs_* tags TAGS make.log MakeOut
  187.  
  188. ###########################################################################
  189. # rules:  $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $
  190.  
  191. ###########################################################################
  192. # start of Imakefile
  193.  
  194. SYS_LIBRARIES = -lX11
  195.  
  196.  OBJS = xwatchwin.o
  197.  SRCS = xwatchwin.c
  198.  
  199.  PROGRAM = xwatchwin
  200.  
  201. all:: xwatchwin
  202.  
  203. xwatchwin: $(OBJS) $(LOCAL_LIBRARIES)
  204.     $(RM) $@
  205.     $(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES)
  206.  
  207. relink::
  208.     $(RM) $(PROGRAM)
  209.     $(MAKE) $(MFLAGS) $(PROGRAM)
  210.  
  211. install:: xwatchwin
  212.     $(INSTALL) -c $(INSTALLFLAGS) xwatchwin $(BINDIR)
  213.  
  214. install.man:: xwatchwin.man
  215.     $(INSTALL) -c $(INSTMANFLAGS) xwatchwin.man $(MANDIR)/xwatchwin.1
  216.  
  217. depend:: $(DEPEND)
  218.  
  219. depend::
  220.     $(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS)
  221.  
  222. $(DEPEND):
  223.     @echo "making $@"; \
  224.     cd $(DEPENDSRC); $(MAKE)
  225.  
  226. clean::
  227.     $(RM) $(PROGRAM)
  228.  
  229. ###########################################################################
  230. # Imake.tmpl common rules for all Makefiles - do not edit
  231.  
  232. emptyrule::
  233.  
  234. clean::
  235.     $(RM_CMD) \#*
  236.  
  237. Makefile:: $(IMAKE)
  238.  
  239. Makefile:: Imakefile \
  240.     $(IRULESRC)/Imake.tmpl \
  241.     $(IRULESRC)/Imake.rules \
  242.     $(IRULESRC)/site.def \
  243.     $(IRULESRC)/$(MACROFILE)
  244.     -@if [ -f Makefile ]; then \
  245.     echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
  246.     $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
  247.     else exit 0; fi
  248.     $(IMAKE_CMD) -DTOPDIR=$(TOP)
  249.  
  250. $(IMAKE):
  251.     @echo "making $@"; \
  252.     cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)
  253.  
  254. tags::
  255.     $(TAGS) -w *.[ch]
  256.     $(TAGS) -xw *.[ch] > TAGS
  257.  
  258. ###########################################################################
  259. # empty rules for directories that do not have SUBDIRS - do not edit
  260.  
  261. install::
  262.     @echo "install done"
  263.  
  264. install.man::
  265.     @echo "install.man done"
  266.  
  267. Makefiles::
  268.  
  269. ###########################################################################
  270. # dependencies generated by makedepend
  271.  
  272. 25787!Funky!Stuff!
  273. echo x - xwatchwin.c
  274. cat > xwatchwin.c << '25787!Funky!Stuff!'
  275. #include <stdio.h>
  276. #include <ctype.h>
  277. #include <sys/time.h>
  278. #include <X11/Xlib.h>
  279. #include <X11/Xutil.h>
  280.  
  281. #define STRINGLENGTH    256
  282. #define SLEEPTIME    0    /* Sleep for this many seconds before redrawing */
  283.  
  284. char    **Argv;
  285. int    Argc;
  286. Display    *dpy;
  287.  
  288.  
  289. main(argc,argv)
  290.      int    argc;
  291.      char    **argv;
  292. {
  293.   Window    watchWin,GetWindowByName();
  294.   int        i,strPos,optIndex;
  295.   char        displayName[64],xWatchName[STRINGLENGTH];
  296.   char        *optstring;
  297.   extern char    *optarg;
  298.   extern int    optind,opterr;
  299.   int        windowID,windowIDSet,updateTime,updateTimeSet;
  300.   
  301.  
  302.   if (argc < 3)                /* Did user enter enough arguments? */
  303.     {                    /* Nope, print an error message and exit. */
  304.       printf("Usage:\t%s HostName [-u UpdateTime] [-w windowID] [WindowName]\n",
  305.       argv[0]);
  306.       exit(1);
  307.     }
  308.  
  309.   /* Initialize var to update every SLEEPTIME seconds. */
  310.   updateTime = SLEEPTIME;
  311.   updateTimeSet = 0;
  312.   windowIDSet = 0;
  313.   optind = 2;        /* Skip over first, obligatory argument (hostname) */
  314.   while ((optIndex = getopt(argc,argv,"u:w:")) != -1) /* Get user's arguments */
  315.     switch (optIndex)
  316.       {
  317.       case 'u':        /* User wants to update every 'optarg' seconds. */
  318.     updateTime = atoi(optarg);
  319.     updateTimeSet = 1;    /* Set flag saying user specified this option. */
  320.     break;
  321.       case 'w':   /* User wants to specify window by id instead of by name */
  322.     sscanf(&optarg[2],"%lx",&windowID);
  323.     windowIDSet = 1;    /* Set flag saying user specified this option. */
  324.     break;
  325.       }                /* end switch (optIndex) */
  326.  
  327.   Argv = argv;
  328.   Argc = argc;
  329.   sprintf(displayName,"%s:0.0",argv[1]);    /* Set the X display name. */
  330.   if (!windowIDSet)       /* Did user specify window to watch by number? */
  331.     for (i=2, bzero(xWatchName, STRINGLENGTH); i < argc; i++)
  332.     /* No, parse rest of arguments as window name to watch */
  333.       {
  334.     if (!strcmp(argv[i],"-u"))       /* Don't parse optional arguments */
  335.       {
  336.         i++;           /* Skip over argument to '-u' switch. */
  337.         continue;
  338.       }
  339.     /* Get current length of xWatchName string */
  340.     strPos = strlen(xWatchName);
  341.     /* Copy another argument to the end of the string */
  342.     strcpy(&xWatchName[strPos],argv[i]);
  343.       }
  344.  
  345.   /* Attempt to open a connection with the remote X server */
  346.   if ((dpy = XOpenDisplay(displayName)) == NULL)
  347.     {
  348.       /* Couldn't open the display for some reason, so... */
  349.       fprintf(stderr,"%s: Could not open Display %s\n", argv[0],displayName);
  350.       exit(1);        /* ...report the error and exit with an error code */
  351.     }
  352.  
  353.   if (!windowIDSet)        /* Did user specify a window to watch by id? */
  354.     /* No, get window id from window name. */
  355.     watchWin = GetWindowByName(XDefaultRootWindow(dpy),xWatchName);
  356.   else watchWin = windowID; /* Yes, use user-specified window id. */
  357.   if (watchWin)       /* Did the user find the window s/he was looking for? */
  358.     /* Yes, periodically show the contents of that window  */
  359.     WatchWindow(watchWin,updateTime);
  360.   else    /* No, report that the window was not found, and exit. */
  361.     {
  362.       printf("Could not find the window you specified.\n");
  363.       exit(1);
  364.     }
  365.   
  366. }    /* end function main */
  367.  
  368.  
  369.  
  370.  
  371. /* Takes two strings, removes spaces from the second,... */
  372. /* ...and compares them..  Returns 1 if equal, 0 if not. */
  373. WinNamesEqual(str1,str2)
  374.      char    *str1,*str2;
  375. {
  376.   char    tempStr[STRINGLENGTH],*tempStrPtr;
  377.   int    index;
  378.   
  379.   bzero(tempStr,STRINGLENGTH);    /* Clear the contents of the string, if any */
  380.   /* Go through each character in the second string. */
  381.   for (tempStrPtr=tempStr; *str2; str2++)
  382.     {
  383.       if (!isspace(*str2))    /* Is this character a space?  */
  384.     *tempStrPtr++ = *str2;    /* No, copy this character to a temp string. */
  385.     }
  386.   if (!strcmp(str1,tempStr))    /* Are the two resulting string equal? */
  387.     return(1);            /* Yes, return 1 */
  388.   else
  389.     return(0);            /* No, return 0 */
  390. }                /* end function WinNamesEqual */
  391.  
  392.  
  393. WatchWindow(win,updateTime)
  394.      Window    win;
  395.      int    updateTime;
  396. {
  397.   Display        *dpy2;
  398.   Window        copyWin;
  399.   GC            gc;
  400.   XWindowAttributes    copyWinInfo,newWinInfo;
  401.   XSetWindowAttributes    copyWinAttrs;
  402.   XWMHints        wmHints;
  403.   XSizeHints        sizeHints;
  404.   XImage        *image;
  405.   struct timeval    currentTime;
  406.   struct timezone    zone;
  407.   long            timeInSecs;
  408.   Bool            srcWinUnmapped;
  409.   
  410.   /* Get the window attributes of the window we're watching */
  411.   XGetWindowAttributes(dpy,win,©WinInfo);
  412.   /* Is the original window in a state to be watched?  */
  413.   if (copyWinInfo.map_state != IsViewable)
  414.     {  /* Nope, tell the user of the problem and exit. */
  415.       printf("The window you wish to look at is not in a state to be viewed\n");
  416.       printf("(perhaps it is iconified or not mapped)\n");
  417.       exit(1);
  418.     }
  419.   /* Attempt to open a connection with the local X server */
  420.   if ((dpy2 = XOpenDisplay(NULL)) == NULL)
  421.     {
  422.       /* Couldn't open the display for some reason, so... */
  423.       fprintf(stderr,"%s: Could not open Display.\n", Argv[0]);
  424.       exit(1); /* ...report the error and exit with an error code */
  425.     }
  426.   /* Set a couple more attributes */
  427.   copyWinAttrs.colormap = XDefaultColormap(dpy2,XDefaultScreen(dpy2));
  428.   copyWinAttrs.bit_gravity = copyWinInfo.bit_gravity;
  429.   /* Check for different depths b/w source & dest displays */
  430.   if (copyWinInfo.depth != XDefaultDepth(dpy2,XDefaultScreen(dpy2)))
  431.     {
  432.       puts("Sorry, the original and copied windows contain incompatible");
  433.       puts("information (i.e., they don't use the same number of bits per pixel.");
  434.       exit(1);
  435.     }
  436.   /* Create a copy of the window we're watching */
  437.   copyWin = XCreateWindow(dpy2,XDefaultRootWindow(dpy2),
  438.               copyWinInfo.x,copyWinInfo.y,
  439.               copyWinInfo.width,copyWinInfo.height,
  440.               copyWinInfo.border_width,
  441.               copyWinInfo.depth,
  442.               CopyFromParent,
  443.               XDefaultVisual(dpy2,XDefaultScreen(dpy2)),
  444.               (CWColormap|CWBitGravity),
  445.               ©WinAttrs);
  446.   /* Get size hints for window being watched */
  447.   XGetNormalHints(dpy,win,&sizeHints);
  448.   /* Set standard window properties for my window */
  449.   XSetStandardProperties(dpy2,copyWin,"XWatchWin","XWatchWin",
  450.              None,Argv,Argc,&sizeHints);
  451.   /* Get window mgr hints for the window being watched */
  452.   XGetWMHints(dpy,win,&wmHints);
  453.   /* Tell the X server about my window manager hints */
  454.   XSetWMHints(dpy2,copyWin,&wmHints);
  455.   gc = XDefaultGC(dpy2,0); /* Get a default graphics context */
  456.   /* Only interested in exposures and button presses */
  457.   XSelectInput(dpy2,copyWin,(ExposureMask|ButtonPressMask));
  458.   /* Put the window up on the display */
  459.   XMapWindow(dpy2,copyWin);
  460.   XSelectInput(dpy,win, /* Only interested if the source window is... */
  461.            /* ...iconified or if it's mapped/unmapped */
  462.            (VisibilityChangeMask|StructureNotifyMask));
  463.   /* Store an image of the original window in an XImage */
  464.   image = XGetImage(dpy,(Drawable)win,
  465.             0,0,
  466.             copyWinInfo.width,copyWinInfo.height,
  467.             AllPlanes,XYPixmap);
  468.   gettimeofday(¤tTime,&zone); /* Get the current time. */
  469.   timeInSecs = currentTime.tv_sec; /* Save the current time in seconds */
  470.   /* Set variable saying it's okay to watch the src window. */
  471.   srcWinUnmapped = 0;
  472.   while (1) /* Enter an infinite event loop */
  473.     {
  474.       XEvent    event;
  475.  
  476.       /* Check if the source window was turned into an... */
  477.       if (XCheckWindowEvent(dpy,win,
  478.                 (VisibilityChangeMask|StructureNotifyMask),
  479.                 &event))
  480.     { /* ...icon or back into a window */
  481.       /* Get the window attributes of the window we're watching */
  482.       XGetWindowAttributes(dpy,win,&newWinInfo);
  483.       /* Is the original window in a state to be watched?  */
  484.       if (newWinInfo.map_state != IsViewable)
  485.         {
  486.           /* Let program know that the src window is unwatchable. */
  487.           srcWinUnmapped = 1;
  488.           printf("The window you are watching just became 'invisible'..\n");
  489.           printf("I will wait until it is 'visible' again...\n");
  490.           continue;
  491.         }
  492.       else
  493.         /* Let program know that src window is watchable again. */
  494.         srcWinUnmapped = 0;
  495.     } /* end if(XCheckWindowEvent... */
  496.  
  497.       /* Look for window events, but don't sit around... */
  498.       if (XCheckWindowEvent(dpy2,copyWin,
  499.                 (ExposureMask|ButtonPressMask),
  500.                 /* ...waiting for one (i.e., don't block) */
  501.                 &event))
  502.     switch (event.type)
  503.       {
  504.       case ButtonPress:
  505.         XDestroyImage(image);/* Free memory resources used by the image */
  506.         exit(0);        /* Get outtahere */
  507.         break;
  508.       case Expose:
  509.         /* Put the original window's image into the... */
  510.         XPutImage(dpy2,(Drawable)copyWin,
  511.               gc,image,0,0,0,0,    /* ...copy of the window. */
  512.               copyWinInfo.width,copyWinInfo.height);
  513.         break;
  514.       }                /* end switch (event.type) */
  515.       gettimeofday(¤tTime,&zone);    /* Get the current time. */
  516.       /* Have 'updateTime' seconds passed? */
  517.       if (currentTime.tv_sec > (timeInSecs + updateTime))
  518.     { /* Yes, update the local copy of the window. */
  519.       if (srcWinUnmapped)/* Is the source window watchable? */
  520.         continue;    /* No, go through the event loop again. */
  521.       else    /* Yes, it's watchable, so get a new copy of the window. */
  522.         {
  523.           XDestroyImage(image);/* Free memory resources used by the image */
  524.           /* Store an image of the original window in an XImage */
  525.           image = XGetImage(dpy,(Drawable)win,
  526.                 0,0,
  527.                 copyWinInfo.width,copyWinInfo.height,
  528.                 AllPlanes,XYPixmap);
  529.         } /* end else XDestroyImage... */
  530.       /* Put the original window's image into the... */
  531.       XPutImage(dpy2,(Drawable)copyWin,
  532.             gc,image,0,0,0,0, /* ...copy of the window. */
  533.             copyWinInfo.width,copyWinInfo.height);
  534.       timeInSecs = currentTime.tv_sec;/* Update the current time */
  535.     }                /* end if currentTime... */
  536.     }                    /* end while(1) */
  537. }                    /* end function WatchWindow */
  538.  
  539.  
  540. /* Given the name of a window and the top of a ... */
  541. /* ...window tree, this function will try to find... */
  542. /* the Window ID corresponding to the window name... */
  543. /* ...given as argument. */
  544. Window GetWindowByName(window,windowName)
  545.      Window    window;
  546.      char    *windowName;
  547. {
  548.   Window    rootWin,parentWin,wID;
  549.   Window    *childWinList;
  550.   int        numChildren,i;
  551.   char        *childWinName;
  552.  
  553.   /* Get information about windows that are children... */
  554.   XQueryTree(dpy,window,
  555.          &rootWin,&parentWin,&childWinList,    /* ...of 'window'. */
  556.          &numChildren);
  557.   for (i=0;i<numChildren;i++) /* Look at each child of 'window' */
  558.     {
  559.       /* Get the name of that window */
  560.       XFetchName(dpy,childWinList[i],&childWinName);
  561.       if (childWinName != NULL) /* Is there a name attached to this window? */
  562.     {
  563.       /* Is this the window the user is looking for? */
  564.       if (WinNamesEqual(windowName,childWinName))
  565.         {
  566.           XFree(childWinList);/* Free up space taken by list of windows */
  567.           XFree(childWinName);/* Return space taken by this window's name */
  568.           /* Yes, return the Window ID of this window */
  569.           return(childWinList[i]);
  570.         }
  571.       XFree(childWinName);/* Return space taken by this window's name */
  572.     }        /* end if childWinName... */
  573.     }            /* end for i=0... */
  574.   /* If this section of code is reached, then no match was found at this
  575.    * level of the tree
  576.    */
  577.   for (i=0;i<numChildren;i++) /* Recurse on the children of this window */
  578.     {
  579.       wID = GetWindowByName(childWinList[i],windowName);
  580.       if (wID)        /* Was a match found in this window's children? */
  581.     {
  582.       XFree(childWinList); /* Free up space taken by list of windows */
  583.       return(wID);    /* Return the ID of the window that matched */
  584.     }
  585.     }            /* end for i=0... */
  586.   /* If this section of code is reached, then no match was found below
  587.    * this level of the tree
  588.    */
  589.   XFree(childWinList); /* Free up space taken by list of windows */
  590.   return((Window)0); /* No match was found, return 0. */
  591. }        /* end function GetWindowByName */
  592. 25787!Funky!Stuff!
  593. echo x - xwatchwin.man
  594. cat > xwatchwin.man << '25787!Funky!Stuff!'
  595. .TH xwatchwin 1 "17 March 1989" "X Version 11"
  596. .SH NAME
  597. xwatchwin - watch a window on another X server
  598. .SH SYNOPSIS
  599. .B "xwatchwin"
  600. hostname
  601. [\-u \fIupdatetime\fP] [\-w \fIwindowID\fP] [window name]
  602. .SH DESCRIPTION
  603. .PP
  604. \fIxwatchwin\fP allows you to peek at a window on another X server.
  605. To use it, you must specify the name of the machine you want to watch, then
  606. the name of the window on that machine.  \fIXwatchwin\fP will attempt to
  607. connect with the X server \fIhostname\fP:0.0, and if successful, will try
  608. to retrieve a copy of the window in which you specified interest.
  609.  
  610. You may specify the window you want to watch either by name or by its
  611. window id, usually a hexidecimal number.  Usually specifying the
  612. window by name is simpler, although not all windows have names
  613. associated with them; in that case you must use the window id option.
  614.  
  615. If the window you want to watch is not in a viewable state,
  616. \fIxwatchwin\fP will tell you so and exit.  If while you are watching a
  617. window it becomes 'unviewable', \fIxwatchwin\fP will print a message to
  618. stdout and wait until the window becomes 'viewable' again.
  619.  
  620. \fIxwatchwin\fP was written as an aid to a class for people learning to
  621. use X.  The idea is that the instructor would type into an xterm
  622. window on his/her display and the students would use \fIxwatchwin\fP to
  623. see what the instructor typed.  The students could then type the same
  624. thing in their own terminal windows.  I hope that others will find
  625. equally (if not more) constructive uses.
  626.  
  627. .SH OPTIONS
  628. .TP 8
  629. .B \-u \fIupdatetime\fP
  630. This option specifies how often (in seconds) you want to get a new copy
  631. of the window you're watching.  It is in effect a 'sample rate'.  By default,
  632. \fIxwatchwin\fP updates your copy of the window as often as it can.  The time
  633. it takes to actually do the update is dependent on the speed of the X server
  634. on both machines, the speed of the intervening network, and other factors.
  635. .TP 8
  636. .B \-w \fIwindowID\fP
  637. This option specifies the window you want to watch by number, for example,
  638. "0x50000b".  Use the xlswins(1) command to get a list of window id's and
  639. possibly their names on the remote server.  
  640.  
  641. You must specify a window to watch either by name or by id.  Specifying
  642. a window to watch by name is usually easier if you know what you're looking for.
  643. .SH EXAMPLES
  644. If there is an X server on the remote machine "crow" and if on that server
  645. there is a window called "X Terminal Emulator", you can watch that window
  646. by typing
  647.  
  648. xwatchwin crow X Terminal Emulator
  649.  
  650. If there is a window on "crow" that has no name but has a window id of
  651. "0x50000b", you can watch it by typing
  652.  
  653. xwatchwin crow -w 0x50000b
  654.  
  655. If you want to get new copies of a window only every 30 seconds, you can
  656. do so by typing
  657.  
  658. xwatchwin crow -u 30 -w 0x50000b
  659. .SH "SEE ALSO"
  660. xlswins(1), xwininfo(1), xdpyinfo(1),
  661. .SH BUGS
  662. \fIxwatchwin\fP doesn't support the \-display option.  You must set the
  663. display on which the \fIxwatchwin\fP window is created by changing your
  664. DISPLAY environment variable.
  665.  
  666. If the window you're watching is unmapped (made 'invisible')
  667. while \fIxwatchwin\fP
  668. is getting a new copy of that window, the program will crash.  The smaller
  669. your update interval, the more likely you are to experience this bug (although
  670. it hasn't happened all that often to me).
  671.  
  672. Parsing arguments is messy and not as forgiving as it should be.
  673.  
  674. The event loop is a mess.
  675.  
  676. \fIxwatchwin\fP cannot deal with two displays with different depths.
  677. For example, if the window you're watching is an 8-bit color window and
  678. your display only supports 2-bit color, \fIxwatchwin\fP will not be able
  679. to display the window.  To understand the issues involved in fixing
  680. this, see the paper by David's Lemke and Rosenthal, "\fIVisualizing X11
  681. Clients\fP".
  682. .SH COPYRIGHT
  683. Copyright 1989, George D. Drapeau
  684. .SH AUTHOR
  685. George D. Drapeau
  686. .PP
  687. Stanford University
  688. .br
  689. Academic Information Resources / Systems Development
  690. .br
  691. Internet: drapeau@jessica.stanford.edu
  692. .br
  693. UUCP: labrea!drapeau@jessica
  694. 25787!Funky!Stuff!
  695.