home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gwm18a.zip / client.c < prev    next >
C/C++ Source or Header  |  1995-07-03  |  57KB  |  1,931 lines

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /*********************************************************\
  5. *                               *
  6. *     BULL WINDOW MANAGER for X11 .              *
  7. *                               *
  8. *     MODULE defining the ClientWindow Object Class.      *
  9. *                               *
  10. \*********************************************************/
  11.  
  12.  /* includes */
  13. #include    <stdio.h>
  14. #include    "EXTERN.h"
  15. #include     "wool.h"
  16. #include    "wl_atom.h"
  17. #include    "wl_string.h"
  18. #include    "wl_list.h"
  19. #include     "wl_number.h"
  20. #include     "wl_func.h"
  21. #include     "gwm.h"
  22. #include    "wl_event.h"
  23. #include     "wl_fsm.h"
  24. #include     "wl_pixmap.h"
  25. #include     "wl_cursor.h"
  26. #include     "wl_client.h"
  27. #ifdef SHAPE            /* compile with -I/usr/include/X11 AND
  28.                    -I/usr/include/X11/extensions to work on
  29.                    machines having shapes.h in either place */
  30. #include    <shape.h>
  31. extern WindowIsShaped();
  32. #endif /* SHAPE */
  33.  
  34. /*  local constants  */
  35.  
  36. /*  external  */
  37.  
  38. extern Wob      SetUpClientWindow();
  39. extern Bar      NewBar(), BarOpen();
  40. extern Wob      LookUpWob();
  41. extern ClientWindow LookUpClient();
  42. extern          UserAskWindow();
  43. extern          UserMessage();
  44. extern          FSMAction();
  45. extern WOOL_METHOD WLMenu[];
  46. extern XError(), NoXError();
  47. extern Window FindToplevelWindow();
  48. extern ClientWindow DecoratedWindow();
  49.  
  50.  
  51. /*  local  */
  52.  
  53. extern        ClientWindowEventHandler(), UpdateClientWindowGeometry();
  54. extern        ReconfigureClientWindow();
  55. ClientWindow    NewClientWindow(), NewClientWindowIcon(), 
  56.         window_is_still_alive(), NewIconWindow();
  57.  
  58. extern ClientWindowOpen(), ClientWindowClose();
  59.  
  60. WOB_METHOD      ClientWindowClass[] = {
  61.                        0,    /* METHODS_ARRAY */
  62.                        WobEval,
  63.                        WobPrint,
  64.                        WobRelease,
  65.                        WobExecute,
  66.                        WobSet,
  67.                        WobGetCValue,
  68.                        ClientWindowOpen,
  69.                        ClientWindowClose,
  70.                        ClientWindowEventHandler,
  71.                        (WOB_METHOD) wool_undefined_method_1,
  72.                        WobGetDimensions,
  73.                        (WOB_METHOD) wool_undefined_method_2,
  74.                        (WOB_METHOD) wool_undefined_method_2,
  75.                         ReconfigureClientWindow,
  76.             (WOB_METHOD) wool_undefined_method_2,
  77.             (WOB_METHOD) wool_undefined_method_1,
  78.             (WOB_METHOD) wool_undefined_method_1,
  79.             (WOB_METHOD) wool_undefined_method_1,
  80.             (WOB_METHOD) wool_undefined_method_1,
  81.             (WOB_METHOD) wool_undefined_method_1
  82. };
  83.  
  84. /* routines */
  85.  
  86. /*
  87.  * To decorate a window, we must:
  88.  *     - see if it is decorable
  89.  *     - get all info about it
  90.  *     - decorate it via NewClientWindow
  91.  */
  92.  
  93. ClientWindow
  94. DecorateWindow(window, parent, must_save_set, being_mapped)
  95. Window        window;
  96. ClientWindow    parent;
  97. int        must_save_set;        /* 0 for screen, 1 for windows */
  98. int        being_mapped;        /* 0 for decorating by reference */
  99. {
  100.     ClientWindow    cw;
  101.     WOOL_Client        wl_client;
  102.     int local_zrt_size = zrt_size;
  103.     XWindowAttributes wa;
  104.     Wob oldTargetWob = TargetWob;
  105.  
  106.     wa.override_redirect = 0;
  107.  
  108.     /* if window has died meanwhile, abort */
  109.     if (TrapXErrors(XGetWindowAttributes(dpy, window, &wa))
  110.     || wa.override_redirect) /* do not manage override_redirect wins */
  111.     return NULL;
  112.  
  113.     /* be careful, we might have decorated it in beetween */
  114.     if(cw = (ClientWindow) LookUpClient(window))
  115.         return cw;
  116.     GWM_window_being_decorated = cw = NewClientWindow(parent, window);
  117.     {
  118.     save_wool_error_resume_point();    /* contains decls */
  119.     if (set_wool_error_resume_point()) {
  120.         restore_wool_error_resume_point();
  121.         return 0;            /* aborts if window dies */
  122.     }
  123.     SetTarget(cw);
  124.     UpdateAllCachedProperties(cw);    /* some preliminar get_properties */
  125.     cw -> colormap = wa.colormap;    /* update attributes */
  126.     MatchWoolDescription(cw, &wl_client); /* get the descriptions */
  127.     UpdateClientWindowFields(cw, wl_client);
  128.     UpdateClientWindowGeometry(cw); /* sets bars,etc */
  129.     if (must_save_set && !(cw -> client_wob)) /* in case of GWM dying */
  130.         XChangeSaveSet(dpy, window, SetModeInsert);
  131.     ClientWindowRecordClient(cw);    /* it */
  132.     ClientWindowOpen(cw, being_mapped); /* create the windows */
  133.     zrt_gc(local_zrt_size);
  134.     SetTarget(oldTargetWob);
  135.     restore_wool_error_resume_point();
  136.     return cw;
  137.     }
  138. }
  139.  
  140. /*  The icon window is realized only on the first call to "iconify-window" or
  141.  * "window-icon".
  142.  * return icon or 0 if wool error
  143.  */
  144.  
  145. ClientWindow
  146. RealizeIconWindow(cw)
  147. ClientWindow    cw;
  148. {
  149.     WOOL_Client     wl_icon;
  150.     ClientWindow     icon;
  151.  
  152.     wl_icon = (WOOL_Client)
  153.     (cw -> icon_description -> type == WLClient ? cw -> icon_description :
  154.      (WOOL_OBJECT) wool_eval_and_catch_errors(cw -> icon_description));
  155.  
  156.     if (!wl_icon || wl_icon -> type != WLClient) {
  157.     ShowUndecoratedWindow(cw);
  158.     wool_print(wl_icon ? wl_icon : (WOOL_Client) NIL_STRING);
  159.     wool_newline();
  160.     wool_error("bad %s description!", "icon");
  161.     }
  162.     GWM_window_being_decorated = icon = NewIconWindow(cw);
  163.     SetTarget(icon);
  164.     icon -> cached_props = cw -> cached_props;
  165.     UpdateClientWindowFields(icon, wl_icon);
  166.     MakeIconWindow(cw);        /* makes central plug */
  167.     if(icon -> client) {
  168.         ClientWindowRecordClient(icon);
  169.     if (!icon -> client_wob)
  170.         XChangeSaveSet(dpy, icon->client, SetModeInsert);
  171.     }
  172.     UpdateClientWindowGeometry(icon);
  173.     decrease_reference(cw -> icon_description);
  174.     cw -> icon_description = NULL;
  175.     UpdateClientWindowIconSize(icon);
  176.     ClientWindowOpen(icon, 1);
  177.     return icon;    
  178. }
  179.  
  180. /* Creates a wob for that new client window.
  181.  */
  182.  
  183. ClientWindow
  184. NewClientWindow(parent, window)
  185. ClientWindow    parent;
  186. Window        window;
  187. {
  188.     ClientWindow    cw = (ClientWindow) NewWob(sizeof(struct _ClientWindow));
  189.  
  190.     cw -> parent = (Wob) parent;
  191.     cw -> screen = parent -> screen;
  192.     cw -> status = ClientWindowStatus;
  193.     cw -> client = window;
  194.     cw -> window = cw;
  195.     cw -> client_wob = LookUpWob(window);
  196.     cw -> type = ClientWindowClass;
  197.     return cw;
  198. }
  199.  
  200. ClientWindow
  201. NewIconWindow(cw)
  202. ClientWindow    cw;
  203. {
  204.     ClientWindow    icon =
  205.     (ClientWindow) NewWob(sizeof(struct _ClientWindow));
  206.  
  207.     cw -> icon = icon;
  208.     icon -> parent = cw -> parent;
  209.     icon -> screen = cw -> screen;
  210.     icon -> window = cw;
  211.     icon -> icon = icon;
  212.     icon -> status = IconStatus;
  213.     icon -> type = ClientWindowClass;
  214.     return icon;
  215. }
  216.  
  217. /*
  218.  * updates now the properties cached in the ClientWindow structure and icon
  219.  */
  220.  
  221. #define CWSTR(a) (((WOOL_String)(cw -> a)) -> string)
  222.  
  223. UpdateAllCachedProperties(cw)
  224. ClientWindow    cw;
  225. {
  226.     Window          window = cw -> client;
  227.     char           *machinename;
  228.     XClassHint      classhints;
  229.     Atom            actualtype;
  230.     int             actualformat;
  231.     unsigned long   nitems;
  232.     unsigned long   bytesafter;
  233.  
  234.     CWCachedProperties cprops = (CWCachedProperties)
  235.     Malloc(sizeof(struct _CWCachedProperties));
  236.  
  237.                      /* get all fixed properties */
  238.     bzero(cprops, sizeof(struct _CWCachedProperties));
  239.     cw -> cached_props = cprops;
  240.  
  241.     classhints.res_name = classhints.res_class = NULL;
  242.     if(XGetWindowProperty(dpy, window, XA_WM_CLIENT_MACHINE, 0,
  243.                MAX_TEMP_STRING_SIZE,
  244.                False, XA_STRING, &actualtype, &actualformat,
  245.                &nitems, &bytesafter, (unsigned char **) &machinename))
  246.     longjmp(wool_goes_here_on_error, 1);
  247.     if (machinename) {
  248.     char *p = machinename;
  249.     while(*p) {            /* truncates to first dot field */
  250.         if (*p == '.') {
  251.         *p = '\0';
  252.         break;
  253.         }
  254.         p++;
  255.     }
  256.     increase_reference(cprops -> machinename = (WOOL_OBJECT)
  257.                WLString_make(machinename));
  258.     XFree(machinename);
  259.     } else
  260.     increase_reference(cprops -> machinename = (WOOL_OBJECT)
  261.                DefaultMachineName);
  262.  
  263.     XGetClassHint(dpy, window, &classhints);
  264.     increase_reference(cprops -> clientclass = (classhints.res_class ?
  265.                (WOOL_OBJECT) WLString_make(classhints.res_class)
  266.                        : (WOOL_OBJECT) DefaultClientClass));
  267.     increase_reference(cprops -> clientname = (classhints.res_name ?
  268.                 (WOOL_OBJECT) WLString_make(classhints.res_name)
  269.                     : (WOOL_OBJECT) DefaultClientName));
  270.     if (classhints.res_name)
  271.     XFree(classhints.res_name);
  272.     if (classhints.res_class)
  273.     XFree(classhints.res_class);
  274.  
  275.                      /* update all variable props */
  276.     Update_XA_WM_NAME(cw);
  277.     Update_XA_WM_ICON_NAME(cw);
  278.     Update_XA_WM_HINTS(cw);
  279.     Update_XA_WM_NORMAL_HINTS(cw);
  280.     Update_XA_WM_TRANSIENT_FOR(cw);
  281.     Update_XA_WM_COLORMAP_WINDOWS(cw);
  282.     Update_XA_WM_PROTOCOLS(cw);
  283.  
  284.     GetPreviousWM_STATE(cw);        /* get the previous WM_STATE if any */
  285.  
  286.     UpdateClientWindowSize(cw);        /* check window real size */
  287. }
  288.  
  289. /*
  290.  * update ONE property
  291.  * cw MUST be a window, not an icon
  292.  */
  293.  
  294. UpdateCachedProperty(cw, property_atom)
  295. ClientWindow    cw;
  296. Atom        property_atom;
  297. {
  298.     switch (property_atom) {        /* predefined atoms */
  299.     case XA_WM_NAME:
  300.     Update_XA_WM_NAME(cw);
  301.     break;
  302.     case XA_WM_ICON_NAME:
  303.     Update_XA_WM_ICON_NAME(cw);
  304.     break;
  305.     case XA_WM_HINTS:
  306.     Update_XA_WM_HINTS(cw);
  307.     break;
  308.     case XA_WM_NORMAL_HINTS:
  309.     Update_XA_WM_NORMAL_HINTS(cw);
  310.     break;
  311.     case XA_WM_TRANSIENT_FOR:
  312.     Update_XA_WM_TRANSIENT_FOR(cw);
  313.     break;
  314.     default:                /* non-predefined props */
  315.     if (property_atom == XA_WM_COLORMAP_WINDOWS)
  316.         Update_XA_WM_COLORMAP_WINDOWS(cw);
  317.     else if (property_atom == XA_WM_PROTOCOLS)
  318.         Update_XA_WM_PROTOCOLS(cw);
  319.     }
  320. }
  321.  
  322. /* individual methods to update or create cached properties
  323.  */
  324.  
  325. #if defined(X11R1)||defined(X11R2)||defined(X11R3)||defined(X11R4)||defined(X11R5)
  326.  
  327. Update_XA_WM_NAME(cw)
  328. ClientWindow    cw;
  329. {
  330.     char           *name = 0;
  331.  
  332.     XFetchName(dpy, cw -> client, &(name));
  333.     decrease_reference(cw -> cached_props -> windowname);
  334.     if (!(name) || (*(name) == '\0'))
  335.     increase_reference(cw -> cached_props -> windowname = (WOOL_OBJECT)
  336.                DefaultWindowName);
  337.     else {
  338.     increase_reference(cw -> cached_props -> windowname = (WOOL_OBJECT)
  339.                WLString_make(name));
  340.     XFree(name);
  341.     }
  342. }
  343.  
  344. Update_XA_WM_ICON_NAME(cw)
  345. ClientWindow    cw;
  346. {
  347.     char           *name = 0;
  348.  
  349.     XGetIconName(dpy, cw -> client, &name);
  350.     if (cw -> cached_props -> iconname) {
  351.     decrease_reference(cw -> cached_props -> iconname);
  352.     }
  353.     if (!(name) || (*(name) == '\0')) {
  354.     increase_reference(cw -> cached_props -> iconname = (WOOL_OBJECT)
  355.                DefaultIconName);
  356.     } else {
  357.     increase_reference(cw -> cached_props -> iconname = (WOOL_OBJECT)
  358.                WLString_make(name));
  359.     XFree(name);
  360.     }
  361. }
  362.  
  363. #else /* X11R6 or later */
  364.  
  365. Update_XA_WM_NAME(cw)
  366. ClientWindow    cw;
  367. {
  368.     char           *name = 0;
  369.     XTextProperty  text_prop;
  370.     char       **list_return = 0;
  371.     int                   count_return;
  372.  
  373.     if (! XGetWMName(dpy, cw -> client, &text_prop));
  374.     else {
  375.     /* incantation from twm/add_window.c */
  376.     if (text_prop.value) text_prop.nitems = 
  377.                  strlen((char *)text_prop.value);
  378.     if ( XmbTextPropertyToTextList(
  379.         dpy,
  380.         &text_prop,
  381.         &list_return,
  382.         &count_return) < Success);
  383.     else {
  384.         if (!list_return || !(*list_return));
  385.         else name = *list_return;
  386.     } 
  387.     }    
  388.     
  389.     decrease_reference(cw -> cached_props -> windowname);
  390.     if (!(name) || (*(name) == '\0'))
  391.     increase_reference(cw -> cached_props -> windowname = (WOOL_OBJECT)
  392.                DefaultWindowName);
  393.     else {
  394.     increase_reference(cw -> cached_props -> windowname = (WOOL_OBJECT)
  395.                WLString_make(name));
  396.     }
  397.     if (list_return) XFreeStringList(list_return);
  398. }
  399.  
  400. Update_XA_WM_ICON_NAME(cw)
  401. ClientWindow    cw;
  402. {
  403.     char           *name = 0;
  404.     XTextProperty  text_prop;
  405.     char       **list_return = 0;
  406.     int                   count_return;
  407.  
  408.     if (! XGetWMIconName(dpy, cw -> client, &text_prop));
  409.     else {
  410.     /* incantation from twm/add_window.c */
  411.     if (text_prop.value) text_prop.nitems = 
  412.                  strlen((char *)text_prop.value);
  413.     if ( XmbTextPropertyToTextList(
  414.         dpy,
  415.         &text_prop,
  416.         &list_return,
  417.         &count_return) < Success);
  418.     else {
  419.         if (!list_return || !(*list_return));
  420.         else name = *list_return;
  421.     } 
  422.     }    
  423.  
  424.     if (cw -> cached_props -> iconname) {
  425.     decrease_reference(cw -> cached_props -> iconname);
  426.     }
  427.     if (!(name) || (*(name) == '\0')) {
  428.     increase_reference(cw -> cached_props -> iconname = (WOOL_OBJECT)
  429.                DefaultIconName);
  430.     } else {
  431.     increase_reference(cw -> cached_props -> iconname = (WOOL_OBJECT)
  432.                WLString_make(name));
  433.     }
  434.     if (list_return) XFreeStringList(list_return);
  435. }
  436.  
  437. #endif /* X11R6 or later */
  438.  
  439. Update_XA_WM_HINTS(cw)
  440. ClientWindow    cw;
  441. {
  442.     XWMHints       *windowhints, *wm_hints;
  443.     ClientWindow    group_leader;
  444.  
  445.     if (windowhints = XGetWMHints(dpy, cw -> client)) {
  446.     if (GWM_backup_old_property)
  447.         bcopy(&(cw -> cached_props -> wm_hints),
  448.               &GWM_backup_of_old_property, sizeof(XWMHints));
  449.     bcopy(windowhints, wm_hints = &(cw -> cached_props -> wm_hints),
  450.           sizeof(XWMHints));
  451.  
  452.     /* window groups */
  453.     if ((windowhints -> flags & WindowGroupHint)
  454.         && windowhints -> window_group
  455.         && (cw -> status & ClientWindowStatus)) {
  456.         if (windowhints -> window_group == cw->client)
  457.         AddWindowToGroupLeader(cw, cw);
  458.         else if (group_leader =
  459.              DecoratedWindow(windowhints -> window_group)) {
  460.         if (group_leader -> status & ClientWindowStatus)
  461.             AddWindowToGroupLeader(cw, group_leader);
  462.         }
  463.     }
  464.  
  465.     /* check validity of hints */
  466.     if (wm_hints->flags & IconWindowHint && !(wm_hints->icon_window))
  467.         wm_hints->flags &= ~IconWindowHint;
  468.     if (wm_hints->flags & IconPixmapHint && !(wm_hints->icon_pixmap))
  469.         wm_hints->flags &= ~IconPixmapHint;
  470.     if (wm_hints->flags & IconMaskHint && !(wm_hints->icon_mask))
  471.         wm_hints->flags &= ~IconMaskHint;
  472.  
  473.     XFree(windowhints);
  474.     }
  475. }
  476.  
  477. Update_XA_WM_NORMAL_HINTS(cw)
  478. ClientWindow    cw;
  479. {
  480.     long supplied;
  481.  
  482. #ifdef NOBASEDIMS
  483.     supplied = 0;
  484.     if (!XGetNormalHints(dpy, cw -> client,
  485.              &(cw -> cached_props -> normal_hints))) {
  486.     cw -> cached_props -> normal_hints.flags = 0;
  487.     }
  488. #else /* NOBASEDIMS */
  489.     if (!XGetWMNormalHints(dpy, cw -> client,
  490.              &(cw -> cached_props -> normal_hints),
  491.                &supplied)) {
  492.     cw -> cached_props -> normal_hints.flags = 0;
  493.     }
  494.     if (supplied & PBaseSize) {
  495.     supplied = 1;
  496.     } else {
  497.     supplied = 0;
  498.     }
  499. #endif /* NOBASEDIMS */
  500.     cw -> cached_props -> new_normal_hints = supplied;
  501.     CheckConsistency(&(cw -> cached_props -> normal_hints));
  502. }
  503.  
  504. Update_XA_WM_TRANSIENT_FOR(cw)
  505. ClientWindow    cw;
  506. {
  507.     ClientWindow    main_cw;
  508.     Window transient_for;
  509.  
  510.     decrease_reference(cw -> cached_props -> transient_for);
  511.     XSync(dpy, 0);
  512.     XSetErrorHandler(NoXError);
  513.     ErrorStatus = 0;
  514.     XGetTransientForHint(dpy, cw -> client, &transient_for);
  515.     XSync(dpy, 0);
  516.     XSetErrorHandler(XError);
  517.     if (ErrorStatus)
  518.     longjmp(wool_goes_here_on_error, 1); /* problem appeared */
  519.  
  520.     if (transient_for) {
  521.      if (transient_for != Context -> root
  522.         && transient_for != cw -> client
  523.             && (main_cw = DecoratedWindow(transient_for))) {
  524.         increase_reference(cw -> cached_props -> transient_for =
  525.                    (WOOL_OBJECT) WLNumber_make(main_cw));
  526.     } else {
  527.         cw -> cached_props -> transient_for = 0;
  528.     }
  529.     } else {
  530.     cw -> cached_props -> transient_for = 0;
  531.     }
  532. }
  533.  
  534. Update_XA_WM_COLORMAP_WINDOWS(cw)
  535. ClientWindow    cw;
  536. {
  537.     Atom            actualtype;
  538.     int             actualformat;
  539.     unsigned long   nitems;
  540.     unsigned long   bytesafter;
  541.     Window       *colormap_windows = NULL, *old_colormap_windows;
  542.     int            result, i;
  543.  
  544.     result = GwmSilentXGetWindowProperty(dpy, cw -> client,
  545.             XA_WM_COLORMAP_WINDOWS, 0, WM_COLORMAP_WINDOWS_PROP_Length,
  546.             False, XA_WM_COLORMAP_WINDOWS, &actualtype,
  547.         &actualformat, &nitems, &bytesafter, &colormap_windows);
  548.  
  549.     if(result == Success && nitems &&
  550.        actualtype != None && actualformat == 32){
  551.     old_colormap_windows = cw -> cached_props -> colormap_windows;
  552.     cw -> cached_props -> colormap_windows =
  553.         (Window *) Malloc ((nitems+1) * sizeof (Window));
  554.     cw -> cached_props -> colormap_windows_size = 1;
  555.     cw -> cached_props -> colormap_windows[0] = cw -> client;
  556.     for(i = 0; i< nitems; i++)
  557.         if(colormap_windows[i] != cw -> client
  558.            && !LookUpClient(colormap_windows[i])) {
  559.             cw -> cached_props -> colormap_windows[
  560.                    cw -> cached_props -> colormap_windows_size++] =
  561.             colormap_windows[i];
  562.         if (colormap_windows[i] != cw -> client) {
  563.             XSelectInput(dpy, colormap_windows[i], ColormapChangeMask);
  564.         }
  565.            }
  566.     if(cw -> cached_props -> colormap_windows_size == 1){
  567.         Free(cw -> cached_props -> colormap_windows);
  568.         cw -> cached_props -> colormap_windows_size = 0;
  569.     } else {
  570.         if (Context -> InstalledColormapCW == cw)
  571.         XInstallColormap(dpy,
  572.                  cw -> cached_props -> colormap_windows[0]);
  573.     }
  574.     cw -> cached_props -> colormap_windows_index = 0;
  575.     if(old_colormap_windows)
  576.         Free(old_colormap_windows);
  577.     }
  578.  
  579.     if(colormap_windows && result == Success)
  580.         XFree(colormap_windows);
  581. }
  582.  
  583. Update_XA_WM_PROTOCOLS(cw)
  584. ClientWindow    cw;
  585. {
  586.     Atom            actualtype;
  587.     int             actualformat;
  588.     unsigned long   nitems;
  589.     unsigned long   bytesafter;
  590.     Window         *protocols = NULL;
  591.     int             result, i;
  592.  
  593.     result = GwmSilentXGetWindowProperty(dpy, cw -> client,
  594.                 XA_WM_PROTOCOLS, 0, WM_PROTOCOLS_PROP_Length,
  595.                 False, XA_ATOM, &actualtype,
  596.                &actualformat, &nitems, &bytesafter, &protocols);
  597.  
  598.     if (result == Success && nitems &&
  599.     actualtype != None && actualformat == 32) {
  600.     cw -> cached_props -> wm_take_focus = 0;
  601.     cw -> cached_props -> wm_save_yourself = 0;
  602.     cw -> cached_props -> wm_delete_window = 0;
  603.     for (i = 0; i < nitems; i++) {
  604.         if ((protocols[i] == XA_WM_TAKE_FOCUS)
  605.         && !(cw -> ignore_take_focus))
  606.         cw -> cached_props -> wm_take_focus = 1;
  607.         else if (protocols[i] == XA_WM_SAVE_YOURSELF)
  608.         cw -> cached_props -> wm_save_yourself = 1;
  609.         else if (protocols[i] == XA_WM_DELETE_WINDOW)
  610.         cw -> cached_props -> wm_delete_window = 1;
  611.     }
  612.     }
  613.     if (protocols && result == Success)
  614.     XFree(protocols);
  615. }
  616.  
  617. /*
  618.  * release their storage
  619.  */
  620.  
  621. FreeCachedProperties(cprops)
  622. CWCachedProperties cprops;
  623. {
  624.     int local_zrt_size = zrt_size;
  625.     decrease_reference(cprops -> machinename);
  626.     decrease_reference(cprops -> clientclass);
  627.     decrease_reference(cprops -> clientname);
  628.     decrease_reference(cprops -> windowname);
  629.     decrease_reference(cprops -> iconname);
  630.     decrease_reference(cprops -> transient_for);
  631.     DelayedFree(cprops);
  632.     zrt_gc(local_zrt_size);
  633. }
  634.  
  635. void
  636. Set_XA_WM_STATE(cw, state)
  637. ClientWindow    cw;
  638. int             state;
  639. {
  640.     struct _WM_STATE_PROP wm_state;
  641.     int             trap_x_errors = 0;
  642.  
  643.     if (state == -1) {
  644.       if (cw -> mapped)
  645.         wm_state.state = WM_STATE_Normal;
  646.       else if ((cw -> icon && cw -> icon -> mapped)
  647.                || (cw -> cached_props -> user_icon &&
  648.                    cw -> cached_props -> user_icon -> mapped))
  649.         wm_state.state = WM_STATE_Iconified;
  650.       else {
  651.         wm_state.state = WM_STATE_Withdrawn;
  652.         trap_x_errors = 1;
  653.       }
  654.     }
  655.     else {
  656.       wm_state.state = state;
  657.       if (state == WM_STATE_Withdrawn)
  658.         trap_x_errors = 1;
  659.     }
  660.         
  661.     if (wm_state.state != cw -> cached_props -> wm_state) {
  662.       cw -> cached_props -> wm_state = wm_state.state;
  663.       wm_state.icon = (cw -> icon ?
  664.                        cw -> icon -> hook :
  665.                        (cw -> cached_props -> user_icon ?
  666.                         cw -> cached_props -> user_icon -> hook : 0));
  667.       if (trap_x_errors)
  668.         XSetErrorHandler(NoXError);
  669.       XChangeProperty(dpy, cw -> client, XA_WM_STATE, XA_WM_STATE,
  670.               32, PropModeReplace, (unsigned char *)&wm_state, WM_STATE_PROP_Length);
  671.       if (trap_x_errors) {
  672.         XSync(dpy, 0);
  673.         XSetErrorHandler(XError);
  674.       }
  675.     }
  676. }
  677.  
  678. /* Updating WM_STATE is setting it on the window
  679.  * returns state
  680.  */
  681.  
  682. int
  683. Update_XA_WM_STATE(cw)
  684. ClientWindow    cw;
  685. {
  686.     cw = cw -> window;
  687.     if (!(cw -> client_wob || cw -> cached_props -> user_icon)) {
  688.     Set_XA_WM_STATE(cw, -1);
  689.     return cw -> cached_props -> wm_state;
  690.     } else
  691.     return WM_STATE_Normal;
  692. }
  693.     
  694. /* first time a window is mapped, decode the WM_STATE from previous wm
  695.  */
  696.  
  697. GetPreviousWM_STATE(cw)
  698. ClientWindow    cw;
  699. {
  700.     Atom            actualtype;
  701.     int             actualformat;
  702.     unsigned long   nitems;
  703.     unsigned long   bytesafter;
  704.     WM_STATE_PROP   wm_state;
  705.  
  706.     if (GWM_ProcessingExistingWindows
  707.     &&
  708.     Success == XGetWindowProperty(dpy, cw -> client, XA_WM_STATE, 0,
  709.                       WM_STATE_PROP_Length, False,
  710.                       XA_WM_STATE, &actualtype,
  711.                       &actualformat, &nitems, &bytesafter,
  712.                       (unsigned char **)&wm_state)
  713.     && nitems && wm_state) {
  714.     cw -> cached_props -> wm_hints.flags |= StateHint;
  715.     cw -> cached_props -> wm_hints.initial_state = wm_state -> state;
  716.     XFree(wm_state);
  717.     }
  718. }
  719.  
  720. /*
  721.  * copies information from descriptor to client
  722.  */
  723.  
  724. UpdateClientWindowBar(parent, field, wl_bar, dir)
  725. ClientWindow    parent;
  726. Bar            *field;
  727. WOOL_Bar    wl_bar;
  728. int        dir;
  729. {
  730.     wl_bar = (WOOL_Bar) wool_type_or_evaluate(wl_bar, WLBar);
  731.     if (wl_bar == (WOOL_Bar) NIL)
  732.     *field = NULL;
  733.     else {
  734.     *field = NewBar(parent, wl_bar, dir);
  735.     }
  736. }
  737.  
  738. UpdateClientWindowFields(cw, wl_client)
  739. ClientWindow    cw;
  740. WOOL_Client     wl_client;
  741. {
  742.     cw -> inner_borderwidth = wl_client -> inner_borderwidth;
  743.     cw -> box.borderwidth = wl_client -> borderwidth;
  744.     cw -> box.borderpixel = wl_client -> borderpixel;
  745.     cw -> box.background = wl_client -> background;
  746.     UpdateClientWindowBar(cw, &(cw -> titlebar), wl_client -> titlebar,
  747.               HORIZONTAL);
  748.     UpdateClientWindowBar(cw, &(cw -> leftbar), wl_client -> leftbar,
  749.               VERTICAL);
  750.     UpdateClientWindowBar(cw, &(cw -> rightbar), wl_client -> rightbar,
  751.               VERTICAL);
  752.     UpdateClientWindowBar(cw, &(cw -> basebar), wl_client -> basebar,
  753.               HORIZONTAL);
  754.     increase_reference(cw -> cursor =
  755.                wool_type_or_evaluate(wl_client -> cursor, WLCursor));
  756.     increase_reference(cw -> bordertile =
  757.           wool_type_or_evaluate(wl_client -> bordertile, WLPixmap));
  758.     increase_reference(cw -> fsm =
  759.                wool_type_or_evaluate(wl_client -> fsm, WLFsm));
  760.     increase_reference(cw -> menu =
  761.                wool_type_or_evaluate(wl_client -> menu, WLMenu));
  762.     increase_reference(cw -> property = (WOOL_OBJECT) wl_client -> property);
  763.     increase_reference(cw -> opening = (WOOL_OBJECT) wl_client -> opening);
  764.     increase_reference(cw -> closing = (WOOL_OBJECT) wl_client -> closing);
  765.     increase_reference(cw -> grabs = (WOOL_OBJECT) wl_client -> grabs);
  766.     increase_reference(cw -> icon_plug =
  767.                (WOOL_OBJECT) wl_client -> icon_plug);
  768.     cw -> map_on_raise = wl_client -> map_on_raise;
  769.     cw -> ignore_take_focus = wl_client -> map_on_raise;
  770. }
  771.  
  772. /*
  773.  * here we create or get the XWindow to put in the icon -> client field
  774.  */
  775.  
  776. MakeIconWindow(cw)
  777. ClientWindow cw;
  778. {
  779.     WOOL_Plug       wl_plug = (WOOL_Plug) cw -> icon -> icon_plug;
  780.     Plug            plug;
  781.  
  782.     wl_plug = (WOOL_Plug) WOOL_send(WOOL_eval, wl_plug, (wl_plug));
  783.     if (wl_plug -> type == WLNumber) {    /* icon window managed by client */
  784.     cw -> icon -> client = (Window)
  785.         ((WOOL_Number) wl_plug) -> number;
  786.     } else if (wl_plug -> type == WLPlug) {    /* icon field is plug */
  787.     plug = (Plug) NewPlug(Context->rootWob, wl_plug);
  788.     UpdatePlugGeometry(plug);
  789.     PlugOpen(plug);
  790.     cw -> icon -> client = plug -> hook;
  791.     cw -> icon -> client_wob = (Wob) plug;
  792.     }
  793. }
  794.  
  795. /*
  796.  * we set here the size of the cw before calling MatchWool, for dims queries
  797.  */
  798.  
  799. UpdateClientWindowSize(cw)
  800. ClientWindow    cw;
  801. {
  802.     Window          root;
  803.     unsigned int    depth, width, height;
  804.     int             must_resize = 0;
  805.  
  806.     if (!XGetGeometry(dpy, cw -> client, &root,
  807.          &(cw -> box.x), &(cw -> box.y),
  808.          &(cw -> box.width), &(cw -> box.height),
  809.          &(cw -> box.borderwidth), &depth))
  810.     longjmp(wool_goes_here_on_error, 1);
  811.     /* update cw fields */
  812.     cw -> inner_width = cw -> box.width;
  813.     cw -> inner_height = cw -> box.height;
  814.     cw -> old_inner_borderwidth = cw -> inner_borderwidth
  815.     = cw -> box.borderwidth;
  816.     
  817.     /* update the size according to hints */
  818.     if (!GWM_ProcessingExistingWindows) {
  819.     if(!cw -> cached_props -> new_normal_hints) {
  820.         if (cw -> cached_props -> normal_hints.flags & USSize) {
  821.         if (cw -> inner_width != cw -> cached_props ->
  822.             normal_hints.width) {
  823.             must_resize = 1;
  824.             cw -> inner_width = cw -> cached_props ->
  825.             normal_hints.width;
  826.         }
  827.         if (cw -> inner_height != cw -> cached_props ->
  828.             normal_hints.height) {
  829.             must_resize = 1;
  830.             cw -> inner_height = cw -> cached_props ->
  831.             normal_hints.height;
  832.         }
  833.         } else if (cw -> cached_props -> normal_hints.flags & PSize) {
  834.         if (cw -> inner_width != cw -> cached_props ->
  835.             normal_hints.width && cw -> inner_width > 1) {
  836.             must_resize = 1;
  837.             cw -> inner_width = cw -> cached_props ->
  838.             normal_hints.width;
  839.         }
  840.         if (cw -> inner_height != cw -> cached_props ->
  841.             normal_hints.height && cw -> inner_height > 1) {
  842.             must_resize = 1;
  843.             cw -> inner_height = cw -> cached_props ->
  844.             normal_hints.height;
  845.         }
  846.         } 
  847.     } else {
  848.         width = cw -> inner_width;
  849.         height = cw -> inner_height;
  850.         conform_to_hints(&(cw -> cached_props -> normal_hints),
  851.                  &width, &height);
  852.         if ((cw -> inner_width != width) ||
  853.         (cw -> inner_height != height)) {
  854.         must_resize = 1;
  855.         cw -> inner_width = width;
  856.         cw -> inner_height = height;
  857.         }
  858.     }
  859.     }
  860.     if (must_resize)
  861.     XResizeWindow(dpy, cw -> client,
  862.               cw -> inner_width, cw -> inner_height);
  863. }
  864.  
  865. /* before opening an icon, place it according to hints
  866.  */
  867.  
  868. UpdateClientWindowIconSize(icon)
  869. ClientWindow icon;
  870. {
  871.     if (icon -> cached_props -> wm_hints.flags & IconPositionHint) {
  872.     icon -> box.x = icon -> cached_props -> wm_hints.icon_x;
  873.     icon -> box.y = icon -> cached_props -> wm_hints.icon_y;
  874.     }
  875. }
  876.  
  877. /*
  878.  * Here we add physically all the gadgets around a client window.
  879.  * A new window is opened. (First Map Request, called from SetUpClient.)
  880.  * The description of the window to be created is in setup.
  881.  *     Create the surrounding window.
  882.  *     Set up window geometry, bars, plugs if any,
  883.  *     reparent the client window.
  884.  */
  885.  
  886. ClientWindowOpen(cw, being_mapped)
  887. ClientWindow    cw;
  888. int        being_mapped;
  889. {
  890.     check_window_size(cw);
  891.     /* create the WOB windows, and map them */
  892.     cw -> curstate = (int) WOOL_send(WOOL_open, cw -> fsm, (cw -> fsm));
  893.     ObeyWinGravityHint(cw, 1);    /* sets reparenting offsets */
  894.     {
  895.       XSetWindowAttributes xsw;
  896.       xsw.background_pixmap = None;
  897.       xsw.border_pixel = cw->box.borderpixel;
  898.       xsw.backing_store = NotUseful;
  899.       xsw.save_under = NotUseful;
  900.             
  901.       cw -> hook =
  902.     XCreateWindow(dpy, Context -> root, cw -> box.x, cw -> box.y,
  903.               cw -> box.width, cw -> box.height,
  904.               cw -> box.borderwidth, CopyFromParent,
  905.               CopyFromParent, CopyFromParent,
  906.               CWBackPixmap | CWBorderPixel | CWBackingStore |
  907.               CWSaveUnder, &xsw);
  908.     }
  909.     cw -> status |= TopLevelXWindowStatus;
  910.     WobRecordHook(cw);
  911.     BarOpen(cw -> titlebar);
  912.     BarOpen(cw -> leftbar);
  913.     BarOpen(cw -> rightbar);
  914.     BarOpen(cw -> basebar);
  915.  
  916.     if (cw -> cursor != NIL)
  917.     XDefineCursor(dpy, cw -> hook,
  918.               ((WOOL_Cursor) cw -> cursor) -> cursor);
  919.     if (cw -> bordertile != NIL)
  920.     XSetWindowBorderPixmap(dpy, cw -> hook,
  921.                    ((WOOL_Pixmap) cw -> bordertile) -> pixmap);
  922.  
  923.     /* put window in window list */
  924.     Context -> WindowCount++;
  925.     if (Context -> rootWob -> next)
  926.     Context -> rootWob -> next -> previous = cw;
  927.     cw -> next = Context -> rootWob -> next;
  928.     Context -> rootWob -> next = cw;
  929.     cw -> previous = Context -> rootWob;
  930.  
  931. #ifdef SHAPE
  932.     /* if we decorate a shaped window, reshape ourselves */
  933.     if (WindowIsShaped(cw))
  934.         ClientWindowSetShape(cw);
  935. #endif /* SHAPE */
  936.  
  937.     if (cw -> client) {            /* Replace client Window */
  938.     unsigned int client_height, client_width, client_borderwidth;
  939.     int dummy;
  940.  
  941.     XUnmapWindow(dpy, cw -> client);
  942.     XSetWindowBorderWidth(dpy, cw -> client, cw -> inner_borderwidth);
  943.     if (cw -> client_wob) {
  944.         cw -> client_wob -> parent = (Wob) cw;
  945.         cw -> client_wob -> status &= ~TopLevelXWindowStatus;
  946.         cw -> client_wob -> input_mask |= ClientClientMask;
  947.         XSelectInput(dpy, cw -> client, cw -> client_wob -> input_mask);
  948.     } else {
  949.         XSelectInput(dpy, cw -> client, ClientClientMask);
  950.     }
  951.     
  952.     if (TrapXErrors(XReparentWindow(dpy, cw -> client, cw -> hook,
  953.             cw -> inner_x, cw -> inner_y))) {
  954.         cw -> client = 0;
  955.         ClientWindowClose(cw);
  956.         SetTarget(Context->rootWob);
  957.         return;
  958.     }
  959.  
  960.     /* check if window hasn't been resized since deco */
  961.     if (!XGetGeometry(dpy, cw -> client,
  962.              (Window *)&dummy, &dummy, &dummy, &client_width, 
  963.              &client_height, &client_borderwidth, (unsigned int *)&dummy))
  964.         longjmp(wool_goes_here_on_error, 1);
  965.     if (client_height != cw -> inner_height
  966.         || client_width != cw -> inner_width
  967.         || client_borderwidth != cw -> inner_borderwidth)
  968.         ReconfigureClientWindow(cw, cw -> client);
  969.         else
  970.             SendSyntheticMoveEvent(cw);
  971.     }
  972.     XSelectInput(dpy, cw -> hook, ClientMask |
  973.          ((WOOL_Fsm) cw -> fsm) -> mask);
  974.     /* set global grabs */
  975.     WLClient_set_grabs(cw -> grabs, cw -> hook);
  976.  
  977.     XSync(dpy, 0);
  978.     if (!GWM_window_being_decorated) {    /* error while decorating? abort! */
  979.     SetTarget(Context->rootWob);
  980.     return;
  981.     }
  982.     
  983.     GWM_window_being_decorated = 0;
  984.  
  985.     /* process pending events */
  986.     if (!GWM_ProcessingExistingWindows && GWM_reenter_on_opens)
  987.     GWM_ProcessEvents(0);
  988.  
  989.     /* execute "opening" WOOL code */
  990.     if (being_mapped && WobIsValid(cw)) {
  991.     ClientWindowExecuteOpening(cw);
  992.     }
  993. }
  994.  
  995. ClientWindowExecuteOpening(cw)
  996.     ClientWindow cw;
  997. {
  998.     int             local_zrt_size = zrt_size;
  999.     if (cw -> opening) {
  1000.         SetTarget(cw);
  1001.         GWM_Window_being_opened = cw;
  1002.         wool_eval_and_catch_errors_proc(cw -> opening);
  1003.         GWM_Window_being_opened = 0;
  1004.         decrease_reference(cw -> opening);
  1005.         cw -> opening = NULL;
  1006.     }
  1007.     SetTarget(cw);
  1008.     zrt_gc(local_zrt_size);
  1009. }
  1010.  
  1011. /*
  1012.  * Take a client window, recursivly set geometry by the sons, and then
  1013.  * set the bars geometry
  1014.  */
  1015.  
  1016. UpdateClientWindowGeometry(cw)
  1017. ClientWindow    cw;
  1018. {
  1019.     UpdateBarWidth(cw -> titlebar);
  1020.     UpdateBarWidth(cw -> leftbar);
  1021.     UpdateBarWidth(cw -> rightbar);
  1022.     UpdateBarWidth(cw -> basebar);
  1023.  
  1024.     ClientWindowComputeGeometry(cw);
  1025.     ClientWindowComputeBarDims(cw);
  1026.  
  1027.     UpdateBarLength(cw -> titlebar);
  1028.     UpdateBarLength(cw -> leftbar);
  1029.     UpdateBarLength(cw -> rightbar);
  1030.     UpdateBarLength(cw -> basebar);
  1031. }
  1032.  
  1033. ClientWindowComputeGeometry(cw)
  1034. ClientWindow cw;
  1035. {
  1036.     Window          root;
  1037.     int             client_x, client_y;
  1038.     unsigned int    client_width, client_height;
  1039.     unsigned int    client_borderwidth, client_depth;
  1040.  
  1041.     if (cw -> client) {
  1042.     if (!XGetGeometry(dpy, cw -> client,
  1043.              &root, &client_x, &client_y, &client_width, &client_height,
  1044.              &client_borderwidth, &client_depth))
  1045.         longjmp(wool_goes_here_on_error, 1);
  1046. #ifdef SHAPE
  1047.     /* if we decorate a shaped window, do not touch borderwidth */
  1048.     
  1049.     if (GWM_ShapeExtension) {
  1050.         int xws, yws, xbs, ybs;
  1051.         unsigned int wws, hws, wbs, hbs;
  1052.         int boundingShaped, clipShaped;
  1053.         
  1054.         XShapeSelectInput (dpy, cw -> client, True);
  1055.         if (XShapeQueryExtents (dpy, cw -> client,
  1056.                      &boundingShaped, &xws, &yws, &wws, &hws,
  1057.                      &clipShaped, &xbs, &ybs, &wbs, &hbs)
  1058.         &&boundingShaped) {
  1059.         cw -> client_shaped = 1;
  1060.         cw -> inner_borderwidth = 0;
  1061.         }
  1062.     }
  1063. #endif                    /* SHAPE */
  1064.     cw -> old_inner_borderwidth = client_borderwidth;
  1065.     if (cw -> inner_borderwidth == ((short) ANY))
  1066.         cw -> inner_borderwidth = client_borderwidth;
  1067.     else
  1068.         client_borderwidth = cw -> inner_borderwidth;
  1069.     cw -> inner_width = client_width;
  1070.     cw -> inner_height = client_height;
  1071.     } else {
  1072.     NaturalBarLength(cw -> titlebar);
  1073.     NaturalBarLength(cw -> leftbar);
  1074.     NaturalBarLength(cw -> rightbar);
  1075.     NaturalBarLength(cw -> basebar);
  1076.     cw -> inner_borderwidth = 0;
  1077.     if (cw -> leftbar || cw -> rightbar) {
  1078.         cw -> inner_width = 0;
  1079.         cw -> inner_height =
  1080.         Max((cw -> leftbar ? cw -> leftbar -> box.height : 0),
  1081.             (cw -> rightbar ? cw -> rightbar -> box.height : 0));
  1082.     } else {
  1083.         cw -> inner_height = 0;
  1084.         cw -> inner_width =
  1085.         Max((cw -> titlebar ? cw -> titlebar -> box.width : 0),
  1086.             (cw -> basebar ? cw -> basebar -> box.width : 0));
  1087.     }
  1088.     }
  1089. }
  1090.  
  1091. ClientWindowComputeBarDims(cw)
  1092. ClientWindow cw;
  1093. {
  1094.     int             titleheight, baseheight, leftwidth, rightwidth;
  1095.  
  1096.     cw -> box.width = cw -> inner_width + 2 * cw -> inner_borderwidth;
  1097.     cw -> box.height = cw -> inner_height + 2 * cw -> inner_borderwidth;
  1098.  
  1099.     /* Special hack */
  1100.     if ((cw -> leftbar && cw -> leftbar -> ewidth) ||
  1101.         (cw -> rightbar && cw -> rightbar -> ewidth)) {
  1102.       int len;
  1103.       UpdateBarWidth(cw -> leftbar);
  1104.       UpdateBarWidth(cw -> rightbar);
  1105.       len = Max(NaturalBarLength(cw -> titlebar),
  1106.                 NaturalBarLength(cw -> basebar));
  1107.       len = len - cw -> inner_width -
  1108.         (cw -> leftbar ? cw -> leftbar -> box.width
  1109.          + 2 * cw -> leftbar -> box.borderwidth : 0) -
  1110.            (cw -> rightbar ? cw -> rightbar -> box.width
  1111.             + 2 * cw -> rightbar -> box.borderwidth : 0);
  1112.       if (len < 0) len = 0;
  1113.       if (!cw -> leftbar || !cw -> leftbar -> ewidth)
  1114.         cw -> rightbar -> box.width += len;
  1115.       else if (!cw -> rightbar || !cw -> rightbar -> ewidth)
  1116.         cw -> leftbar -> box.width += len;
  1117.       else {
  1118.         int llen = len / 2, rlen = len - llen;
  1119.         cw -> leftbar -> box.width += llen;
  1120.         cw -> rightbar -> box.width += rlen;
  1121.       }
  1122.     }
  1123.  
  1124.     titleheight = (cw -> titlebar ? cw -> titlebar -> box.height
  1125.     + 2 * cw -> titlebar -> box.borderwidth : 0);
  1126.     baseheight = (cw -> basebar ? cw -> basebar -> box.height
  1127.     + 2 * cw -> basebar -> box.borderwidth : 0);
  1128.     leftwidth = (cw -> leftbar ? cw -> leftbar -> box.width
  1129.     + 2 * cw -> leftbar -> box.borderwidth : 0);
  1130.     rightwidth = (cw -> rightbar ? cw -> rightbar -> box.width
  1131.     + 2 * cw -> rightbar -> box.borderwidth : 0);
  1132.  
  1133.     /* sets the dimensions of the box itself */
  1134.     cw -> inner_x = leftwidth;
  1135.     cw -> inner_y = titleheight;
  1136.     cw -> box.width += leftwidth + rightwidth;
  1137.     cw -> box.height += titleheight + baseheight;
  1138.  
  1139.     /* set the titlebar (height and borderwidth are already set) */
  1140.     if(cw -> titlebar) {
  1141.     cw -> titlebar -> box.x = 0;
  1142.     cw -> titlebar -> box.y = 0;
  1143.     cw -> titlebar -> box.width =
  1144.     cw -> box.width - 2 * cw -> titlebar -> box.borderwidth;
  1145.     }
  1146.     /* set the leftbar (width and borderwidth are already set) */
  1147.     if(cw -> leftbar) {
  1148.     cw -> leftbar -> box.x = 0;
  1149.     cw -> leftbar -> box.y = titleheight;
  1150.     cw -> leftbar -> box.height = cw -> box.height
  1151.     - titleheight - baseheight
  1152.     - 2 * cw -> leftbar -> box.borderwidth;
  1153.     }
  1154.     /* set the rightbar (width and borderwidth are already set) */
  1155.     if(cw -> rightbar) {
  1156.     cw -> rightbar -> box.x = cw -> box.width
  1157.     - 2 * cw -> rightbar -> box.borderwidth
  1158.     - cw -> rightbar -> box.width;
  1159.     cw -> rightbar -> box.y = titleheight;
  1160.     cw -> rightbar -> box.height = cw -> box.height
  1161.     - titleheight - baseheight
  1162.     - 2 * cw -> rightbar -> box.borderwidth;
  1163.     }
  1164.     /* set the basebar (height and borderwidth are already set) */
  1165.     if(cw -> basebar) {
  1166.     cw -> basebar -> box.x = 0;
  1167.     cw -> basebar -> box.y = cw -> box.height - baseheight;
  1168.     cw -> basebar -> box.width =
  1169.     cw -> box.width - 2 * cw -> basebar -> box.borderwidth;
  1170.     }
  1171. }
  1172.  
  1173. /* destroys all data concerning the window
  1174.  * suppose that the client window is already destroyed, so we do not need to
  1175.  * destroy it ourselves
  1176.  */
  1177.  
  1178. ClientWindowClose(cw)
  1179. ClientWindow    cw;
  1180. {
  1181.     int             closeflag;
  1182.     ClientWindow    icon = cw -> icon;
  1183.     CWCachedProperties cprops = cw -> cached_props;
  1184.  
  1185.     if (cprops -> client_group)
  1186.     RemoveWindowFromGroup(cw);
  1187.     closeflag = ClientWindowClose_aux(cw -> window);
  1188.     if (icon)
  1189.     ClientWindowClose_aux(icon);
  1190.     if (closeflag)
  1191.     FreeCachedProperties(cprops);
  1192.     if (TargetWindow == cw || TargetWindow == icon)
  1193.     SetTarget(Context -> rootWob);
  1194. }
  1195.  
  1196. int
  1197. ClientWindowClose_aux(cw)
  1198. ClientWindow    cw;
  1199. {
  1200.     int             local_zrt_size = zrt_size;
  1201.     WOOL_OBJECT     closing;
  1202.     if (cw -> closing) {    /* Otherwise this is already done */
  1203.     SetTarget(cw);
  1204.     closing = cw -> closing;
  1205.     cw -> closing = 0;
  1206.     if (!(GWM_is_ending || GWM_is_restarting))
  1207.         wool_eval_and_catch_errors_proc(closing);
  1208.     if (cw->client_wob)
  1209.         WOOL_send(WOOL_close, cw->client_wob, (cw->client_wob));
  1210.     BarClose(cw -> titlebar);
  1211.     BarClose(cw -> leftbar);
  1212.     BarClose(cw -> rightbar);
  1213.     BarClose(cw -> basebar);
  1214.     decrease_reference(cw -> opening);
  1215.     decrease_reference(closing);
  1216.     decrease_reference(cw -> grabs);
  1217.     decrease_reference(cw -> icon_plug);
  1218.     decrease_reference(cw -> icon_description);
  1219.     /* remove from list */
  1220.     if (cw -> previous) {
  1221.         Context -> WindowCount--;
  1222.         cw -> previous -> next = cw -> next;
  1223.         if (cw -> next)
  1224.           cw -> next -> previous = cw -> previous;
  1225.     }
  1226.     if (cw -> client)
  1227.         XDeleteContext(dpy, cw -> client, client_context);
  1228.     WobRelease(cw);
  1229.     zrt_gc(local_zrt_size);
  1230.     return 1;
  1231.     }
  1232.     return 0;
  1233. }
  1234.  
  1235. ClientWindowMap(cw)
  1236. ClientWindow    cw;
  1237. {
  1238.     if (cw && !(cw -> mapped)) {
  1239.     if (cw -> client)
  1240.         XMapWindow(dpy, cw -> client);
  1241.     XMapWindow(dpy, cw -> hook);
  1242.     cw -> mapped = 1;
  1243.     Update_XA_WM_STATE(cw);
  1244.     }
  1245.     return;
  1246. }
  1247.  
  1248. ClientWindowUnmap(cw)
  1249. ClientWindow    cw;
  1250. {
  1251.     if (cw && cw -> mapped) {
  1252.     XUnmapWindow(dpy, cw -> hook);
  1253.         if (cw -> client && !cw -> client_wob)
  1254.           XUnmapWindow(dpy, cw -> client);
  1255.     cw -> mapped = 0;
  1256.     Update_XA_WM_STATE(cw);
  1257.     }
  1258.     return;
  1259. }
  1260.  
  1261. ClientWindowInitialMap(cw)
  1262. ClientWindow    cw;
  1263. {
  1264.     int             mapping = 1;
  1265.  
  1266.     if (!cw || cw -> status & IconStatus)
  1267.     return;
  1268.     if (cw -> cached_props -> wm_hints.flags & StateHint) {
  1269.     switch (cw -> cached_props -> wm_hints.initial_state) {
  1270.     case WM_STATE_Iconified: 
  1271.     {
  1272.         int local_zrt_size = zrt_size;
  1273.         WOOL_OBJECT res;
  1274.         if (TargetWindow != cw) 
  1275.         SetTarget(cw);
  1276.         
  1277.         res = (WOOL_OBJECT) 
  1278.         wool_eval_and_catch_errors(WL_iconify_window_call);
  1279.         zrt_gc(local_zrt_size);
  1280.         
  1281.         mapping = res ? 0 : 1;    /* map in case of errors */
  1282.     }
  1283.         break;
  1284.     case WM_STATE_Withdrawn:    /* ERROR! buggy clients */
  1285.         /* we map, ignoring the bogus hint but printing a warning */
  1286.         wool_warning1("GWM: window %s has a bogus hint WM_STATE_Withdrawn as its initial_map field in its WM_HINTS property!\n", 
  1287.               ((WOOL_String) (cw -> cached_props -> windowname))
  1288.               -> string);
  1289.         break;
  1290.     }
  1291.     }
  1292.     if (mapping) {
  1293.     XMapWindow(dpy, cw -> hook);
  1294.     cw -> mapped = 1;
  1295.     if (cw -> client)
  1296.         XMapWindow(dpy, cw -> client);
  1297.     }
  1298.     Update_XA_WM_STATE(cw);
  1299. }
  1300.  
  1301. int
  1302. Mapped(w) 
  1303. Window w;
  1304. {
  1305.     XWindowAttributes wa;
  1306.  
  1307.     if (TrapXErrors(XGetWindowAttributes(dpy, w, &wa)))
  1308.     return 0;
  1309.     else
  1310.     return (wa.map_state != IsUnmapped);
  1311. }
  1312.  
  1313. /* to make a window appear, we may have to de-iconify it*/
  1314.  
  1315. ShowClientWindow(cw)
  1316. ClientWindow    cw;
  1317. {
  1318.     if (!(cw->opening)) {
  1319.     if(!(cw->mapped) &&
  1320.        !(cw->status & IconStatus)) {    /* client is mapping its window */
  1321.         if (cw->icon) {
  1322.         SetTarget(cw->icon);
  1323.         {
  1324.             int local_zrt_size = zrt_size;
  1325.             
  1326.             WOOL_send(WOOL_eval, WL_iconify_window_call,
  1327.                   (WL_iconify_window_call));
  1328.             zrt_gc(local_zrt_size);
  1329.         }
  1330.         } else {
  1331.         XMapWindow(dpy, cw->hook);
  1332.         cw->mapped = 1;
  1333.         Update_XA_WM_STATE(cw);
  1334.         }
  1335.     }
  1336.     } else {                /* initial map */
  1337.     ClientWindowExecuteOpening(cw);
  1338.     ClientWindowInitialMap(cw);
  1339.     }
  1340. }
  1341.  
  1342. ClientWindowEventHandler(cw, evt)
  1343. ClientWindow    cw;
  1344. Event        evt;
  1345. {
  1346.     switch (evt -> type) {
  1347.     case MapNotify:        /* hook is mapped and were waiting for it */
  1348.     if (evt -> xmap.window == cw -> hook
  1349.         && ((WOOL_Fsm) cw -> fsm) -> mask & StructureNotifyMask) {
  1350.         WLFsm_action(cw -> fsm, cw, evt);
  1351.     }
  1352.     break;
  1353.         
  1354.     case MapRequest:
  1355.     XMapWindow(dpy, cw -> client);
  1356.     ShowClientWindow(cw);
  1357.     break;
  1358.  
  1359.     case UnmapNotify:
  1360.     if (evt -> xunmap.window == cw -> client
  1361.             && cw -> mapped) {
  1362.         XUnmapWindow(dpy, cw -> hook);
  1363.         cw -> mapped = 0;
  1364.         Update_XA_WM_STATE(cw);
  1365.     }
  1366.     break;
  1367.  
  1368.     case ConfigureNotify:
  1369.     if (evt -> xconfigure.window == cw -> client
  1370.             && evt -> xconfigure.event == cw -> hook
  1371.         && ((WOOL_Fsm) cw -> fsm) -> mask & SubstructureNotifyMask) {
  1372.         WLFsm_action(cw -> fsm, cw, evt);
  1373.     }
  1374.     break;
  1375.         
  1376.     case ConfigureRequest:
  1377.     ConfigureRequestEventHandler(cw, evt);
  1378.     break;
  1379.  
  1380.     case DestroyNotify:
  1381.     if (evt -> xdestroywindow.window == cw -> client
  1382.             && evt -> xdestroywindow.event == cw -> client) {
  1383.         ClientWindowClose(cw);
  1384.     }
  1385.     break;
  1386.  
  1387.     case ColormapNotify:        /* if is the active one, re-install */
  1388.     if (evt -> xcolormap.new) {
  1389.         Colormap        old_colormap = cw -> colormap;
  1390.  
  1391.         SetTarget(cw);
  1392.         cw -> colormap = evt -> xcolormap.colormap;
  1393.         if (Context -> InstalledColormapCW == cw)
  1394.         if (cw -> colormap)
  1395.             XInstallColormap(dpy, cw -> colormap);
  1396.         else if (old_colormap)
  1397.             XInstallColormap(dpy, Context -> rootWob -> colormap);
  1398.     }                /* else install/uninstall result */
  1399.     break;
  1400.  
  1401.     case GWMUserEvent:
  1402.     WLFsm_action(cw -> fsm, cw, evt);
  1403.     if (GWM_Propagate_user_events) {
  1404.         if (cw -> client_wob)
  1405.         WOOL_send(WOOL_process_event, cw -> client_wob,
  1406.               (cw -> client_wob, evt));
  1407.         if (cw -> titlebar)
  1408.         WOOL_send(WOOL_process_event, cw -> titlebar,
  1409.               (cw -> titlebar, evt));
  1410.         if (cw -> leftbar)
  1411.         WOOL_send(WOOL_process_event, cw -> leftbar,
  1412.               (cw -> leftbar, evt));
  1413.         if (cw -> rightbar)
  1414.         WOOL_send(WOOL_process_event, cw -> rightbar,
  1415.               (cw -> rightbar, evt));
  1416.         if (cw -> basebar)
  1417.         WOOL_send(WOOL_process_event, cw -> basebar,
  1418.               (cw -> basebar, evt));
  1419.     }
  1420.     break;
  1421.  
  1422.     case ClientMessage:        /* iccc: for iconifying window */
  1423.     SetTarget(cw);
  1424.     if (evt -> xclient.message_type == XA_WM_CHANGE_STATE
  1425.         && evt -> xclient.data.l[0] == IconicState) {
  1426.         int local_zrt_size = zrt_size;
  1427.         
  1428.         WOOL_send(WOOL_eval, WL_iconify_window_call,
  1429.               (WL_iconify_window_call));
  1430.         zrt_gc(local_zrt_size);
  1431.         /* iccc: for deleting window */
  1432.     } else if (evt -> xclient.message_type == XA_WM_PROTOCOLS
  1433.         && evt -> xclient.data.l[0] == (long) XA_WM_DELETE_WINDOW) {
  1434.         ClientWindow    icon = cw -> icon;
  1435.         Wob old_wob = TargetWob;
  1436.         ClientWindow old_client = TargetWindow;
  1437.  
  1438.         ClientWindowClose(cw);
  1439.         if (TargetWob == (Wob) Context -> rootWob
  1440.         && old_client != cw && old_client != icon)
  1441.         SetTarget(old_wob);
  1442.     } else {
  1443.         WLFsm_action(cw -> fsm, cw, evt);
  1444.     }
  1445.     break;
  1446.  
  1447.     case PropertyNotify:
  1448.     SetTarget(cw);
  1449.     if (evt -> xproperty.atom == XA_GWM_EXECUTE) {
  1450.         WlExecGWM_EXECUTE();
  1451.     } else {
  1452.         GWM_backup_old_property = 1;
  1453.         UpdateCachedProperty(cw -> window, evt -> xproperty.atom);
  1454.         GWM_backup_old_property = 0;
  1455.         WLFsm_action(cw -> fsm, cw, evt);
  1456.     }
  1457.     break;
  1458.  
  1459.     default:
  1460.  
  1461. #ifdef SHAPE
  1462.     if (GWM_ShapeExtension &&
  1463.         evt -> type == GWM_ShapeEventBase + ShapeNotify)
  1464.         ShapeNotifyEventHandler(cw, evt);
  1465.     else
  1466. #endif /* SHAPE */
  1467.         {
  1468.         WLFsm_action(cw -> fsm, cw, evt);
  1469.         }
  1470.     }
  1471. }
  1472.  
  1473. /*
  1474.  * ConfigureRequestEventHandler is used to decode what operation is really
  1475.  * intended by the configure event to only perform the appropriate action
  1476.  */
  1477. /* TO_DO: do only one XConfigure...*/
  1478.  
  1479. ConfigureRequestEventHandler(cw, evt)
  1480. ClientWindow    cw;
  1481. XConfigureRequestEvent           *evt;
  1482. {
  1483.     XWindowChanges  values;
  1484.     int real_configure_sent = evt -> value_mask
  1485.     & (CWWidth | CWHeight | CWBorderWidth);
  1486.  
  1487.     /* move: move hook */        /* MOVE HOOK */
  1488.     if (evt -> value_mask & (CWX | CWY)) {
  1489.     int xgrav, ygrav;
  1490.     GetWinGravityHint(cw, &xgrav, &ygrav);
  1491.     XMoveWindow(dpy, cw -> hook,
  1492.             (evt -> value_mask & CWX ?
  1493.              cw -> box.x = (xgrav == 0 ?
  1494.                     evt -> x - cw -> box.borderwidth : 
  1495.                     evt -> x - cw -> inner_x
  1496.                                      - cw -> box.borderwidth) : 
  1497.              cw -> box.x),
  1498.             (evt -> value_mask & CWY ?
  1499.              cw -> box.y = (ygrav == 0 ?
  1500.                     evt -> y - cw -> box.borderwidth :
  1501.                     evt -> y - cw -> inner_y
  1502.                              - cw -> box.borderwidth) :
  1503.              cw -> box.y));
  1504.     if(!real_configure_sent)
  1505.         SendSyntheticMoveEvent(cw);
  1506.     }
  1507.     /* resize is handled via recomputing */
  1508.     if (real_configure_sent) {
  1509.     values.width = evt -> width;
  1510.     values.height = evt -> height;
  1511.     values.border_width = evt -> border_width;
  1512.     XSync(dpy, 0);
  1513.     XSetErrorHandler(NoXError);
  1514.     ErrorStatus = 0;
  1515.     XConfigureWindow(dpy, cw -> client,
  1516.            evt -> value_mask & (CWWidth | CWHeight | CWBorderWidth),
  1517.              &values);
  1518.     XSync(dpy, 0);
  1519.     XSetErrorHandler(XError);
  1520.     if (ErrorStatus)
  1521.         return;            /* problem appeared */
  1522.     ReconfigureClientWindow(cw, cw -> client);
  1523.     }
  1524.     /* stacking change is independant of the rest and done last */
  1525.     if (evt -> value_mask & CWStackMode) {
  1526.     Wob             sibling = 0;
  1527.  
  1528.     if (evt -> value_mask & CWSibling) {    /* % to a sibling */
  1529.         sibling = (Wob) LookUpClient(evt -> above);
  1530.         if (!sibling)
  1531.         sibling = (Wob) LookUpWob(evt -> above);
  1532.     }
  1533.     if (sibling) {
  1534.         values.sibling = sibling->hook;
  1535.     }
  1536.     values.stack_mode = evt -> detail;
  1537.     XConfigureWindow(dpy, cw -> hook,
  1538.           evt -> value_mask & (CWStackMode | (sibling ? CWSibling : 0)),
  1539.              &values);
  1540.     if (cw->map_on_raise
  1541.         && (evt -> value_mask & CWStackMode)
  1542.         && (values.stack_mode == Above
  1543.         || values.stack_mode == TopIf)) {
  1544.         ShowClientWindow(cw);
  1545.     }
  1546.     }
  1547. }
  1548.  
  1549. UnDecorateWindow(cw, must_reparent, remap)
  1550. ClientWindow    cw;
  1551. int             must_reparent;    /* must reparent window back to root? */
  1552. int             remap;        /* must try to re-map window? */
  1553. {
  1554.     Window          client = cw -> window -> client;
  1555.     Wob             wob = cw -> window -> client_wob;
  1556.  
  1557.     int             oldbw = cw -> window -> old_inner_borderwidth;
  1558.     int             must_remap;
  1559.  
  1560.     cw = cw -> window;
  1561.     if (wob) {
  1562.     wob -> parent = (Wob) Context -> rootWob;
  1563.     }
  1564.     if (remap)
  1565.     must_remap = (Update_XA_WM_STATE(cw) == WM_STATE_Withdrawn ? 0 : 1);
  1566.     else
  1567.     must_remap = 0;
  1568.     XSetErrorHandler(NoXError);
  1569.     if (cw -> mapped)
  1570.     XUnmapWindow(dpy, cw -> hook);
  1571.     if (must_reparent) {
  1572.     ObeyWinGravityHint(cw, 0);
  1573.     XReparentWindow(dpy, client, Context -> root,
  1574.             cw -> box.x, cw -> box.y);
  1575.         SendSyntheticMoveEvent(cw);
  1576.     if (!wob)
  1577.         XRemoveFromSaveSet(dpy, client);
  1578.     }
  1579.     /* reparent icon-window if client created it */
  1580.     if (cw->icon && cw->icon->client && (!cw->icon->client_wob)) {
  1581.     XReparentWindow(dpy, cw->icon->client, Context -> root, 0, 0); 
  1582.     XRemoveFromSaveSet(dpy, cw->icon->client);
  1583.         XUnmapWindow(dpy, cw->icon->client);
  1584.     }
  1585.     if (!cw -> client_shaped)
  1586.     XSetWindowBorderWidth(dpy, client, oldbw);
  1587.     if (cw -> client_wob)
  1588.     cw -> client_wob -> status &= TopLevelXWindowStatus;
  1589.     if (must_remap)
  1590.     XMapWindow(dpy, cw -> client);
  1591.     ClientWindowClose(cw);
  1592.     XSync(dpy, 0);
  1593.     XSetErrorHandler(XError);
  1594. }
  1595.  
  1596. /* if a decoration aborts, we must put it back on screen! */
  1597. ShowUndecoratedWindow(cw)
  1598.     ClientWindow    cw;
  1599. {
  1600.     XSync(dpy, 0);
  1601.     GWM_ProcessEvents(0);    /* empty events */
  1602.     if (cw) {
  1603.     cw->mapped = 0;            /* forces a remap */
  1604.     ClientWindowMap(cw);
  1605.     }
  1606. }
  1607.  
  1608. ReconfigureClientWindow(cw, culprit)
  1609. ClientWindow    cw;
  1610. Wob        culprit;    /* cw, client or bar */
  1611. {
  1612.     int             x = cw -> box.x, y = cw -> box.y;
  1613.     int             inner_x = cw -> inner_x, inner_y = cw -> inner_y;
  1614.  
  1615.     if (culprit == (Wob) cw -> client || culprit == cw -> client_wob
  1616.     || (!cw -> client)) {
  1617.     ClientWindowComputeGeometry(cw);
  1618.     }
  1619.     ClientWindowComputeBarDims(cw);
  1620. /*    if (culprit != (Wob) cw -> titlebar) */
  1621.     ReconfigureBar(cw -> titlebar, cw);
  1622. /*    if (culprit != (Wob) cw -> leftbar) */
  1623.     ReconfigureBar(cw -> leftbar, cw);
  1624. /*    if (culprit != (Wob) cw -> rightbar) */
  1625.     ReconfigureBar(cw -> rightbar, cw);
  1626. /*    if (culprit != (Wob) cw -> basebar) */
  1627.     ReconfigureBar(cw -> basebar, cw);
  1628.     XMoveResizeWindow(dpy, cw -> hook, cw -> box.x = x, cw -> box.y = y,
  1629.               cw -> box.width, cw -> box.height);
  1630.     if (inner_x != cw -> inner_x || inner_y != cw -> inner_y)
  1631.     XMoveWindow(dpy, cw -> client, cw -> inner_x, cw -> inner_y);
  1632. #ifdef SHAPE
  1633.     /* do not reshape if client reshaped, it will send an event later */
  1634.     if (WindowIsShaped(cw) &&
  1635.         !((culprit == (Wob) cw -> client) && !cw -> client_wob && cw -> client_shaped)) 
  1636.       ClientWindowSetShape(cw);
  1637. #endif /* SHAPE */
  1638. }
  1639.  
  1640. /*
  1641.  * transforms outer sizes in inner ones
  1642.  */
  1643.  
  1644. dims_outer_to_inner(cw, pw, ph)
  1645. ClientWindow    cw;
  1646. int *pw, *ph;
  1647. {
  1648.     *pw = *pw - (cw -> box.width - cw -> inner_width) - 2 * cw -> box.borderwidth;
  1649.     *ph = *ph - (cw -> box.height - cw -> inner_height) - 2 * cw -> box.borderwidth;
  1650. }
  1651.  
  1652. /****************\
  1653. *          *
  1654. * window groups     *
  1655. *          *
  1656. \****************/
  1657.  
  1658. /* Maintains the group list of a group_leader
  1659.  * In the client_group field of the cw, we find:
  1660.  *     - for the leaded, the cw of the leader.
  1661.  *     - for the leader, the list (WOOL_List) of grouped sons
  1662.  *       first one being the leader itself
  1663.  */
  1664.  
  1665. AddWindowToGroupLeader(cw, group_leader)
  1666. ClientWindow cw, group_leader;
  1667. {
  1668.     WOOL_List      *gwlgp = (WOOL_List *) & (group_leader ->
  1669.     cached_props -> client_group);
  1670.  
  1671.     /* if leader's group is not yet initialised, do it */
  1672.     if (!(*gwlgp)) {
  1673.     if (cw != group_leader) {    /* follower */
  1674.         AddWindowToGroupLeader(group_leader, group_leader);
  1675.         AddWindowToGroupLeader(cw, group_leader);
  1676.     } else {        /* leader */
  1677.         increase_reference(*gwlgp = wool_list_make(1));
  1678.         increase_reference((*gwlgp) -> list[0] = (WOOL_OBJECT)
  1679.                    WLNumber_make(group_leader));
  1680.     }
  1681.     /* leader is initialized */
  1682.     } else if ((*gwlgp) -> type == WLList) {
  1683.     int             i;
  1684.     WOOL_List       old_list;
  1685.  
  1686.     for (i = 0; i < (*gwlgp) -> size; i++)
  1687.         if ((*gwlgp) -> list[i] == (WOOL_OBJECT) cw)
  1688.         return;
  1689.     old_list = *gwlgp;
  1690.     increase_reference(*gwlgp = wool_list_make((*gwlgp) -> size + 1));
  1691.     copy_n_objects(old_list -> list, (*gwlgp) -> list, old_list -> size);
  1692.     decrease_reference(old_list);
  1693.     increase_reference((*gwlgp) -> list[(*gwlgp) -> size - 1]
  1694.                = (WOOL_OBJECT) WLNumber_make(cw));
  1695.     if((cw -> cached_props -> client_group)
  1696.             && (cw -> cached_props -> client_group -> type == WLList))
  1697.         decrease_reference(cw -> cached_props -> client_group);
  1698.     cw -> cached_props -> client_group = (WOOL_OBJECT) group_leader;
  1699.     }
  1700. }
  1701.  
  1702. /* called when a window is closed if client_group not void
  1703.  */
  1704.  
  1705. RemoveWindowFromGroup(cw)
  1706. ClientWindow cw;
  1707. {
  1708.     WOOL_List      *gwlgp = (WOOL_List *) & (cw ->
  1709.                 cached_props -> client_group), list;
  1710.     int             i;
  1711.  
  1712.     if ((*gwlgp) -> type == WLList) {    /* leader */
  1713.     ClientWindow    son;
  1714.  
  1715.     list = (*gwlgp);
  1716.     for (i = 0; i < list -> size; i++) {
  1717.         son = (ClientWindow) ((WOOL_Number) list -> list[i]) -> number;
  1718.         if (WobIsValid(son))
  1719.         son -> cached_props -> client_group = NULL;
  1720.     }
  1721.     decrease_reference(list);
  1722.     } else {            /* follower */
  1723.     ClientWindow leader = (ClientWindow) cw->cached_props->client_group;
  1724.     list = (WOOL_List) leader -> cached_props -> client_group;
  1725.  
  1726.     if (list -> type == WLList) {
  1727.         cw -> cached_props -> client_group = NULL;
  1728.         i = 0;
  1729.         while (i < list -> size) {
  1730.         if (((WOOL_Number) list -> list[i]) -> number == (Num) cw)
  1731.             break;
  1732.         i++;
  1733.         }
  1734.         if (i == list -> size) /* not in list (should not happen) */
  1735.         return;
  1736.         if (--(list -> size) == 1) { /* only leader remains in list
  1737.                         so destroy the list */
  1738.         leader -> cached_props -> client_group = NULL;
  1739.         decrease_reference(list);
  1740.         } else {        /* remove window from leader's list */
  1741.         while (i++ < list -> size)
  1742.             list -> list[i - 1] = list -> list[i];
  1743.         }
  1744.     }
  1745.     }
  1746. }
  1747.         
  1748. /*
  1749.  * wool interface
  1750.  */
  1751.  
  1752. WOOL_OBJECT
  1753. wool_window_group_get()
  1754. {
  1755.     ClientWindow    cw = TargetWindow -> window;
  1756.  
  1757.     if (cw -> cached_props -> client_group) { /* group exists */
  1758.     if (cw -> cached_props -> client_group -> type == WLList) { /* lead */
  1759.         return cw -> cached_props -> client_group;
  1760.     } else {            /* follower */
  1761.         WOOL_OBJECT group =
  1762.         ((ClientWindow) (cw -> cached_props -> client_group))
  1763.             -> cached_props -> client_group;
  1764.         if (group -> type == WLList) { /* sanity check */
  1765.         return group;
  1766.         } else {
  1767.         cw -> cached_props -> client_group = 0;
  1768.         return NIL;
  1769.         }
  1770.     }
  1771.     } else {                /* no group */
  1772.     return NIL;
  1773.     }
  1774. }
  1775.  
  1776. WOOL_OBJECT
  1777. wool_window_group_set(group_leader_num)
  1778. WOOL_Number group_leader_num;
  1779. {
  1780.     ClientWindow    cw = TargetWindow -> window;
  1781.     ClientWindow    group_leader;
  1782.  
  1783.     if (group_leader_num -> type == WLNumber) {
  1784.     group_leader = (ClientWindow) group_leader_num -> number;
  1785.     } else if (group_leader_num -> type == WLList) {
  1786.     group_leader = (ClientWindow)
  1787.         ((WOOL_Number) ((WOOL_List) group_leader_num) -> list[0])
  1788.         -> number;
  1789.     } else if(cw-> cached_props -> client_group) {
  1790.      RemoveWindowFromGroup(cw);
  1791.      return NIL;
  1792.     }
  1793.     AddWindowToGroupLeader(cw, group_leader);
  1794.     return (WOOL_OBJECT) group_leader_num;
  1795. }
  1796.  
  1797. ClientWindow
  1798. ClientWindowLeader(cw)
  1799.     ClientWindow cw;
  1800. {
  1801.     if (cw->cached_props->client_group) {    /* group exists */
  1802.     if (cw->cached_props->client_group->type == WLList) {    /* lead */
  1803.         return cw;
  1804.     } else {            /* follower */
  1805.         return (ClientWindow) (cw->cached_props->client_group);
  1806.     }
  1807.     } else {
  1808.     return 0;
  1809.     }
  1810. }
  1811.  
  1812. ClientWindowRecordClient(cw)
  1813. ClientWindow cw;
  1814. {
  1815.     XSaveContext(dpy, cw -> client, client_context, (caddr_t)cw);
  1816. }
  1817.  
  1818. #ifdef SHAPE
  1819. /* non-rectangular extension:
  1820.  * set the frame to the shape of client +bars
  1821.  */
  1822.  
  1823. WindowIsShaped(cw)
  1824. ClientWindow cw;
  1825. {
  1826.   if (cw -> client_shaped)
  1827.     return 1;
  1828.   if (((cw -> titlebar) && (cw -> titlebar -> shaped)) ||
  1829.       ((cw -> basebar) && (cw -> basebar -> shaped)) ||
  1830.       ((cw -> leftbar) && (cw -> leftbar -> shaped)) ||
  1831.       ((cw -> rightbar) && (cw -> rightbar -> shaped)))
  1832.     return 1;
  1833.   return 0;
  1834. }
  1835.  
  1836. ClientWindowSetShape(cw)
  1837. ClientWindow cw;
  1838. {
  1839.     XRectangle rect;
  1840.     int initop = ShapeSet;
  1841.  
  1842.     if (cw -> box.borderwidth && GWM_allow_border_on_shaped_windows) {
  1843.     /* disabled for back compat */
  1844.     rect.x = - cw -> box.borderwidth;
  1845.     rect.y = - cw -> box.borderwidth;
  1846.     rect.width = cw -> box.width + 2 * cw -> box.borderwidth;
  1847.     rect.height = cw -> box.height + 2 * cw -> box.borderwidth;
  1848.     XShapeCombineRectangles(dpy, cw -> hook, ShapeBounding,
  1849.                 0, 0,
  1850.                 &rect, 1, ShapeSet, 0);
  1851.     rect.x = 0;
  1852.     rect.y = 0;
  1853.     rect.width = cw -> box.width;
  1854.     rect.height = cw -> box.height;
  1855.     XShapeCombineRectangles(dpy, cw -> hook, ShapeBounding,
  1856.                 0, 0,
  1857.                 &rect, 1, ShapeSubtract, 0);
  1858.     initop = ShapeUnion;
  1859.     }
  1860.     if (cw -> client_shaped)
  1861.     XShapeCombineShape (dpy, cw -> hook, ShapeBounding,
  1862.                 cw -> inner_x, cw -> inner_y,
  1863.                 cw -> client, ShapeBounding,
  1864.                 initop);
  1865.     else {
  1866.     rect.x = cw -> inner_x;
  1867.     rect.y = cw -> inner_y;
  1868.     rect.width = cw -> inner_width + 2 * cw -> inner_borderwidth;
  1869.     rect.height = cw -> inner_height + 2 * cw -> inner_borderwidth;
  1870.     XShapeCombineRectangles(dpy, cw -> hook, ShapeBounding, 
  1871.                 0, 0,
  1872.                 &rect, 1, initop, 0); 
  1873.     }
  1874.     if (cw -> titlebar)
  1875.     XShapeCombineShape (dpy, cw -> hook, ShapeBounding,
  1876.                             cw -> titlebar -> box.borderwidth, 
  1877.                             cw -> titlebar -> box.borderwidth,
  1878.                             cw -> titlebar -> hook, ShapeBounding,
  1879.                             ShapeUnion);
  1880.     if (cw -> leftbar)
  1881.     XShapeCombineShape (dpy, cw -> hook, ShapeBounding,
  1882.                             cw -> leftbar -> box.borderwidth, 
  1883.                             cw -> leftbar -> box.borderwidth + cw -> inner_y,
  1884.                             cw -> leftbar -> hook, ShapeBounding,
  1885.                             ShapeUnion);
  1886.     if (cw -> rightbar)
  1887.     XShapeCombineShape (dpy, cw -> hook, ShapeBounding,
  1888.                             cw -> inner_x + cw -> inner_width
  1889.                             + cw -> rightbar -> box.borderwidth
  1890.                             + 2 * cw -> inner_borderwidth,
  1891.                             cw -> rightbar -> box.borderwidth + cw -> inner_y,
  1892.                             cw -> rightbar -> hook, ShapeBounding,
  1893.                             ShapeUnion);
  1894.     if (cw -> basebar)
  1895.     XShapeCombineShape (dpy, cw -> hook, ShapeBounding,
  1896.                             cw -> basebar -> box.borderwidth, 
  1897.                             cw -> inner_y + cw -> inner_height
  1898.                             + cw -> basebar -> box.borderwidth
  1899.                             + 2 * cw -> inner_borderwidth,
  1900.                             cw -> basebar -> hook, ShapeBounding,
  1901.                             ShapeUnion);
  1902. }
  1903.  
  1904. /* what to do if shape changes
  1905.  */
  1906.  
  1907. ShapeNotifyEventHandler(cw, evt)
  1908. ClientWindow    cw;
  1909. XShapeEvent    *evt;
  1910. {
  1911.     if (evt -> kind == ShapeBounding && evt -> window == cw -> client) {
  1912.     cw -> client_shaped = evt -> shaped;
  1913.     if (WindowIsShaped(cw))
  1914.         ClientWindowSetShape(cw);
  1915.     else
  1916.         XShapeCombineMask (dpy, cw -> hook, ShapeBounding,
  1917.                    0, 0, None, ShapeSet);
  1918.     }
  1919. }
  1920.  
  1921. WOOL_OBJECT
  1922. wool_window_has_shaped_client()
  1923. {
  1924.     if (TargetWindow -> client_shaped)
  1925.     return TRU;
  1926.     else
  1927.     return NIL;
  1928. }
  1929.  
  1930. #endif /* SHAPE */
  1931.