home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / awm2 / part04 / GetButton.c next >
Encoding:
C/C++ Source or Header  |  1989-02-17  |  21.7 KB  |  819 lines

  1.  
  2.  
  3.  
  4. #ifndef lint
  5. static char *rcsid_GetButton_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/GetButton.c,v 1.3 89/02/07 22:39:19 jkh Exp $";
  6. #endif    lint
  7.  
  8. #include "X11/copyright.h"
  9. /*
  10.  *
  11.  * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  12.  *
  13.  * Copyright 1987 by Jordan Hubbard.
  14.  *
  15.  *
  16.  *                         All Rights Reserved
  17.  *
  18.  * Permission to use, copy, modify, and distribute this software and its
  19.  * documentation for any purpose and without fee is hereby granted,
  20.  * provided that the above copyright notice appear in all copies and that
  21.  * both that copyright notice and this permission notice appear in
  22.  * supporting documentation, and that the name of Ardent Computer
  23.  * Corporation or Jordan Hubbard not be used in advertising or publicity
  24.  * pertaining to distribution of the software without specific, written
  25.  * prior permission.
  26.  *
  27.  */
  28.  
  29. /*
  30.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  31.  *
  32.  *                         All Rights Reserved
  33.  *
  34.  * Permission to use, copy, modify, and distribute this software and its
  35.  * documentation for any purpose and without fee is hereby granted,
  36.  * provided that the above copyright notice appear in all copies and that
  37.  * both that copyright notice and this permission notice appear in
  38.  * supporting documentation, and that the name of Digital Equipment
  39.  * Corporation not be used in advertising or publicity pertaining to
  40.  * distribution of the software without specific, written prior permission.
  41.  *
  42.  *
  43.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  44.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  45.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  46.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  47.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  48.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  49.  * SOFTWARE.
  50.  */
  51.  
  52.  
  53.  
  54. /*
  55.  * MODIFICATION HISTORY
  56.  *
  57.  * 000 -- M. Gancarz, DEC Ultrix Engineering Group
  58.  * 001 -- L. Guarino Reid, DEC Ultrix Engineering Group, Western Software Lab
  59.  *      February 16, 1987
  60.  *      Add EnterWindow, LeaveWindow, and MouseMotion as recognized
  61.  *      awm buttons for awm menus. Add bug fixes to prevent mem faults
  62.  *      if icon_str is NULL.
  63.  * 002 -- L. Guarino Reid, DEC Ultrix Engineering Group
  64.  *      April 16, 1987
  65.  *      Convert to X11
  66.  * 003 -- J. Hubbard, U.C. Berkeley. Title/gadget box event handling.
  67.  *    December 3, 1987.
  68.  * 004 -- J.Hubbard, Ardent Computer. More conformance with ICCCM. Merge of
  69.  * changes from R2 uwm.
  70.  */
  71.  
  72. #ifndef lint
  73. static char *sccsid = "@(#)GetButton.c    3.8    1/24/86";
  74. #endif
  75. /*
  76.  *    GetButton - This subroutine is used by the Ardent Window Manager (awm)
  77.  *    to acquire button events.  It waits for a button event to occur
  78.  *    and handles all event traffic in the interim.
  79.  *
  80.  *    File:        GetButton.c
  81.  */
  82.  
  83. #include "awm.h"
  84. #include "X11/Xutil.h"
  85.  
  86. extern XContext AwmContext;
  87. extern Window FocusWindow;
  88.  
  89. #define ICONSTR    (icon_str ? icon_str : "")
  90. /* Amount of padding between text in a title bar and the edge of the bar */
  91. #define PAD    1
  92.  
  93. static Icon_modified = FALSE;
  94.  
  95. Boolean GetButton(b_ev)
  96. XEvent *b_ev;    /* Button event packet. */
  97. {
  98. #define STRLEN 50
  99.      char *icon_str;        /* Icon's name string. */
  100.      register int icon_str_len;    /* Icon name string lenght.  */
  101.      register int key_char;    /* Key press character code. */
  102.      register int icon_x;    /* Icon window X coordinate. */
  103.      register int icon_y;    /* Icon window Y coordinate. */
  104.      register unsigned int icon_w;    /* Icon window width. */
  105.      register unsigned int icon_h;    /* Icon window height. */    
  106.      int status;            /* Routine call return status. */
  107.      Window icon;        /* Icon window. */
  108.      XWindowAttributes win_info;    /* Icon window info structure. */
  109.      char kbd_str[STRLEN];      /* Keyboard string. */
  110.      int nbytes;                /* Keyboard string length. */
  111.      int i;                     /* Iteration counter. */
  112.      Window win;        /* scratch */
  113.      AwmInfoPtr awi;
  114.      extern char *GetTitleName();
  115.      
  116.      Entry("GetButton")
  117.   
  118.      /*
  119.       * Get next event from input queue and store it in the event packet
  120.       * passed to GetButton.
  121.       */
  122.   
  123.      XNextEvent(dpy, b_ev);
  124.      /* print_event_info("mainloop", b_ev); /* debugging for event handling */
  125.  
  126.      /*
  127.       * The event occured on the root window, check for substructure
  128.       * changes. Otherwise, it must be a mouse button event. 
  129.       */
  130.  
  131.      if (b_ev->xany.window == RootWindow(dpy, scr)) {
  132.       switch (b_ev->xany.type) {
  133.       case CreateNotify:
  134.       case UnmapNotify:
  135.       case ReparentNotify:
  136.       case ConfigureNotify:
  137.       case GravityNotify:
  138.       case MapNotify:
  139.       case CirculateNotify:
  140.            Leave(FALSE)
  141.             
  142.       case MappingNotify:
  143.            XRefreshKeyboardMapping((XMappingEvent *) b_ev);
  144.            Leave(FALSE)
  145.  
  146.       case MapRequest: 
  147.            CheckMap(b_ev->xmap.window);
  148.            Leave(FALSE)
  149.  
  150.       case ConfigureRequest: 
  151.            Configure((XConfigureRequestEvent *)b_ev);
  152.            Leave(FALSE)
  153.            
  154.       case CirculateRequest: 
  155.            Circulate((XCirculateEvent *)b_ev);
  156.            Leave(FALSE)
  157.            
  158.       case DestroyNotify:
  159.            RemoveIcon(b_ev->xdestroywindow.window);
  160.            Leave(FALSE)
  161.  
  162.       case FocusIn:
  163.            if (b_ev->xfocus.detail == NotifyPointerRoot) {
  164.             if (FocusSetByUser) {
  165.              XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
  166.                     CurrentTime);
  167.              FocusSetByUser = FALSE;
  168.              FocusWindow = RootWindow(dpy, scr);
  169.             }
  170.            }
  171.            Leave(FALSE)
  172.            
  173.       case FocusOut:
  174.            if (b_ev->xfocus.detail == NotifyPointerRoot) {
  175.             if (FocusSetByUser == FALSE && !FocusSetByWM) {
  176.              XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
  177.                     CurrentTime);
  178.              FocusWindow = RootWindow(dpy, scr);
  179.             }
  180.            }
  181.            Leave(FALSE)
  182.            
  183.       case ButtonPress:
  184.       case ButtonRelease:
  185.            Leave(TRUE)
  186.  
  187.       default: 
  188.            Leave(FALSE) 
  189.       }
  190.      }
  191.      
  192.      /*
  193.       * If the event type is EnterWindow, LeaveWindow, or MouseMoved,
  194.       * we are processing a menu. 
  195.       * If the event type is ButtonPress or ButtonRelease,
  196.       * we have a button event.
  197.       * If it's an expose, then we may have exposed a title bar.
  198.       * If it's a Notify, we've probably frobbed a titled window.
  199.       */
  200.      
  201.      switch (b_ev->type) {
  202.       XEvent e_fake;
  203.  
  204.      case MotionNotify: 
  205.      case ButtonPress: 
  206.      case ButtonRelease: 
  207.       Leave(TRUE)
  208.       break;
  209.  
  210.      case FocusIn:
  211.       if (!FocusSetByWM) {
  212.            e_fake.xcrossing.type = FocusIn;
  213.            e_fake.xcrossing.focus = TRUE;
  214.            e_fake.xcrossing.window = b_ev->xcrossing.window;
  215.            HandleFocusIn(&e_fake);
  216.       }
  217.       Leave(FALSE)
  218.       break;
  219.  
  220.      case FocusOut:
  221.       if (!FocusSetByWM) {
  222.            e_fake.xcrossing.type = FocusOut;
  223.            e_fake.xcrossing.focus = TRUE;
  224.            e_fake.xcrossing.window = b_ev->xcrossing.window;
  225.            HandleFocusOut(&e_fake);
  226.       }
  227.       Leave(FALSE)
  228.       break;
  229.       
  230.      case EnterNotify:
  231.       HandleFocusIn(b_ev);
  232.       Leave(FALSE)
  233.  
  234.      case LeaveNotify: 
  235.       HandleFocusOut(b_ev);
  236.       Leave(FALSE)
  237.  
  238.      case ConfigureRequest:
  239.       Configure((XConfigureRequestEvent *)b_ev);
  240.       Leave(FALSE)
  241.  
  242.      case MapRequest:
  243.       CheckMap(b_ev->xmap.window);
  244.       Leave(FALSE);
  245.  
  246.      case MapNotify:
  247.           Leave(FALSE)
  248.       break;
  249.       
  250.      case UnmapNotify:
  251.       win = b_ev->xunmap.window;
  252.           if (!(awi = GetAwmInfo(win)))
  253.               Leave(FALSE)
  254.  
  255.       if (IsIcon(win, None))
  256.            Leave(FALSE)
  257.        XUnmapWindow(dpy, awi->frame);
  258.       Leave(FALSE)
  259.       break;
  260.  
  261.      case DestroyNotify:
  262.       win = b_ev->xdestroywindow.window;
  263.           if (!(awi = GetAwmInfo(win)))
  264.               Leave(FALSE)
  265.       if (win != awi->title) {
  266.            /* remove any icon associated with this window */
  267.            RemoveIcon(win);
  268.            /* remove the frame/titlebar (if present) */
  269.            NoDecorate(win, TRUE);
  270.            /* punt the rest of the per-window info */
  271.            XDeleteContext(dpy, awi->client, AwmContext);
  272.            free(awi);
  273.       }
  274.           Leave(FALSE)
  275.  
  276.      case PropertyNotify:
  277.       win = b_ev->xproperty.window;
  278.           if (!(awi = GetAwmInfo(win)))
  279.                Leave(FALSE);
  280. #ifdef WMSTATE
  281.       if (!(b_ev->xproperty.atom==wm_state_atom)) /* ignore state change */
  282. #endif /* WMSTATE */
  283.       switch(b_ev->xproperty.atom) {
  284.  
  285.       case XA_WM_COMMAND:
  286.       case XA_WM_HINTS:
  287.       case XA_WM_CLIENT_MACHINE:
  288.            break;
  289.  
  290.       case XA_WM_ICON_NAME:
  291.            if (Icon_modified == TRUE) {
  292.             /*
  293.              * Icon was modified by type-in (I still think that's a
  294.              * gross feature, but some people like it... sigh),
  295.              * ignore this event.
  296.              */
  297.             Icon_modified = FALSE;    /* reset */
  298.             Leave(FALSE)
  299.            }
  300.            /*
  301.         * Icon was modifed in a more civilized fashion.
  302.         */
  303.            if (awi->icon && awi->own && awi->iconPixmap == IBackPixmap) {
  304.             win = awi->icon;
  305.             status = XGetWindowAttributes(dpy, win, &win_info);
  306.             icon_str = GetIconName(awi->client);
  307.             icon_str_len = icon_str ? strlen(icon_str) : 0;
  308.             if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
  309.                              strlen(ICONSTR)) +
  310.             (HIconPad << 1)) {
  311.              XResizeWindow(dpy, win, 
  312.                        XTextWidth(IFontInfo, ICONSTR,
  313.                           strlen(ICONSTR)) +
  314.                        (HIconPad << 1), IFontInfo->ascent +
  315.                        IFontInfo->descent + (VIconPad << 1));
  316.             }
  317.             XClearWindow(dpy, win);
  318.             if (icon_str_len != 0) {
  319.              XDrawImageString(dpy, win, IconGC, HIconPad,
  320.                       VIconPad+IFontInfo->ascent, icon_str,
  321.                       icon_str_len);
  322.              free(icon_str);
  323.             }
  324.            }
  325.            break;
  326.  
  327.       case XA_WM_ICON_SIZE:
  328.            break;
  329.  
  330.       case XA_WM_NAME:
  331.            if (awi->title) {
  332.             if (awi->name)
  333.              free(awi->name);
  334.             awi->name = GetTitleName(win);
  335.             PaintTitle(win, (FocusWindow == awi->client));
  336.            }
  337.            break;
  338.  
  339.       case XA_WM_NORMAL_HINTS:
  340.       case XA_WM_SIZE_HINTS:
  341.       case XA_WM_ZOOM_HINTS:
  342.            break;
  343.  
  344.       default:
  345.            fprintf(stderr, "awm: Got unknown property %d\n",
  346.                b_ev->xproperty.atom);
  347.       }
  348.       Leave(FALSE)
  349.       break;
  350.       
  351.       
  352.      case Expose:
  353.       win = b_ev->xexpose.window;
  354.           if (!(awi = GetAwmInfo(win))) /* probably a menu */
  355.                Leave(FALSE)
  356.       if (awi->title == win) {
  357.            if (b_ev->xexpose.count == 0) {
  358.             XEvent evt;
  359.  
  360.             /* Eat up any previous exposes */
  361.             while (XCheckTypedWindowEvent(dpy, awi->title, Expose,
  362.                           &evt));
  363.             PaintTitle(win, (FocusWindow == awi->client));
  364.             if (awi->gadgets)
  365.              PaintGadgets(win);
  366.            }
  367.            Leave(FALSE)
  368.       }
  369.       break;
  370.       
  371.      default:
  372.       break;
  373.      }
  374.      
  375.      /*
  376.       * If we got this far, the event must be for an icon.
  377.       */
  378.      win = b_ev->xany.window;
  379.      if (!(awi = GetAwmInfo(win)))
  380.           Leave(FALSE)
  381.      status = XGetWindowAttributes(dpy, win, &win_info);
  382.      if (status == FAILURE)
  383.       Leave(FALSE)
  384.      
  385.      if (b_ev->type == MapNotify || 
  386.      b_ev->type == UnmapNotify ||
  387.      b_ev->type == CreateNotify ||
  388.      b_ev->type == ReparentNotify ||
  389.      b_ev->type == GravityNotify ||
  390.      b_ev->type == CirculateNotify ||
  391.      b_ev->type == ConfigureNotify)
  392.       Leave(FALSE)
  393.      
  394.      /*
  395.       * Initialize the icon position variables.
  396.       */
  397.      icon_x = win_info.x;
  398.      icon_y = win_info.y;
  399.      
  400.      /*
  401.       * Get the name of the window associated with the icon and
  402.       * determine its length.
  403.       */
  404.      if (!awi->icon)
  405.       Leave(FALSE)
  406.      /*
  407.       * If we don't own it, or it's got a background pixmap, we don't have
  408.       * to repaint it.
  409.       */
  410.      if (!awi->own || (awi->iconPixmap != IBackPixmap))
  411.       Leave(FALSE)
  412.      icon = awi->icon;
  413.      icon_str = GetIconName(awi->client);
  414.      icon_str_len = icon_str ? strlen(icon_str) : 0;
  415.      
  416.      /*
  417.       * If the event is a window exposure event and the icon's name string
  418.       * is not of zero length, simply repaint the text in the icon window
  419.       * and return FALSE.
  420.       */
  421.      if (b_ev->type == Expose && (!Freeze || Frozen == 0)) {
  422.       if (win_info.width != XTextWidth(IFontInfo, ICONSTR,
  423.                        strlen(ICONSTR))+(HIconPad << 1)) {
  424.            XResizeWindow(dpy, icon, 
  425.                  XTextWidth(IFontInfo, ICONSTR,
  426.                     strlen(ICONSTR)) + (HIconPad << 1),
  427.                  IFontInfo->ascent + IFontInfo->descent + 
  428.                  (VIconPad << 1));
  429.       }
  430.       XClearWindow(dpy, icon);
  431.       if (icon_str_len != 0) {
  432.            XDrawImageString(dpy, icon,
  433.                 IconGC, HIconPad, VIconPad+IFontInfo->ascent,
  434.                 icon_str, icon_str_len);
  435.            /*
  436.         * Remember to free the icon name string.
  437.         */
  438.            free(icon_str);
  439.       }
  440.       Leave(FALSE)
  441.      }
  442.  
  443. #ifndef NO_ICON_TYPIN     
  444.      /*
  445.       * If we have gotten this far event can only be a key pressed event.
  446.       */
  447.      
  448.      /* 
  449.       * We convert the key pressed event to ascii.
  450.       */
  451.      nbytes = XLookupString((XKeyEvent *)b_ev, kbd_str, STRLEN,
  452.                 (KeySym *) NULL, (XComposeStatus *) NULL);
  453.      
  454.      /*
  455.       * If kbd_str is a "non-string", then don't do anything.
  456.       */
  457.      if (nbytes == 0 || !kbd_str || !*kbd_str) {
  458.       if (icon_str)
  459.            free(icon_str);
  460.       Leave(FALSE)
  461.      }
  462.      for (i = 0; i < nbytes; i++) {
  463.       key_char = kbd_str[i];
  464.       /*
  465.        * If the key was <DELETE>, then delete a character from the end of
  466.        * the name, return FALSE.
  467.        *
  468.        * If the key was <CTRL-U>, then wipe out the entire window name
  469.        * and return FALSE.
  470.        *
  471.        * All other ctrl keys are squashed and we return FALSE.
  472.        *
  473.        * All printable characters are appended to the window's name, which
  474.        * may have to be grown to allow for the extra length.
  475.        */
  476.       if (key_char == '\177') {
  477.            /*
  478.         * <DELETE>
  479.         */
  480.            if (icon_str_len > 0) {
  481.             icon_str_len--;
  482.             icon_str[icon_str_len] = '\0';
  483.            }
  484.       }
  485.       else if (key_char == '\025') {
  486.            /*
  487.         * <CTRL-U>
  488.         */
  489.            if (icon_str_len > 0) {
  490.             icon_str_len = 0;
  491.             icon_str[0] = '\0';
  492.            }
  493.       }
  494.       else if (key_char < IFontInfo->min_char_or_byte2 ||
  495.            key_char > IFontInfo->max_char_or_byte2) {
  496.            /*
  497.         * Any other random (non-printable) key; ignore it.
  498.         */
  499.            /* do nothing */ ;
  500.                }
  501.       else {
  502.            /*
  503.         * ASCII Alphanumerics.
  504.         */
  505.            if (icon_str == NULL)
  506.             icon_str = (char *) malloc (icon_str_len + 2);
  507.            else
  508.             icon_str = (char *)realloc(icon_str, (icon_str_len + 2));
  509.            if (icon_str == NULL) {
  510.             errno = ENOMEM;
  511.             Error("GetButton -> Realloc of window name string memory failed.");
  512.            }
  513.            icon_str[icon_str_len] = key_char;
  514.            icon_str[icon_str_len + 1] = '\0';
  515.            icon_str_len += 1;
  516.       }
  517.      }
  518.      
  519.      /*
  520.       * Now that we have changed the size of the icon we have to reconfigure
  521.       * it so that everything looks good.  Oh yes, don't forget to move the
  522.       * mouse so that it stays in the window!
  523.       */
  524.      
  525.      /*
  526.       * Set the window name to the new string. Icon_modified is a kludge
  527.       * that tells us to avoid the next PropertyNotify, as it's a result of
  528.       * this call.
  529.       */
  530.      XSetIconName(dpy, awi->client, ICONSTR);
  531.      Icon_modified = TRUE;
  532.      /*
  533.       * Determine the new icon window configuration.
  534.       */
  535.      icon_h = IFontInfo->ascent + IFontInfo->descent + (VIconPad << 1);
  536.      icon_w = XTextWidth(IFontInfo, ICONSTR, strlen(ICONSTR));
  537.      if (icon_w == 0) {
  538.       icon_w = icon_h;
  539.      }
  540.      else {
  541.       icon_w += (HIconPad << 1);
  542.      }
  543.      
  544.      if (icon_x < 0) icon_x = 0;
  545.      if (icon_y < 0) icon_y = 0;
  546.      if (icon_x - 1 + icon_w + (IBorderWidth << 1) > ScreenWidth) {
  547.       icon_x = ScreenWidth - icon_w - (IBorderWidth << 1) + 1;
  548.      }
  549.      if (icon_y - 1 + icon_h + (IBorderWidth << 1) > ScreenHeight) {
  550.       icon_y = ScreenHeight - icon_h - (IBorderWidth << 1) + 1;
  551.      }
  552.      
  553.      XMoveResizeWindow(dpy, icon, icon_x, icon_y, icon_w, icon_h);
  554.      XWarpPointer(dpy, None, icon, 
  555.           0, 0, 0, 0, (icon_w >> 1), (icon_h >> 1));
  556.      
  557.      /* 
  558.       * Free the local storage and return FALSE.
  559.       */
  560.      if (icon_str)
  561.       free(icon_str);
  562. #endif
  563.      Leave(FALSE)
  564. }
  565.  
  566. CheckMap(window)
  567. Window window;
  568. {
  569.      XWMHints *XGetWMHints();
  570.      XWMHints *wmhints;
  571.      Window transient_for = None;
  572.      Binding *bptr;
  573.      AwmInfoPtr awi;
  574.      long event_mask;
  575.  
  576.      Entry("CheckMap")
  577.  
  578.      /* if it's a transient window, we won't rubber-band
  579.       * note that this call always sets transient_for.
  580.       */
  581.      if (!XGetTransientForHint( dpy, window, &transient_for )) {
  582.       /*
  583.        * Handle any registered grabs for this window. We do this here
  584.        * because we may be about to make an icon out of this window
  585.        * and we want to register any potential grabs on it before this
  586.        * happens.
  587.        */
  588.       awi = GetAwmInfo(window);
  589.       if (!awi) {
  590.            for (bptr = Blist; bptr; bptr = bptr->next)
  591.             if (bptr->context & WINDOW)
  592.              Grab(bptr->mask, window);
  593.            awi = RegisterWindow(window);
  594.            Decorate(awi->client);
  595.            event_mask = PropertyChangeMask | FocusChangeMask;
  596.            if (!FrameFocus)
  597.             event_mask |= (EnterWindowMask | LeaveWindowMask);
  598.            XSelectInput(dpy, window, event_mask);
  599. #ifndef RAINBOW
  600.            SetBorderPixmaps(awi, GrayPixmap);
  601. #else
  602.            SetBorderPixmaps(awi, awi->grayPixmap);
  603. #endif
  604.       }
  605.       if ((wmhints = XGetWMHints(dpy, window))) {
  606.            if ((wmhints->flags & StateHint) && (awi->state & ST_WINDOW) &&
  607.            (wmhints->initial_state == IconicState)) {
  608.             /* window wants to be created as an icon. Leave size
  609.                /* and position alone, create as icon. */
  610.                          XFree(wmhints);
  611.                          Iconify(window, 0, 0, 0, 0);
  612.                          Leave_void
  613.            }
  614.            XFree(wmhints);
  615.       }
  616.      }
  617.      else { /* It's a transient */
  618.       if (!(awi = GetAwmInfo(window)))
  619.            awi = RegisterWindow(window);
  620.       awi->attrs = AT_NONE;
  621.       if (transient_for == None)
  622.            transient_for = RootWindow(dpy, scr);
  623.      }
  624.      if (awi->state & ST_WINDOW) {
  625.       PlaceWindow(window, transient_for);
  626.       if (awi->frame) {
  627.            XMapRaised(dpy, awi->frame);
  628.            XMapWindow(dpy, awi->client);
  629.       }
  630.       else
  631.            XMapRaised(dpy, awi->client);
  632.       XSync(dpy, 0);
  633.      }
  634.      Leave_void
  635. }
  636.  
  637. Configure(event)
  638. XConfigureRequestEvent *event;
  639. {
  640.      XWindowChanges values;
  641.      
  642.      Entry("Configure")
  643.  
  644.      values.x = event->x;
  645.      values.y = event->y;
  646.      values.width = event->width;
  647.      values.height = event->height;
  648.      values.border_width = event->border_width;
  649.      values.stack_mode = event->detail;
  650.      values.sibling = event->above;
  651.  
  652.      ConfigureWindow(event->window, event->value_mask, &values);
  653.      Leave_void
  654. }
  655.  
  656. Circulate(event)
  657. XCirculateEvent *event;
  658. {
  659.      Entry("Circulate")
  660.  
  661.      if (event->place == PlaceOnTop)
  662.       XRaiseWindow(event->display, event->window);
  663.      else
  664.       XLowerWindow(event->display, event->window);
  665.      Leave_void
  666. }
  667.  
  668. PlaceWindow(window, transient)
  669. Window window;
  670. Window transient;
  671. {
  672.      XSizeHints wsh;
  673.      int x, y;
  674.      unsigned int w, h;
  675.      XWindowChanges xwc;
  676.      AwmInfoPtr awi;
  677.      unsigned long flags;
  678.  
  679.      wsh.flags = 0;
  680.      flags = CWX | CWY | CWWidth | CWHeight;
  681.      awi = GetAwmInfo(window);
  682.      XGetSizeHints(dpy, window, &wsh, XA_WM_NORMAL_HINTS);
  683.      CheckConsistency(&wsh);
  684.      AskUser(dpy, scr, window, &x, &y, &w, &h, &wsh, transient);
  685.  
  686.      wsh.flags |= (USPosition | USSize);
  687.      wsh.x = x;
  688.      wsh.y = y;
  689.      wsh.width = w;
  690.      wsh.height = h;
  691.      if (x < 0 || y < 0) {
  692.       Window jW;
  693.       int j, border_width;
  694.  
  695.       XGetGeometry(dpy, window, &jW, &j, &j, &j, &j, &border_width, &j);
  696.  
  697.       if (x < 0)
  698.            x += DisplayWidth(dpy, scr) - w - (border_width<<1);
  699.       if (y < 0)
  700.            y += DisplayHeight(dpy, scr) - h - (border_width<<1);
  701.      }
  702.      if (awi->frame)
  703.       XSetSizeHints(dpy, awi->frame, &wsh, XA_WM_NORMAL_HINTS);
  704.      XSetSizeHints(dpy, awi->client, &wsh, XA_WM_NORMAL_HINTS);
  705. #ifdef titan /* 5x4 alignment */
  706.      x = ((x+3) / 5) * 5;
  707.      y = ((y+2) / 4) * 4;
  708. #endif
  709.      xwc.x = x;
  710.      xwc.y = y;
  711.      xwc.height = h;
  712.      xwc.width = w;
  713.      ConfigureWindow(window, flags, &xwc);
  714.      awi->state |= ST_PLACED;
  715. }
  716.  
  717. Boolean ConfigureWindow(w, mask, xwc)
  718. Window w;
  719. unsigned int mask;
  720. XWindowChanges *xwc;
  721. {
  722.      AwmInfoPtr awi;
  723.      int height, width, x, y;
  724.      int bch = 0, bcv = 0;
  725.      Entry("ConfigureWindow")
  726.  
  727.      awi = GetAwmInfo(w);
  728.      if (!awi) {
  729.       /*
  730.        * Make sure XtRealize gets its configure event. We'll actually
  731.        * do another configure before we map, but this fakes XtRealize
  732.        * into not waiting around for the configure notify.
  733.        */
  734.       XConfigureWindow(dpy, w, mask, xwc);
  735.       XFlush(dpy);
  736.           Leave(FALSE)
  737.      }
  738.  
  739.      if (awi->icon == w) {
  740.       XConfigureWindow(dpy, w, mask, xwc);
  741.       Leave(TRUE)
  742.      }
  743.      if (awi->attrs & AT_BORDER && DECORATED(awi)) {
  744.       bcv = BContext + 1;
  745.       bch = bcv * 2;
  746.      }
  747.  
  748.      height = xwc->height;
  749.      width = xwc->width;
  750.      if (awi->frame)
  751.       x = y = 0;
  752.      else {
  753.       x = xwc->x;
  754.       y = xwc->y;
  755.      }
  756.      /* width */
  757.      xwc->width += bch;
  758.      if (awi->title)
  759.       XResizeWindow(dpy, awi->title, (unsigned) xwc->width, 
  760.             (unsigned) titleHeight);
  761.      /* height */
  762.      if (DECORATED(awi)) {
  763.       if (awi->attrs & AT_TITLE) {
  764.            y = titleHeight + 2;
  765.            xwc->height += y;
  766.       }
  767.       if (awi->attrs & AT_BORDER) {
  768.            if (!(awi->attrs & AT_TITLE)) {
  769.             xwc->height += (bcv * 2);
  770.             y = bcv;
  771.            }
  772.            else
  773.             xwc->height += bcv;
  774.            xwc->x -= (BContext + (awi->border_width ? awi->border_width :
  775.                       1));
  776.            x = BContext;
  777.       }
  778.      }
  779.      if (PushDown == FALSE) {
  780.       if (awi->attrs & AT_TITLE && DECORATED(awi))
  781.            xwc->y -= (titleHeight + 2);
  782.       else if (awi->attrs & AT_BORDER && DECORATED(awi))
  783.            xwc->y -= (BContext + (awi->border_width ?
  784.                       awi->border_width : 1));
  785.      }
  786.      if (awi->frame)
  787.           XConfigureWindow(dpy, awi->frame, mask, xwc);
  788.      if (awi->gadgets)
  789.       PutGadgets(w);
  790.      xwc->width = width;
  791.      xwc->height = height;
  792.      xwc->x = x;
  793.      xwc->y = y;
  794.      XConfigureWindow(dpy, awi->client, mask, xwc);
  795.      Leave(TRUE)
  796. }
  797.  
  798. int
  799. ProcessRequests(box, num_vectors)
  800. XSegment *box;
  801. int num_vectors;
  802. {
  803.     XEvent event;
  804.  
  805.     XPeekEvent(dpy, &event);
  806.     switch (event.type) {
  807.  
  808.     case MapRequest:
  809.     case ConfigureRequest:
  810.     case CirculateRequest:
  811.  
  812.         DrawBox();
  813.         GetButton(&event);
  814.         DrawBox();
  815.         return TRUE;
  816.     }
  817.     return FALSE;
  818. }
  819.