home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume12 / xicon / part01 next >
Text File  |  1991-03-20  |  19KB  |  735 lines

  1. Path: uunet!ukma!asuvax!cs.utexas.edu!sun-barr!newstop!exodus!cse.ogi.edu!trost%reed
  2. From: trost%reed@cse.ogi.edu
  3. Newsgroups: comp.sources.x
  4. Subject: v12i042: xicon, Part01/01
  5. Message-ID: <10105@exodus.Eng.Sun.COM>
  6. Date: 20 Mar 91 11:35:28 GMT
  7. Sender: news@exodus.Eng.Sun.COM
  8. Lines: 724
  9. Approved: argv@sun.com
  10.  
  11. Submitted-by: trost%reed@cse.ogi.edu
  12. Posting-number: Volume 12, Issue 42
  13. Archive-name: xicon/part01
  14.  
  15. IT EVEN WORKS!!!!
  16.  
  17. After months of eager anticipation, the new and *functional* version
  18. of xicon has been put together.  This version was actually tested
  19. before distribution.  I have been told it works under vtwm and tvtwm.
  20.  
  21. Also, the problem with spinning xicons (xica?) seems to have been
  22. eliminated.
  23.  
  24. Again, the patches were large enough warranting posting of the entire
  25. source --- not to mention the confusion caused by that broken
  26. distribution of xicon.  I posted this with filesize checking, just in
  27. case the Bitnot should happen to get a hold of it.
  28.  
  29. #!/bin/sh
  30. # to extract, remove the header and type "sh filename"
  31. if `test ! -s ./Imakefile`
  32. then
  33. echo "writing ./Imakefile"
  34. cat > ./Imakefile << '\End\Of\Shar\'
  35.         DEPLIBS = $(DEPXLIB)
  36. LOCAL_LIBRARIES = $(XLIB)
  37.            SRCS = xicon.c
  38.            OBJS = xicon.o
  39.  
  40. ComplexProgramTarget(xicon)
  41. \End\Of\Shar\
  42. else
  43.   echo "will not over write ./Imakefile"
  44. fi
  45. if [ `wc -c ./Imakefile | awk '{printf $1}'` -ne 136 ]
  46. then
  47. echo `wc -c ./Imakefile | awk '{print "Got " $1 ", Expected " 136}'`
  48. fi
  49. if `test ! -s ./patchlevel.h`
  50. then
  51. echo "writing ./patchlevel.h"
  52. cat > ./patchlevel.h << '\End\Of\Shar\'
  53. #define PATCHLEVEL 3
  54. \End\Of\Shar\
  55. else
  56.   echo "will not over write ./patchlevel.h"
  57. fi
  58. if [ `wc -c ./patchlevel.h | awk '{printf $1}'` -ne 21 ]
  59. then
  60. echo `wc -c ./patchlevel.h | awk '{print "Got " $1 ", Expected " 21}'`
  61. fi
  62. if `test ! -s ./xicon.c`
  63. then
  64. echo "writing ./xicon.c"
  65. cat > ./xicon.c << '\End\Of\Shar\'
  66. #include <stdio.h>
  67. #include <ctype.h>
  68.  
  69. #ifdef SYSV
  70. # define SIGCHLD SIGCLD
  71. # ifndef att
  72. #  define sigsetmask(x)
  73. # endif /* !att */
  74. #else /* SYSV */
  75. # include <sys/wait.h>
  76. #endif /* SYSV */
  77.  
  78. #include <sys/signal.h>
  79. #include <sys/errno.h>
  80.  
  81. #include <X11/Xlib.h>
  82. #include <X11/Xresource.h>
  83. #include <X11/Xutil.h>
  84. #include <X11/Xatom.h>
  85.  
  86. static char* programName;
  87. #define programClass  "XIcon"
  88.  
  89. typedef struct {
  90.     Window window;
  91.     Bool running;
  92.     char* name;
  93.     char* title;
  94.     char* class;
  95.     char* icon_name;
  96.     char* command;
  97. } Icon;
  98.  
  99. static childDied = 0;
  100. static wmFrame;
  101. static XrmDatabase initialDatabase, serverDatabase = 0;
  102.  
  103. static XrmOptionDescRec switches[] = {
  104.     { "-display",    ".display",    XrmoptionSepArg,
  105.       (caddr_t) NULL },
  106.     { "-wmframe",    ".wmFrame",    XrmoptionNoArg,
  107.       (caddr_t) "true" },
  108.     { "-xrm",        NULL,        XrmoptionResArg,
  109.       (caddr_t) NULL },
  110. };
  111.  
  112. static void
  113. usage()
  114. {
  115.     fprintf(stderr,
  116.         "usage: %s [ -display display ] \
  117. [ -wmframe ] [ -xrm resource [ ... ] ]\n", programName);
  118.     exit(1);
  119. }
  120.  
  121. static char*
  122. GetStringResource(name, class)
  123. char* name;
  124. char* class;
  125. {
  126.     char* type;
  127.     XrmValue value;
  128.  
  129.     if (!XrmGetResource(initialDatabase, name, class, &type, &value))
  130.     if (serverDatabase &&
  131.         !XrmGetResource(serverDatabase, name, class, &type, &value))
  132.         return 0;
  133.     return (char*) value.addr;
  134. }
  135.  
  136. static Bool
  137. GetBooleanResource(name, class, dflt)
  138. char* name;
  139. char* class;
  140. Bool dflt;
  141. {
  142.     char* resource;
  143.     char* s;
  144.     char** p;
  145.     static char* affirmation[] = { "yes", "on", "true", 0 };
  146.     static char* denial[] = { "no", "off", "false", 0 };
  147.  
  148.     resource = GetStringResource(name, class);
  149.  
  150.     if (!resource)
  151.     return dflt;
  152.  
  153.     for (s = resource; *s; s++)
  154.     if (isupper(*s))
  155.         *s = tolower(*s);
  156.  
  157.     p = affirmation;
  158.     while (*p)
  159.     if (strcmp(*p++, resource) == 0)
  160.         return 1;
  161.  
  162.     p = denial;
  163.     while (*p)
  164.     if (strcmp(*p++, resource) == 0)
  165.         return 0;
  166.  
  167.     return dflt;
  168. }
  169.  
  170. /*
  171.   We need a mapping from pids to windows.
  172.  */
  173.  
  174. typedef struct pidmap {
  175.     int pid;
  176.     Window window;
  177.     struct pidmap* next;
  178. } pidmap;
  179.  
  180. static pidmap* processes = 0;
  181.  
  182. static void
  183. HandleDeadChildren(display, icons)
  184. Display* display;
  185. XContext icons;
  186. {
  187.     while (childDied) {
  188.     int pid = wait(0);
  189.     pidmap** process = &processes;
  190.     pidmap* old;
  191.     Icon* icon;
  192.  
  193.     while (*process && (*process)->pid != pid)
  194.         process = &(*process)->next;
  195.  
  196.     if (!*process) {
  197.         fprintf(stderr, "Programmer error --- lost a process!\n");
  198.         abort();
  199.     }
  200.  
  201.     old = *process;
  202.     *process = old->next;
  203.     XUnmapWindow(display, old->window);
  204.     XMapWindow(display, old->window);
  205.  
  206.     /*
  207.       Thanks to jik@pit-manager.mit.edu for the correct cast in
  208.       XFindContext.  I just *couldn't* figure out what gcc was
  209.       complaining about....
  210.      */
  211.     if (XFindContext(display, old->window, icons,
  212.              (caddr_t*) &icon) != XCSUCCESS) {
  213.         fprintf(stderr, "Programmer error --- lost an icon!\n");
  214.         abort();
  215.     }
  216.     icon->running = 0;
  217.     free((char*) old);
  218.     childDied--;
  219.     }
  220. }
  221.  
  222. static void
  223. HandleSIGCHLD()
  224. {
  225.     childDied++;
  226. }
  227.  
  228. static void
  229. AddProcess(display, window, icons)
  230. Display* display;
  231. Window window;
  232. XContext icons;
  233. {
  234.     Icon* icon;
  235.     int pid;
  236.     XUnmapEvent sendEvent;
  237.  
  238.     if (XFindContext(display, window, icons, (caddr_t*) &icon) != XCSUCCESS) {
  239.     fprintf(stderr, "Programmer error --- lost an icon!\n");
  240.     abort();
  241.     }
  242.  
  243.     XUnmapWindow(display, icon->window);
  244.  
  245.     /*
  246.       ICCCM says we must do this, as the window may have since
  247.       become unmapped....
  248.       */
  249.     sendEvent.event = DefaultRootWindow(display);
  250.     sendEvent.window = icon->window;
  251.     sendEvent.from_configure = 0;
  252.     XSendEvent(display, sendEvent.event, 0,
  253.            SubstructureRedirectMask | SubstructureNotifyMask,
  254.            (XEvent*) &sendEvent);
  255.  
  256.     XFlush(display);        /* do it NOW! */
  257.     
  258.     if (icon->running)
  259.     /* Prevent a race-sort of condition if the child dies too quickly? */
  260.     HandleDeadChildren(display, icons);
  261.     else {
  262.     pidmap* process;
  263.     char* command = icon->command;
  264.     char* s;
  265.  
  266.     icon->running = 1;
  267.  
  268.     /* ??? We need to conditionally redefine vfork as fork. */
  269.  
  270.     /*
  271.       Never you mind the above; there is a bug with Ultrix 4.0+
  272.       RISC; if the child process from a vfork fails to do an exec,
  273.       the parent never receives a SIGCHLD.
  274.          -|trost Fri Feb  8 12:00:06 1991
  275.      */
  276.  
  277.     switch (pid = fork()) {
  278.     case -1:
  279.         perror("fork");
  280.         exit(2);
  281.         /* NOT REACHED */
  282.     case 0:
  283.         setpgrp(0, getpid());
  284.         for (s = command; *s; s++)
  285.         if (index(" \t\n|<>&'\"*?$()[]{}=\\;~`", *s)) {
  286.             char* getenv();
  287.             char* shell = getenv("SHELL");
  288.             
  289.             execl(shell, shell, "-c", command, 0);
  290.             break;
  291.         }
  292.         if (!*s)
  293.         execlp(command, command, 0);
  294.         fprintf(stderr, "Couldn't run \"%s\".\n", command);
  295.         perror("exec");
  296.         exit(0);
  297.         /* NOT REACHED */
  298.     }
  299.  
  300.     process = (pidmap*) malloc(sizeof(*process));
  301.     process->window = icon->window;
  302.     process->pid = pid;
  303.     process->next = processes;
  304.     processes = process;
  305.     }
  306. }
  307.  
  308. static Window
  309. CreateIconWindow(display, icon)
  310. Display* display;
  311. Icon* icon;
  312. {
  313.     Window window = XCreateSimpleWindow(display, DefaultRootWindow(display),
  314.                     0, 0,  2, 2,  0, 0,  None);
  315.     XClassHint    classHint;
  316.     XSizeHints    sizeHints;
  317.     XWMHints    wmHints;
  318.     char    hostname[255];
  319.     XSetWindowAttributes    attributes;
  320.  
  321.     XSelectInput(display, window, ExposureMask | StructureNotifyMask);
  322.  
  323.     classHint.res_name = icon->name;
  324.     classHint.res_class = icon->class;
  325.     XSetClassHint(display, window, &classHint);
  326.  
  327.     /*
  328.       Obsolete, but we should set for old wm's.  And maybe new wm's
  329.       will be nice and do it for us anyhow (since I can't figure out
  330.       the new way of doing it).
  331.      */
  332.     sizeHints.flags = PPosition;
  333.     sizeHints.x = 200;
  334.     sizeHints.y = 200;
  335.     XSetNormalHints(display, window, &sizeHints);
  336.  
  337.     /* This was hacked in so that tvtwm will put window on-screen. */
  338.     /* Transient for self?  Sure, why not? */
  339.     XSetTransientForHint(display, window, window);
  340.  
  341.     XStoreName(display, window, icon->title);
  342.     XSetIconName(display, window, icon->icon_name);
  343.  
  344.     wmHints.flags = StateHint;
  345.     wmHints.initial_state = IconicState;
  346.     XSetWMHints(display, window, &wmHints);
  347.  
  348.     attributes.backing_store = NotUseful;
  349.     XChangeWindowAttributes(display, window, CWBackingStore, &attributes);
  350.  
  351.     gethostname(hostname, sizeof(hostname));
  352.     XChangeProperty(display, window, XA_WM_CLIENT_MACHINE, XA_STRING, 8,
  353.             PropModeReplace, (unsigned char*) hostname,
  354.             strlen(hostname));
  355.  
  356.     return window;
  357. }
  358.  
  359. static void
  360. CreateIcon(display, icons, name)
  361. Display* display;
  362. XContext icons;
  363. char* name;
  364. {
  365.     char    resource[255], class[255];
  366.     char    baseResource[255];
  367.     char    baseClass[255];
  368.     Icon*    icon = (Icon*) Xpermalloc(sizeof(Icon));
  369.  
  370.     icon->name = name;
  371.  
  372.     sprintf(baseResource, "%s.%s.%%s", programName, name);
  373.     sprintf(baseClass, "%s.%s.%%s", programClass, name);
  374.  
  375.     sprintf(resource, baseResource, "class");
  376.     sprintf(class, baseClass, "Class");
  377.     if (icon->class = GetStringResource(resource, class))
  378.     sprintf(baseClass, "%s.%s.%%s", programClass, icon->class);
  379.     else
  380.     icon->class = name;
  381.  
  382.     sprintf(resource, baseResource, "title");
  383.     sprintf(class, baseClass, "Title");
  384.     icon->title = GetStringResource(resource, class);
  385.     if (!icon->title)
  386.     icon->title = name;
  387.  
  388.     sprintf(resource, baseResource, "iconName");
  389.     sprintf(class, baseClass, "IconName");
  390.     icon->icon_name = GetStringResource(resource, class);
  391.     if (!icon->icon_name)
  392.     icon->icon_name = icon->title ? icon->title : name;
  393.  
  394.     sprintf(resource, baseResource, "command");
  395.     sprintf(class, baseClass, "Command");
  396.     icon->command = GetStringResource(resource, class);
  397.     if (!icon->command)
  398.     icon->command = name;
  399.  
  400.     icon->running = 0;
  401.     icon->window = CreateIconWindow(display, icon);
  402.  
  403.     XSaveContext(display, icon->window, icons, icon);
  404.  
  405.     sprintf(resource, baseResource, "startIconic");
  406.     sprintf(class, baseClass, "Command");
  407.     if (GetBooleanResource(resource, class, 1))
  408.     XMapWindow(display, icon->window);
  409.     else
  410.     AddProcess(display, icon->window, icons);
  411. }
  412.     
  413. static char**
  414. ParseIconList(list)
  415. char* list;
  416. {
  417.     int i;
  418.     static char* rv[255];
  419.     char buf[1024];
  420.  
  421.     if (!list) {
  422.     rv[0] = 0;
  423.     return rv;
  424.     }
  425.  
  426.     /*
  427.       The upper bound for the loop has been decreased by one so that
  428.       we can add the terminating null pointer to the array if our
  429.       array fills up.
  430.      */
  431.     for (i = 0; i < sizeof(rv)/sizeof(rv[0]) - 1; i++) {
  432.     char* s = buf;
  433.     /* eat leading whitespace */
  434.     while (*list == ' ' || *list == '\t')
  435.         list++;
  436.     while (*list && *list != ',')
  437.         *s++ = *list++;
  438.     *s++ = '\0';
  439.     rv[i] = Xpermalloc(s - buf);
  440.     bcopy(buf, rv[i], s - buf);
  441.     if (!*list) {
  442.         rv[i + 1] = 0;
  443.         return rv;
  444.     }
  445.     list++;
  446.     }
  447.     fprintf(stderr, "Sorry, \"only\" 255 icons supported; continuing....\n");
  448.     rv[i] = 0;
  449.     return rv;
  450. }
  451.  
  452. static void
  453. Dispatch(event, icons)
  454. XEvent* event;
  455. XContext icons;
  456. {
  457.     XEvent junkEvent;
  458.     switch (event->type) {
  459.     case UnmapNotify:
  460.     case ReparentNotify:
  461.     case ConfigureNotify:
  462.     /* ignore */
  463.     break;
  464.     case MapNotify:
  465.     XRaiseWindow(event->xany.display, event->xany.window);
  466.     XMoveWindow(event->xany.display, event->xany.window, 5, 5);
  467.     break;
  468.     case Expose:
  469.     /*
  470.       Let's try sucking off all the exposes that might be pending
  471.       for this window.
  472.      */
  473.     if (wmFrame) {
  474.         Window root, parent;
  475.         Window* children;
  476.         unsigned nchildren;    /* should always be zero */
  477.  
  478.         XQueryTree(event->xany.display, event->xany.window,
  479.                &root, &parent, &children, &nchildren);
  480.         XFree((char *) children);
  481.         if (root == parent)
  482.         break;
  483.     }
  484.     AddProcess(event->xany.display, event->xany.window, icons);
  485.     break;
  486.     default:
  487.     fprintf(stderr, "Strange event %d.\n", event->type);
  488.     break;
  489.     }
  490. }
  491.  
  492. main(argc, argv)
  493. int argc;
  494. char** argv;
  495. {
  496.     Display* display;
  497.     char* displayName;
  498.     char resource[255], class[255];
  499.     char* waitString;
  500.     int i;
  501.     char** iconNames;
  502.     char** name;
  503.     XContext icons;
  504.     char* rindex();
  505.     int fd;
  506.  
  507.     programName = rindex(argv[0], '/');
  508.     if (programName)
  509.     programName++;
  510.     else
  511.     programName = argv[0];
  512.  
  513.     XrmParseCommand(&initialDatabase,
  514.             switches, sizeof(switches)/sizeof(switches[0]),
  515.             programName, &argc, argv);
  516.  
  517.     if (argc > 1)
  518.     usage();
  519.             
  520.     sprintf(resource, "%s.display", programName);
  521.     display = XOpenDisplay(displayName = GetStringResource(resource, ""));
  522.  
  523.     if (!display) {
  524.     fprintf(stderr, "Couldn't open display \"%s\"\n",
  525.         XDisplayName(displayName));
  526.     usage();
  527.     }
  528.  
  529.     serverDatabase = XrmGetStringDatabase(display->xdefaults);
  530.  
  531.     sprintf(resource, "%s.wmFrame", programName);
  532.     sprintf(class, "%s.WmFrame", programClass);
  533.     wmFrame = GetBooleanResource(resource, class, 0);
  534.  
  535.     sprintf(resource, "%s.icons", programName);
  536.     sprintf(class, "%s.Icons", programClass);
  537.     iconNames = ParseIconList(GetStringResource(resource, class));
  538.  
  539.     for (name = iconNames; *name; name++)
  540.     CreateIcon(display, icons, *name);
  541.  
  542.     fd = ConnectionNumber(display);
  543.  
  544.     (void) signal(SIGCHLD, HandleSIGCHLD);
  545.  
  546.     /*
  547.       Some machines (e.g., Tek 4317) start processes with some bogus
  548.       sigmask.  If I were trying to port this program and sigsetmask
  549.       failed to link, I'd remove the following lines, or, if you feel
  550.       up to it, inspect the #ifdef junk at the top of the file.
  551.      */
  552.  
  553.     sigsetmask(0);
  554.  
  555.     for (;;) {
  556.     static unsigned long readfds[1], exceptfds[1];
  557.     XEvent event;
  558.     extern int errno;
  559.  
  560.     if (*readfds) {
  561.         XNextEvent(display, &event);
  562.         Dispatch(&event, icons);
  563.     }
  564.  
  565.     while (i = XPending(display))
  566.         while (i--) {
  567.         XNextEvent(display, &event);
  568.         Dispatch(&event, icons);
  569.         }
  570.     XFlush(display);
  571.     
  572.     readfds[fd/32] = 1 << fd % 32;
  573.     exceptfds[fd/32] = 1 << fd % 32;
  574.  
  575.     HandleDeadChildren(display, icons);
  576.     /*
  577.       race condition here:  If a child dies here before the select starts,
  578.       no one will ever know about it....
  579.      */
  580.     while (select(fd + 1, readfds, 0, exceptfds, 0) < 1) {
  581.         if (errno != EINTR) {
  582.         perror("select");
  583.         exit(2);
  584.         }
  585.         HandleDeadChildren(display, icons);
  586.         XFlush(display);
  587.     }
  588.     }
  589. }
  590. \End\Of\Shar\
  591. else
  592.   echo "will not over write ./xicon.c"
  593. fi
  594. if [ `wc -c ./xicon.c | awk '{printf $1}'` -ne 12133 ]
  595. then
  596. echo `wc -c ./xicon.c | awk '{print "Got " $1 ", Expected " 12133}'`
  597. fi
  598. if `test ! -s ./xicon.man`
  599. then
  600. echo "writing ./xicon.man"
  601. cat > ./xicon.man << '\End\Of\Shar\'
  602. .TH XICON 1 "20 September 1990" "X contributed software"
  603. .SH NAME
  604. xicon -- manage "inactive icons"
  605. .SH SYNOPSIS
  606. \fBxicon\fP
  607. [-display \fIdisplay\fP]
  608. [-wmframe]
  609. [-xrm \fIresource\fP [...]]
  610. .SH DESCRIPTION
  611. \fIXicon\fP creates a set of icons; when one of these icons becomes
  612. deiconified, a user-specified program is started.  When a program
  613. started by \fIxicon\fP exits, the fake icon is restarted.
  614. .PP
  615. The program starts out by reading its "icons" (class "Icons")
  616. resource, which is a comma-separated list of icons to create.
  617. \fIXicon\fP then reads the resources specific to each of those icons
  618. (described below).
  619. .SH RESOURCES
  620. \fIXicon\fP is of class "XIcon".
  621. .TP 8
  622. .B "wmFrame (\fPclass\fB WmFrame)"
  623. This resource tells xicon that it should treat the icon as being
  624. deiconified only if there is a window-manager frame on the icon
  625. window.  This is very useful if you have occasion to restart your
  626. window manager, or if you exit your session while xicon is still
  627. running (the window manager can get killed before the xicon does,
  628. meaning that \fIall\fP your icons become deiconified, and many will
  629. end up in the next person's session).
  630. .PP
  631. Icon resources are specified by "xicon.\fIicon\fP.\fIresource\fP."  If
  632. a class name is specified for the icon, class lookups will be of the
  633. form "XIcon.\fIclass\fP.\fIresource\fP."  Icon resources are as follows:
  634. .TP 8
  635. .B "class (\fPclass\fB Class)"
  636. This is the first resource read for each icon.  It specifies the
  637. icon's resource class, which can be used for further lookups (as
  638. described above).
  639. .TP 8
  640. .B "command (\fPclass\fB Command)"
  641. This specifies the command to be executed when the icon is activated.
  642. The command is fed to $SHELL intact (unless the command looks
  643. like a simple single-word command, in which case it is executed
  644. directly), so pipes, redirection, and the
  645. "exec" shell builtin are all useful.  One useful command (for shells
  646. supporting it, like GNU bash) is "kill $PPID", to exit \fIxicon\fP.
  647. \fIXicon\fP could then be used as a session manager.
  648. .TP 8
  649. .B "iconName (\fPclass\fB IconName)"
  650. This resource specifies the WM_ICON_NAME property
  651. for the icon, and is used as
  652. the name for the icon by most window managers.  It defaults to the
  653. value of the title resource (see below).
  654. .TP 8
  655. .B "startIconic (\fPclass\fB StartIconic)"
  656. This resource, true by default, indicates whether \fIxicon\fP
  657. will start by displaying the icon or by immediately starting the
  658. program.  Useful if you want to start some things running but would
  659. still like to have them managed by \fIxicon\fP.
  660. .TP 8
  661. .B "title (\fPclass\fB Title)"
  662. This resource specifies the WM_NAME property for the icon, which is
  663. used as the "window name" (as opposed to the icon name) for the icon.
  664. This is of relevance in certain cases -- for instance, the window name
  665. appears in TWM's window menu.
  666. .PP
  667. All icon resources default to icon's name as specified in the "XIcon.icons"
  668. resource unless otherwise specified.
  669. .SH EXAMPLE
  670. The following is a reasonable (albeit somewhat contrived) set of X
  671. defaults:
  672. .EX 0
  673. XIcon.icons:        xterm, slowvax, exit, hibernate, xwininfo, xclock
  674. ! My window manager can do clever things with the name (like put
  675. ! parentheses around it.
  676. XIcon*class:        XIcon
  677. ! Gotta start somewhere...
  678. XIcon.xterm.startIconic:    false
  679. ! Both "exit" and "hibernate" are based on a bash feature which sets
  680. ! $PPID to the shell's parent process (oddly enough).
  681. ! Hibernate makes xicon go away and restart in 20 seconds.  But make
  682. ! sure our parent isn't /etc/init....
  683. XIcon.hibernate.command: \\
  684.     set `ps ww$PPID` ; kill $PPID ; shift 9 ; sleep 20 ; \\
  685.         [ $PPID -gt 1 ] && exec $*
  686. XIcon.exit.command:    kill $PPID
  687. XIcon.slowvax.command:    xterm -T reed -e rlogin reed
  688. XIcon.xwininfo.command: \\
  689.     xterm -T 'window info' -e sh -c 'xwininfo -all ; cat > /dev/null'
  690. ! Just some cute names for the xclock.
  691. XIcon.xclock.iconName:    Clock
  692. XIcon.xclock.Title:    Ugly Blue Clock
  693. .EE
  694. .SH ENVIRONMENT
  695. .IP "DISPLAY" 8
  696. Determines X server to use.
  697. .IP "SHELL" 8
  698. Specifies shell to be used for command invocation.
  699. .SH BUGS
  700. WmFrame should probably be true by default.
  701. .PP
  702. Under \fItwm\fP (and probably most other window managers)
  703. there is a brief flash as the "real" xicon window gets mapped by the
  704. window manager when the icon gets deiconified.  This is ugly, to say
  705. the least.
  706. .PP
  707. \fIXdm\fP may fail to set the SHELL environment variable if it
  708. is empty (used to imply a default of /bin/sh under some version of
  709. Unix).
  710. \fIXIcon\fP will either crash or fail on such machines.
  711. A good workaround (even if you don't used \fIxicon\fP) is to 
  712. check for a null SHELL in the system Xsession and set it to /bin/sh.
  713. .SH AUTHOR
  714. Bill Trost (trost%reed@cse.ogi.edu)
  715. \End\Of\Shar\
  716. else
  717.   echo "will not over write ./xicon.man"
  718. fi
  719. if [ `wc -c ./xicon.man | awk '{printf $1}'` -ne 4638 ]
  720. then
  721. echo `wc -c ./xicon.man | awk '{print "Got " $1 ", Expected " 4638}'`
  722. fi
  723. echo "Finished archive 1 of 1"
  724. exit
  725.  
  726. --
  727. Dan Heller
  728. ------------------------------------------------
  729. O'Reilly && Associates         Z-Code Software
  730. Senior Writer                   President
  731. argv@ora.com            argv@zipcode.com
  732. ------------------------------------------------
  733. General Email: argv@sun.com
  734. Comp-sources-x stuff: comp-sources.x@uunet.uu.net
  735.