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

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /***********************************************\
  5. *                             *
  6. * GWM: icccm.c                        *
  7. * Miscellaneous utilities to enforce the ICCCM  *
  8. *                             *
  9. \***********************************************/
  10.  
  11. #include "EXTERN.h"
  12. #include <stdio.h>
  13. #include "wool.h"
  14. #include "wl_atom.h"
  15. #include "wl_list.h"
  16. #include "wl_string.h"
  17. #include "gwm.h"
  18. #include <X11/Xatom.h>
  19. #include <X11/Xutil.h>
  20. #include "wl_number.h"
  21.  
  22. extern XError(), NoXError();
  23. DECLARE_strchr;
  24.  
  25. /* Used to tell a client that it has been moved
  26.  */
  27.  
  28. SendSyntheticMoveEvent(cw)
  29. ClientWindow    cw;
  30. {
  31.     XConfigureEvent    event;
  32.  
  33.     if(cw -> client_wob)        /* do not send to ourselves */
  34.     return;
  35.     event.type = ConfigureNotify;
  36.     event.display = dpy;
  37.     event.event = cw -> client;
  38.     event.window = cw -> client;
  39.     event.x = cw -> inner_x + cw ->box.x + cw -> box.borderwidth;
  40.     event.y = cw -> inner_y + cw ->box.y + cw -> box.borderwidth;
  41.     event.width = cw -> inner_width;
  42.     event.height = cw -> inner_height;
  43.     event.border_width = cw -> inner_borderwidth;
  44.     event.above = cw -> hook;
  45.     event.override_redirect = False;
  46.     Trace('e', ("SendSyntheticMoveEvent: event 0x%x window 0x%x x %d y %d w %d h %d bw %d above 0x%x\n", event.event, event.window, event.x, event.y, event.width, event.height, event.border_width, event.above));
  47.     XSendEvent(dpy, cw -> client, False, StructureNotifyMask,
  48.            (XEvent *) &event);
  49. }
  50.  
  51. /* for defining another icon for WM_STATE property
  52.  */
  53.  
  54. WOOL_OBJECT
  55. wool_wm_state_user_icon_get()
  56. {
  57.     if (TargetWindow -> cached_props -> user_icon)
  58.     return (WOOL_OBJECT)
  59.         WLNumber_make(TargetWindow -> cached_props -> user_icon);
  60.     else
  61.     return NIL;
  62. }
  63.  
  64. WOOL_OBJECT
  65. wool_wm_state_user_icon_set(number)
  66. WOOL_Number    number;
  67. {
  68.     must_be_number(number, 0);
  69.     TargetWindow -> cached_props -> user_icon = (ClientWindow)
  70.     number -> number;
  71.     Update_XA_WM_STATE(TargetWindow);
  72.     return (WOOL_OBJECT) number;
  73. }
  74.  
  75. /* updating this window's WM_STATE once another icon is defined
  76.  */
  77.  
  78. WOOL_OBJECT
  79. wool_wm_state_update(argc, argv)
  80. int     argc;
  81. WOOL_Atom argv[];
  82. {
  83.     int state = -1;
  84.     if (argc) {
  85.     if (argv[0] == WA_window)
  86.         state = WM_STATE_Normal;
  87.     else if (argv[0] == WA_icon)
  88.         state = WM_STATE_Iconified;
  89.     else if ((WOOL_OBJECT) argv[0] == NIL)
  90.             state = WM_STATE_Withdrawn;
  91.     }
  92.     if (!TargetWindow -> window -> client_wob)
  93.       Set_XA_WM_STATE(TargetWindow -> window, state);
  94.     return NIL;
  95. }
  96.  
  97. /*&WN window-wm-state
  98.  * getting this window's WM_STATE once another icon is defined
  99.  */
  100.  
  101. WOOL_OBJECT
  102. wool_wm_state_get(argc, argv)
  103. int     argc;
  104. WOOL_Number argv[];
  105. {
  106.     ClientWindow    cw = TargetWindow;
  107.     Atom            actualtype;
  108.     int             actualformat;
  109.     unsigned long   nitems;
  110.     unsigned long   bytesafter;
  111.     WM_STATE_PROP   wm_state;
  112.  
  113.     if (argc) {
  114.     must_be_number(argv[0], 0);
  115.     cw = (ClientWindow) argv[0] -> number;
  116.     }
  117.     cw = cw -> window;
  118.     if ((Success == XGetWindowProperty(dpy, cw -> client, XA_WM_STATE, 0,
  119.               WM_STATE_PROP_Length, False, XA_WM_STATE, &actualtype,
  120.                 &actualformat, &nitems, &bytesafter, 
  121.                        (unsigned char **) &wm_state))
  122.     && nitems && wm_state) {
  123.     switch (wm_state -> state) {
  124.     case WM_STATE_Iconified:
  125.         XFree(wm_state);
  126.         return (WOOL_OBJECT) WA_icon;
  127.     case WM_STATE_Normal:
  128.         XFree(wm_state);
  129.         return (WOOL_OBJECT) WA_window;
  130.     default:
  131.         XFree(wm_state);
  132.     }
  133.     }
  134.     return NIL;
  135. }
  136.  
  137. /* Colormaps
  138.  * colormap focus management:
  139.  */
  140.  
  141. WOOL_OBJECT
  142. wool_set_colormap_focus(argc, argv)
  143. int    argc;
  144. WOOL_Number argv[];
  145. {
  146.     ClientWindow    cw = TargetWindow;
  147.  
  148.     if (argc) {
  149.     if (argv[0] == (WOOL_Number) NIL) {
  150.         GWM_set_default_colormap();
  151.         Context -> InstalledColormapCW = Context -> rootWob;
  152.         return NIL;
  153.     }
  154.     must_be_number(argv[0], 0);
  155.     cw = (ClientWindow) argv[0] -> number;
  156.     }
  157.     if (cw -> colormap) {
  158.     if (cw != Context -> InstalledColormapCW ||
  159.         cw -> colormap != Context -> InstalledColormapCW -> colormap)
  160.         XInstallColormap(dpy, cw -> colormap);
  161.     if (cw -> cached_props -> colormap_windows)
  162.         cw -> cached_props -> colormap_windows_index = 0;
  163.     } else {
  164.     GWM_set_default_colormap();
  165.     }
  166.     Context -> InstalledColormapCW = cw;
  167.     return NIL;
  168. }
  169.  
  170. GWM_set_default_colormap()
  171. {
  172.     if (Context -> InstalledColormapCW != Context -> rootWob &&
  173.     Context -> InstalledColormapCW -> colormap &&
  174.     Context -> InstalledColormapCW -> colormap
  175.     != Context -> rootWob -> colormap) {
  176.     XInstallColormap(dpy, Context -> rootWob -> colormap);
  177.     Context -> InstalledColormapCW = Context -> rootWob;
  178.     }
  179. }
  180.  
  181. /* Sub windows colormaps
  182.  * colormap focus management:
  183.  */
  184.  
  185. WOOL_OBJECT
  186. wool_set_subwindow_colormap_focus(argc, argv)
  187. int    argc;
  188. WOOL_Number argv[];
  189. {
  190.     ClientWindow    cw = TargetWindow;
  191.     int             index;
  192.     XWindowAttributes wa;
  193.     Colormap        current_colormap;
  194.  
  195.     if (argc) {
  196.     must_be_number(argv[0], 0);
  197.     index = argv[0] -> number;
  198.     }
  199.     if (cw == Context -> InstalledColormapCW &&
  200.     cw -> cached_props -> colormap_windows) {
  201.     if (argc) {            /* absolute index */
  202.         cw -> cached_props -> colormap_windows_index =
  203.         index % cw -> cached_props -> colormap_windows_size;
  204.         XGetWindowAttributes(dpy,
  205.                  cw -> cached_props -> colormap_windows[
  206.             cw -> cached_props -> colormap_windows_index], &wa);
  207.         if (wa.colormap)
  208.         XInstallColormap(dpy, wa.colormap);
  209.     } else {            /* increment index */
  210.         XGetWindowAttributes(dpy,
  211.                  cw -> cached_props -> colormap_windows[
  212.             cw -> cached_props -> colormap_windows_index], &wa);
  213.         current_colormap = wa.colormap;
  214.         for (index = cw -> cached_props -> colormap_windows_index + 1;
  215.          index % cw -> cached_props -> colormap_windows_size !=
  216.          cw -> cached_props -> colormap_windows_index;
  217.          index++) {
  218.         index = index % cw -> cached_props -> colormap_windows_size;
  219.         XGetWindowAttributes(dpy,
  220.             cw -> cached_props -> colormap_windows[index], &wa);
  221.         if (wa.colormap != current_colormap) {
  222.             cw -> cached_props -> colormap_windows_index = index;
  223.             XInstallColormap(dpy, wa.colormap);
  224.             break;
  225.         }
  226.         }
  227.     }
  228.     }
  229.     return NIL;
  230. }
  231.  
  232.  
  233. /* updating a colormap for a watched window in a WM_COLORMAP_WINDOWS list
  234.  */
  235.  
  236. Update_colormap_in_colormap_windows_list(evt)
  237. XColormapEvent    *evt;
  238. {
  239.     ClientWindow    cw;
  240.  
  241.     if (ContextOfXWindow(evt -> window))
  242.     return;                /* if no more window, returns */
  243.     cw = Context -> InstalledColormapCW;
  244.     if (WobIsValid(cw) && cw -> cached_props -> colormap_windows_index &&
  245.     evt -> window == cw -> cached_props -> colormap_windows[
  246.                    cw -> cached_props -> colormap_windows_index]
  247.     && evt -> new)
  248.     if (evt -> colormap)
  249.         XInstallColormap(dpy, evt -> colormap);
  250.     else
  251.         XInstallColormap(dpy, Context->rootWob -> colormap);
  252. }
  253.  
  254. /* declare accepted icons sizes for future clients
  255.  */
  256.  
  257. WOOL_OBJECT
  258. wool_set_wm_icon_sizes(argc, argv)
  259. int     argc;
  260. WOOL_Number argv[];
  261. {
  262.     int i;
  263.     XIconSize    icon_sizes;
  264.  
  265.     if(argc != 6)
  266.     return wool_error(BAD_NUMBER_OF_ARGS, argc);
  267.     for(i=0;i<6;i++){
  268.     must_be_number(argv[i], i);
  269.     }
  270.     icon_sizes.min_width = argv[0] -> number;
  271.     icon_sizes.min_height = argv[1] -> number;
  272.     icon_sizes.max_width = argv[2] -> number;
  273.     icon_sizes.max_height = argv[3] -> number;
  274.     icon_sizes.width_inc = argv[4] -> number;
  275.     icon_sizes.height_inc = argv[5] -> number;
  276.     XSetIconSizes(dpy, Context->root, &icon_sizes, 6);
  277.     return NIL;
  278. }
  279.  
  280. /* get WM_COMMAND
  281.  */
  282.  
  283. WOOL_OBJECT
  284. wool_get_wm_command()
  285. {
  286.     Atom actual_type;
  287.     int actual_format = 0;
  288.     unsigned long nitems = 0L, leftover = 0L;
  289.     unsigned char *prop = NULL;
  290.     WOOL_List list;
  291.     int i, nstrings = 0, n;
  292.     unsigned char *p;
  293.  
  294.     if (XGetWindowProperty (dpy, TargetWindow -> client, XA_WM_COMMAND,
  295.                 0L, 1000000L, False,
  296.                 AnyPropertyType, &actual_type, &actual_format,
  297.                 &nitems, &leftover, &prop) == Success &&
  298.     actual_type != None && prop && nitems) {
  299.     for (i = 0; i < nitems; i++)
  300.         if (prop[i] == '\0')
  301.         nstrings ++;
  302.     list = wool_list_make(nstrings);
  303.     p = prop;
  304.     for (n = 0; n < nstrings; n++) {
  305.         increase_reference(list -> list[n] =
  306.                    (WOOL_OBJECT) WLString_make(p));
  307.         while(*p++);
  308.     }
  309.     XFree(prop);
  310.     return (WOOL_OBJECT) list;
  311.     }
  312.  
  313.     return NIL;
  314.  
  315. }
  316.  
  317. /* When not-yet mapped configures its window, we must execute the 
  318.  * configure request!
  319.  */
  320.  
  321. ConfigureUnmappedWindow(evt)
  322. XConfigureRequestEvent    *evt;
  323. {
  324.     XWindowChanges    window_changes;
  325.  
  326.     window_changes.x = evt -> x;
  327.     window_changes.y = evt -> y;
  328.     window_changes.width = evt -> width;
  329.     window_changes.height = evt -> height;
  330.     window_changes.border_width = evt -> border_width;
  331.     window_changes.sibling = evt -> above;
  332.     window_changes.stack_mode = evt -> detail;
  333.  
  334.     TrapXErrors(XConfigureWindow(dpy,
  335.                  evt -> window, evt -> value_mask,
  336.                  &window_changes));
  337. }
  338.  
  339. /* PROTOCOLS communication via user events
  340.  */
  341.  
  342. send_protocol_message(window, protocol, timestamp, data_size, data)
  343. Window    window;
  344. Atom       protocol;
  345. Time     timestamp;            /* 0 for CurrentTime */
  346. int     data_size;            /* 0 to 3 32-bit quantities */
  347. Card32 *data;
  348. {
  349.     XClientMessageEvent event;
  350.  
  351.     event.type = ClientMessage;
  352.     event.window = window;
  353.     event.message_type = XA_WM_PROTOCOLS;
  354.     event.format = 32;
  355.     event.data.l[0] = (long) protocol;
  356.     if (timestamp)
  357.     event.data.l[1] = (long) timestamp;
  358.     else
  359.     event.data.l[1] = (long) CurrentTime;
  360.     data_size = Min(3, data_size);
  361.     if (data_size)
  362.     bcopy(data, &(event.data.l[2]), data_size * 4);
  363.     if (data_size < 3)
  364.     bzero(&(event.data.l[2 + data_size]), (3 - data_size) * 4);
  365.  
  366.     TrapXErrors(XSendEvent(dpy, window, False, 0, (XEvent *) &event));
  367. }
  368.  
  369. /* WM_DELETE_WINDOW
  370.  * if window participate in protocol, sends message and returns TRUE
  371.  * else unmaps it and its associated icon (go to withdrawn) and returns NIL
  372.  */
  373.  
  374. WOOL_OBJECT
  375. wool_delete_window(argc, argv)
  376. int argc;
  377. WOOL_Number *argv;
  378. {
  379.     ClientWindow    cw = TargetWindow -> window;
  380.  
  381.     if (argc) {
  382.     must_be_number(argv[0], 0);
  383.     cw = ((ClientWindow) argv[0] -> number) -> window;
  384.     }
  385.     if (cw -> client
  386.     && cw -> cached_props -> wm_delete_window) {
  387.     send_protocol_message(cw -> client, XA_WM_DELETE_WINDOW,
  388.                   GWMTime, 0, 0);
  389.     return TRU;
  390.     } else {
  391.     return NIL;
  392.     }
  393. }
  394.  
  395. /* WM_SAVE_YOURSELF
  396.  * if window participate in protocol, sends message and returns TRUE
  397.  * else returns NIL
  398.  */
  399.  
  400. WOOL_OBJECT
  401. wool_save_yourself(argc, argv)
  402. int argc;
  403. WOOL_Number *argv;
  404. {
  405.     ClientWindow    cw = TargetWindow -> window;
  406.  
  407.     if (argc) {
  408.     must_be_number(argv[0], 0);
  409.     cw = ((ClientWindow) argv[0] -> number) -> window;
  410.     }
  411.     if (cw -> client && !cw -> client_wob
  412.     && cw -> cached_props -> wm_save_yourself) {
  413.     send_protocol_message(cw -> client, XA_WM_SAVE_YOURSELF,
  414.                   GWMTime, 0, 0);
  415.     return TRU;
  416.     } else {
  417.     return NIL;
  418.     }
  419. }
  420.  
  421. /* Gravity: 123
  422.  *          456
  423.  *          789
  424.  * (Gravity - 1) % 3: x: 0 1 2
  425.  * (Gravity - 1) / 3: y: 0 1 2
  426.  * 1 is center, -1 is just client mustn't move
  427.  */
  428.  
  429. GetWinGravityHint(cw, xgrav, ygrav)
  430. ClientWindow    cw;
  431. int *xgrav, *ygrav;
  432. {
  433. #ifdef NOBASEDIMS
  434.     *xgrav = *ygrav = -1;
  435. #else /* NOBASEDIMS */
  436.     int grav = cw -> cached_props -> normal_hints.win_gravity;
  437.     if (cw -> cached_props -> normal_hints.flags & PWinGravity) {
  438.         if ((grav <= ForgetGravity) || (grav >= StaticGravity))
  439.             *xgrav = *ygrav = -1;
  440.         else {
  441.             *xgrav = (grav - 1) % 3;
  442.             *ygrav = (grav - 1) / 3;
  443.         }
  444.     } else {
  445.         *xgrav = *ygrav = 0;           /* NorthWest is default */
  446.     }
  447. #endif /* NOBASEDIMS */
  448. }
  449.   
  450.  
  451. /* obeys the Window Gravity hints
  452.  * direction is 1 on decoration, 0 on un-decoration
  453.  * adjusts in place the cw->box.x/y dims
  454.  */
  455.  
  456. ObeyWinGravityHint(cw, direction)
  457. ClientWindow    cw;
  458. int             direction;
  459. {
  460.     int x_gravity, y_gravity;
  461.     int x_offset, y_offset;
  462.  
  463. #ifdef NOBASEDIMS        /* old pre -R4 code */
  464.     if (!GWM_ProcessingExistingWindows
  465.     && !cw -> cached_props -> new_normal_hints) {
  466.     if (cw -> cached_props -> normal_hints.flags & USPosition) {
  467.         cw -> box.x = cw -> cached_props -> normal_hints.x;
  468.         cw -> box.y = cw -> cached_props -> normal_hints.y;
  469.     } else if (cw -> cached_props -> normal_hints.flags & PPosition) {
  470.         cw -> box.x = cw -> cached_props -> normal_hints.x;
  471.         cw -> box.y = cw -> cached_props -> normal_hints.y;
  472.     } 
  473.     }
  474. #endif /* NOBASEDIMS */
  475.  
  476.     GetWinGravityHint(cw, &x_gravity, &y_gravity);
  477.  
  478.     switch(x_gravity) {
  479.     case 0:            /* west */
  480.     x_offset = 0;
  481.     break;
  482. /*    I dont beleive in this. I think 1 means that it shouldn't move in */
  483. /*    this direction, like the default below. / aho@nada.kth.se 950302  */
  484. /*    case 1:    */        /* center */
  485. /*    x_offset =  cw -> old_inner_borderwidth - cw -> box.borderwidth */
  486. /*        + (cw -> inner_width - cw -> box.width)/2; */
  487. /*    break; */
  488.     case 2:            /* east */
  489.     x_offset = cw -> inner_width - cw -> box.width
  490.         + 2 * (cw -> old_inner_borderwidth - cw -> box.borderwidth);
  491.     break;
  492.     default:            /* client don't move */
  493.     x_offset = cw -> old_inner_borderwidth - cw -> inner_borderwidth
  494.         - cw -> inner_x - cw -> box.borderwidth;
  495.     }
  496.  
  497.     switch(y_gravity) {
  498.     case 0:            /* north */
  499.     y_offset = 0;
  500.     break;
  501. /*    I dont beleive in this. I think 1 means that it shouldn't move in */
  502. /*    this direction, like the default below. / aho@nada.kth.se 950302  */
  503. /*    case 1:    */        /* center */
  504. /*    y_offset = cw -> old_inner_borderwidth - cw -> box.borderwidth */
  505. /*        + (cw -> inner_height - cw -> box.height)/2; */
  506. /*    break; */
  507.     case 2:            /* south */
  508.     y_offset =  cw -> inner_height - cw -> box.height
  509.         + 2 * (cw -> old_inner_borderwidth - cw -> box.borderwidth);
  510.     break;
  511.     default:            /* client don't move */
  512.     y_offset = cw -> old_inner_borderwidth - cw -> inner_borderwidth
  513.         - cw -> inner_y - cw -> box.borderwidth;
  514.     }
  515.     trace1(6, "window 0x%x:" , cw->client);
  516.     trace2(6, "at %d, %d, offseted by:" , cw->box.x, cw->box.y);
  517.     trace2(6, " %d, %d\n" , x_offset, y_offset);
  518.     cw->box.x += (direction ?  x_offset : - x_offset);
  519.     cw->box.y += (direction ?  y_offset : - y_offset);
  520. }
  521.  
  522.  
  523.     
  524. /* misc utilities */
  525.  
  526. /* replaces ., blanks,  and * by _ for using as class in Xrm
  527.  * returns arg if not changed, new string if changed so as not to modify
  528.  * the original string
  529.  */
  530.  
  531. WOOL_OBJECT
  532. MakeResourceIdentifier(string)
  533. WOOL_String string;
  534. {
  535.     char *p;
  536.     WOOL_String new_string = 0;
  537.  
  538.     must_be_string(string, 1);
  539.     for (p = string->string; *p; p++)
  540.     if (*p == '.' || *p == '*' || *p == ' ' || *p == '\t') {
  541.         if (!new_string)
  542.         new_string = WLString_make(string->string);
  543.         new_string->string[p - string->string] = '_';
  544.     }
  545.  
  546.     if (new_string)
  547.     return (WOOL_OBJECT) new_string;
  548.     else
  549.     return (WOOL_OBJECT) string;
  550. }
  551.  
  552. /* create an unmapped window whose ID is stored on the root window of each
  553.  * managed screen in the GWM_RUNNING property
  554.  * current screen is given in the context
  555.  */
  556.  
  557. CreateGwmLabelWindow()
  558. {
  559.     XSetWindowAttributes wa;
  560.  
  561.  
  562.     wa.override_redirect = True;
  563.     Context->GwmWindow = XCreateWindow (dpy, Context->root, 
  564.                     -100, -100, 10, 10, 0, 0,
  565.                     InputOnly, CopyFromParent,
  566.                     CWOverrideRedirect,
  567.                     &wa);
  568.     XChangeProperty(dpy, Context->root, XA_GWM_RUNNING, XA_GWM_RUNNING,
  569.     32, PropModeReplace, (unsigned char *) &(Context->GwmWindow), 1);
  570.     XChangeProperty(dpy, Context->GwmWindow, XA_GWM_RUNNING, XA_GWM_RUNNING,
  571.     32, PropModeReplace, (unsigned char *) &(Context->GwmWindow), 1);
  572. }
  573.  
  574. /* FindToplevelWindow
  575.  * given a window, move back in hierarchy to return the toplevel one
  576.  * If given root, returns 0
  577.  */
  578.  
  579. Window
  580. FindToplevelWindow(w)
  581.     Window w;
  582. {
  583.     Window parent = 0;
  584.     Window         *children;        /* list of root sons */
  585.     unsigned int    nchildren;        /* number of children */
  586.     Window root;
  587.  
  588.     if (w == Context->root) {
  589.     return 0;
  590.     }
  591.     
  592.     for (;;) {
  593.     if(!XQueryTree(dpy, w, &root, &parent, &children, &nchildren)) {
  594.         return 0;            /* failed */
  595.     }
  596.     XFreeN(children);
  597.     if (parent == Context->root) {
  598.         return w;
  599.     }
  600.     w = parent;
  601.     }
  602. }
  603.  
  604. /* IsAToplevelWindow
  605.  * Examine a non-gwm decorated window to see if it is legal to decorate it
  606.  */
  607.  
  608. int 
  609. IsAToplevelWindow(w)
  610.     Window w;
  611. {
  612.     Window          dummywin, parent;    /* dummy parent */
  613.     Window         *children;        /* list of root sons */
  614.     unsigned int    nchildren;        /* number of children */
  615.  
  616.     if (XQueryTree(dpy, w, &dummywin, &parent, &children, &nchildren)) {
  617.     XFreeN(children);
  618.     if (parent == Context -> root) { /* w is son of root, OK */
  619.         return 1;
  620.     }
  621.     }                    /* then not valid! */
  622.     return 0;
  623. }
  624.  
  625. /* ClientWindowAncestorOfWindow
  626.  * looks into all the ancestors to eventually find a ClientWindow, which would
  627.  * be returned, or 0
  628.  */
  629.  
  630. ClientWindow
  631. ClientWindowAncestorOfWindow(w)
  632.     Window w;
  633. {
  634.     Window toplevel = FindToplevelWindow(w);
  635.     ClientWindow cw;
  636.     if (toplevel
  637.     && (cw = (ClientWindow) LookUpWob(toplevel))
  638.     && (cw -> status & ClientWindowStatus)) {
  639.     return cw;
  640.     } else {
  641.     return 0;
  642.     }
  643. }
  644.  
  645. /* DecoratedWindow
  646.  * given a X window, returns the GWM window associated to, decorating it in
  647.  * the process if needed.
  648.  * used to look for window group leaders and transient_for masters
  649.  * returns 0 if failed
  650.  */
  651.  
  652. ClientWindow
  653. DecoratedWindow(w)
  654.     Window w;
  655. {
  656.     ClientWindow tw;
  657.     ClientWindow cw = (ClientWindow) LookUpClient(w);
  658.     if (cw) {
  659.     return cw;
  660.     } else {
  661.     cw = (ClientWindow) LookUpWob(w);
  662.     if (cw) {
  663.         if (cw->status | ClientWindowStatus) {
  664.         return 0;
  665.         } else {
  666.         Window win = FindToplevelWindow(w);
  667.  
  668.         if (win) {
  669.             return (ClientWindow)
  670.             DecorateWindow(win, Context->rootWob, 1, 0);
  671.         } else {
  672.             return 0;
  673.         }            
  674.         }
  675.     } else if (tw = ClientWindowAncestorOfWindow(w)) {
  676.         return tw;        
  677.     } else if (IsAToplevelWindow(w)) {
  678.         cw = (ClientWindow) DecorateWindow(w, Context->rootWob, 1, 0);
  679.         return cw;
  680.     }
  681.     }
  682.     return 0;
  683. }
  684.