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

  1. /* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
  2.  * Copyright 1989 Massachusetts Institute of Technology
  3.  */
  4. /**************************************************************\
  5. *                                    *
  6. *     X11 BULL WINDOW MANAGER.                   *
  7. *                                    *
  8. *     MODULE FOR OPERATIONS THAT MAY BE CALLED FROM Lisp.    *
  9. *                                    *
  10. \**************************************************************/
  11.  
  12. /*  include  */
  13.  
  14. #include        "EXTERN.h"
  15. #include "wool.h"
  16. #include "wl_atom.h"
  17. #include "gwm.h"
  18. #include "wl_number.h"
  19. #include "wl_string.h"
  20. #include "wl_client.h"
  21. #include "wl_menu.h"
  22. #include "wl_name.h"
  23. #include "wl_event.h"
  24. #include "wl_pixmap.h"
  25.  
  26. /*  local constants  */
  27.  
  28. /*  external  */
  29.  
  30. extern XError(), NoXError();
  31. extern WOB_METHOD ClientWindowClass[];
  32. extern WOOL_OBJECT UserMoveWindow(), UserResizeWindow();
  33. extern WOOL_OBJECT UserMoveSeveralWindows();
  34. extern WOOL_OBJECT MwmLikeUserResizeWindow();
  35. extern ClientWindow ClientWindowLeader();
  36.  
  37. /*  routines  */
  38.  
  39. char *NoRootError="Window function called on root window%s";
  40. #define NoRoot(w) ((w)->status != RootStatus ? (w) : \
  41.            (wool_error(NoRootError, ""),w))
  42.  
  43. /*
  44.  * GetTarget returns window having status in ancestors of current wob
  45.  */
  46.  
  47. Wob
  48. GetTarget(flag)
  49. unsigned long   flag;
  50. {
  51.     Wob             wob = TargetWob;
  52.  
  53.     while ((wob -> parent != NULL) && (wob -> status & flag) == 0)
  54.     wob = wob -> parent;
  55.     return wob;
  56. }
  57.  
  58. /*
  59.  * SetTarget makes TargetWob, TargetWindow and Context
  60.  */
  61.  
  62. SetTarget(wob)
  63. Wob   wob;
  64. {
  65.     extern WOOL_Namespace ContextNamespace;
  66.  
  67.     TargetWob = wob;
  68.     while (!(wob -> status & (TargetWindowStatus)))
  69.     wob = wob -> parent;
  70.     TargetWindow = (ClientWindow) wob;
  71.     Context = TargetWindow -> screen;
  72.     ContextNamespace -> current = Context -> screen;
  73. }
  74.  
  75. WOOL_OBJECT
  76. MapWindow(argc, argv)
  77. int argc;
  78. WOOL_Number argv[];
  79. {
  80.     ClientWindow    cw;
  81.  
  82.     if (argc)
  83.     cw = (ClientWindow) argv[0] -> number;
  84.     else
  85.     cw = TargetWindow;
  86.     ClientWindowMap(cw);
  87.     return NIL;
  88. }
  89.  
  90. WOOL_OBJECT
  91. UnmapWindow(argc, argv)
  92. int argc;
  93. WOOL_Number argv[];
  94. {
  95.     ClientWindow    cw;
  96.  
  97.     if (argc)
  98.     cw = (ClientWindow) argv[0] -> number;
  99.     else
  100.     cw = TargetWindow;
  101.     ClientWindowUnmap(cw);
  102.     return NIL;
  103. }
  104.  
  105. WOOL_OBJECT
  106. IconifyWindow()
  107. {
  108.     if (TargetWindow) {
  109.     if (TargetWindow -> mapped) {
  110.         XUnmapWindow(dpy, TargetWindow -> hook);
  111.         if (TargetWindow -> client && !TargetWindow -> client_wob)
  112.         XUnmapWindow(dpy, TargetWindow -> client);
  113.         TargetWindow -> mapped = 0;
  114.     }
  115.     if (TargetWindow -> status & IconStatus) {    /* de-iconify */
  116.         SetTarget(TargetWindow -> window);
  117.     } else {            /* iconify */
  118.         if (!(TargetWindow -> icon)) {
  119.         if (!RealizeIconWindow(TargetWindow)) {
  120.             ClientWindowMap(TargetWindow);
  121.             wool_error("Error in wool code for decorating icon %s",
  122.                    ((WOOL_String) 
  123.                 TargetWindow->cached_props->iconname)->string);
  124.             return NIL;
  125.         }
  126.         }
  127.         SetTarget(TargetWindow -> icon);
  128.     }
  129.     ClientWindowMap(TargetWindow);
  130.     }
  131.     return NIL;
  132. }
  133.  
  134. /* move window returns () if Ok, else:
  135.  *    0 if X problem with server/window
  136.  *     1 if pointer was not on screen
  137.  *     2 if user cancelled move
  138.  *    3 if button was released before entering function
  139.  */
  140.  
  141. WOOL_OBJECT
  142. MoveSeveralWindows(argc, argv)
  143.     int       argc;
  144.     WOOL_Number argv[];
  145. {
  146.     ClientWindow cwl[255];
  147.     int       i;
  148.  
  149.     for (i = 0; i < argc; i++) {
  150.     must_be_number(argv[i], i);
  151.     cwl[i] = (ClientWindow) argv[i]->number;
  152.     }
  153.     return UserMoveSeveralWindows(argc, cwl);
  154. }
  155.  
  156.  
  157. WOOL_OBJECT
  158. MoveWindow(argc, argv)
  159. int argc;
  160. WOOL_Number argv[];
  161. {
  162.     int i;
  163.     ClientWindow    cw = TargetWindow;
  164.  
  165.     for(i=0; i< argc; i++)        /* MOVE HOOK */
  166.     must_be_number(argv[i], i);
  167.     switch (argc) {
  168.     case 1:
  169.         cw = (ClientWindow) argv[0] -> number;
  170.     case 0:
  171.     return UserMoveWindow(cw);
  172.     break;
  173.     case 2:
  174.     XMoveWindow(dpy, TargetWindow -> hook,
  175.             TargetWindow -> box.x = argv[0] -> number,
  176.             TargetWindow -> box.y = argv[1] -> number);
  177.     SendSyntheticMoveEvent(TargetWindow);
  178.     break;
  179.     default:
  180.     XMoveWindow(dpy, ((Wob) (argv[0] -> number)) -> hook,
  181.             ((Wob) (argv[0] -> number)) -> box.x = argv[1] -> number,
  182.             ((Wob) (argv[0] -> number)) -> box.y = argv[2] -> number);
  183.     SendSyntheticMoveEvent(argv[0] -> number);
  184.     break;
  185.     }
  186.     return NIL;
  187. }
  188.  
  189. /* resize window returns () if Ok, else:
  190.  *    0 if X problem with server/window
  191.  *      1 if pointer was not on screen
  192.  *      2 if user cancelled resize
  193.  *    3 if button was released before entering function
  194.  */
  195.  
  196. WOOL_OBJECT
  197. ResizeWindow(argc, argv)
  198. int argc;
  199. WOOL_Number argv[];
  200. {
  201.     int             width, height;
  202.     int i;
  203.     ClientWindow    cw = TargetWindow;
  204.  
  205.     for(i=0; i< argc; i++)
  206.     must_be_number(argv[i], i);
  207.     switch (argc) {
  208.     case 1:
  209.     cw = (ClientWindow) argv[0] -> number;
  210.     case 0:
  211.     if (cw -> client)
  212.         if (GWM_resize_style)
  213.         return MwmLikeUserResizeWindow(cw);
  214.         else
  215.             return UserResizeWindow(cw);
  216.     break;
  217.     case 2:
  218.     if (TargetWindow -> client)
  219.         width = argv[0] -> number;
  220.     height = argv[1] -> number;
  221.     dims_outer_to_inner(TargetWindow, &width, &height);
  222.     conform_to_hints(&(TargetWindow -> cached_props -> normal_hints),
  223.              &width, &height);
  224.     XResizeWindow(dpy, TargetWindow -> client, width, height);
  225.     ReconfigureClientWindow(TargetWindow, TargetWindow -> client);
  226.     break;
  227.     default:
  228.     if (!(cw = ((ClientWindow) argv[0] -> number)) -> client)
  229.         return NIL;
  230.     width = argv[1] -> number;
  231.     height = argv[2] -> number;
  232.     dims_outer_to_inner(cw, &width, &height);
  233.     conform_to_hints(&(cw -> cached_props -> normal_hints), 
  234.              &width, &height);
  235.     XResizeWindow(dpy, cw -> client, width, height);
  236.         ReconfigureClientWindow(cw, cw -> client);
  237.     break;
  238.     }
  239.     return NIL;
  240. }
  241.  
  242. /*
  243.  * Raise window (optionally % other top-level window)
  244.  */
  245.  
  246. WOOL_OBJECT
  247. RaiseWindow(argc, argv)
  248. int argc;
  249. WOOL_Number argv[];
  250. {
  251.     XWindowChanges values;
  252.  
  253.     switch (argc) {
  254.     case 0:
  255.     XRaiseWindow(dpy, TargetWindow -> hook);
  256.     break;
  257.     case 1:
  258.     must_be_number(argv[0], 0);
  259.     values.sibling = ((Wob) (argv[0] -> number)) -> hook;
  260.     values.stack_mode = Above;
  261.     XConfigureWindow(dpy, TargetWindow -> hook,
  262.              CWStackMode | CWSibling, &values);
  263.     break;
  264.     }
  265.     return NIL;
  266. }
  267.  
  268. /*
  269.  * Lower window (optionally % other top-level window)
  270.  */
  271.  
  272. WOOL_OBJECT
  273. LowerWindow(argc, argv)
  274. int argc;
  275. WOOL_Number argv[];
  276. {
  277.     XWindowChanges values;
  278.  
  279.     switch (argc) {
  280.     case 0:
  281.     XLowerWindow(dpy, TargetWindow -> hook);
  282.     break;
  283.     case 1:
  284.         must_be_number(argv[0], 0);
  285.         values.sibling = ((Wob) (argv[0] -> number)) -> hook;
  286.         values.stack_mode = Below;
  287.         XConfigureWindow(dpy, TargetWindow -> hook,
  288.                          CWStackMode | CWSibling, &values);
  289.     break;
  290.     }
  291.     return NIL;
  292. }
  293.  
  294. WOOL_OBJECT
  295. KillWindow(argc, argv)
  296. int argc;
  297. WOOL_Number argv[];
  298. {
  299.     ClientWindow    cw = TargetWindow;
  300.     Wob             wob;
  301.  
  302.     if (argc)
  303.     cw = (ClientWindow) argv[0] -> number;
  304.     /*  kill always main window, not icon! */
  305.     cw = cw -> window;
  306.     if (wob = (Wob) LookUpWob(cw -> client))
  307.     WOOL_send(WOOL_close, wob, (wob));    /* don't kill gwm! */
  308.     else if (cw -> client)
  309.     XKillClient(dpy, cw -> client);
  310.     return NIL;
  311. }
  312.  
  313. WOOL_OBJECT
  314. ReDecorateWindow(argc, argv)
  315. int argc;
  316. WOOL_Number argv[];
  317. {
  318.     ClientWindow    cw = TargetWindow;
  319.     int             new_target = 0;
  320.     int             was_mapped;
  321.     Window        window;
  322.     WOOL_List       window_group;
  323.  
  324.     if (argc)
  325.     cw = (ClientWindow) (argv[0] -> number);
  326.     if (cw && cw -> type == ClientWindowClass) {
  327.     GWM_ProcessingExistingWindows = 1;
  328.     if (cw == TargetWindow)
  329.         new_target = 1;
  330.     cw = cw -> window;
  331.     window = cw -> client;
  332.     if (was_mapped = cw -> mapped)
  333.         ClientWindowUnmap(cw);
  334.     SetTarget(cw);
  335.     if (cw == ClientWindowLeader(cw)) {
  336.         increase_reference(window_group =
  337.                    (WOOL_List) wool_window_group_get());
  338.     } else {
  339.         window_group = 0;
  340.     }
  341.     UnDecorateWindow(cw, 1, 1);
  342.     if (cw = (ClientWindow) DecorateWindow(window,
  343.                            Context->rootWob, 1, 1)) {
  344.         if (was_mapped) {
  345.         ClientWindowMap(cw);
  346.         wool_process_unmap_events(window);
  347.         } else {
  348.         ClientWindowInitialMap(cw);
  349.         }
  350.         if (window_group && window_group != (WOOL_List) NIL) {
  351.         int i;
  352.         for (i=1; i<window_group->size; i++) {
  353.             AddWindowToGroupLeader(
  354.                       ((WOOL_Number)window_group->list[i])
  355.                        ->number, cw);
  356.         }
  357.         }
  358.         GWM_ProcessingExistingWindows = 0;
  359.         if (new_target)
  360.         SetTarget(cw);
  361.         return (WOOL_OBJECT) WLNumber_make(cw);
  362.     } else {
  363.         XMapWindow(dpy, window);
  364.     }
  365.     decrease_reference(window_group);
  366.     }
  367.     return NIL;
  368. }
  369.  
  370. /* returns NIL if OK
  371.  * (pop-up [menu [item]])
  372.  * if menu = () takes default
  373.  * item is the nth item in the menu (starting with 0).
  374.  * If pointer is not on screen, do nothing and returns 0
  375.  * if cannot grab, returns 1, Ok= ()
  376.  * returns pointer (modifier + buttons status) mask
  377.  */
  378.  
  379. WOOL_OBJECT
  380. PopMenu(argc, argv)
  381. int argc;
  382. WOOL_Menu argv[];
  383. {
  384.     WOOL_Menu       wl_menu = (WOOL_Menu) TargetWob -> menu;
  385.     int             x, y, rx, ry, item = 0, i;
  386.     Window          root, child;
  387.     Menu            menu;
  388.     int             floating = 1;
  389.     unsigned int    mask;
  390.  
  391.  
  392.     for (i = 0; i < argc; i++) {
  393.     if (argv[i] -> type == WLNumber)
  394.         item = ((WOOL_Number) argv[i]) -> number;
  395.     else if (argv[i] -> type == WLMenu)
  396.         wl_menu = argv[i];
  397.     else if (argv[i] == (WOOL_Menu) WA_here)
  398.         floating = 0;
  399.     }
  400.     menu = wl_menu -> wob_menu;
  401.     set_grab(Context -> rootWob);
  402.     XQueryPointer(dpy, Context -> root, &root, &child,
  403.           &x, &y, &rx, &ry, &mask);
  404.     if (root == Context -> root) {
  405.     if (floating) {
  406.         PlaceMenu(item, menu, x, y, TargetWob);
  407.         XMoveWindow(dpy, menu -> hook, menu -> box.x, menu -> box.y);
  408.     }
  409.     XMapRaised(dpy, menu -> hook);
  410.     if (NIL == set_grab(menu)) {    /* ok */
  411.         XSync(dpy, 0);
  412.         wool_process_exposes();
  413.         menu -> parent = (TargetWob == (Wob) menu
  414.                   ? (Wob) Context -> rootWob :TargetWob) ;
  415.         return NIL;
  416.     } else {            /* grab failed */
  417.         remove_grab(0);
  418.         XUnmapWindow(dpy, menu -> hook);
  419.         return (WOOL_OBJECT) WLNumber_make(1);
  420.     }
  421.     } else {                /* not good screen */
  422.     remove_grab(0);
  423.     return (WOOL_OBJECT) WLNumber_make(0);
  424.     }
  425. }
  426.  
  427. /* de-pop a menu previously popped by PopMenu
  428.  */
  429.  
  430. WOOL_OBJECT
  431. UnpopMenu(argc, argv)
  432. int argc;
  433. WOOL_Menu argv[];
  434. {
  435.     Menu            menu;
  436.     WOOL_Menu       wl_menu;
  437.  
  438.     menu = (Menu) GetTarget(MenuStatus);
  439.     if (argc) {
  440.     wl_menu = argv[0];
  441.     if (wl_menu == (WOOL_Menu) NIL)
  442.         return NIL;
  443.     if (wl_menu -> type == WLMenu)
  444.         menu = wl_menu -> wob_menu;
  445.     else
  446.         menu = (Menu) ((WOOL_Number) wl_menu) -> number;
  447.     }
  448.     remove_grab(menu);
  449.     XUnmapWindow(dpy, menu -> hook);
  450.     menu -> parent = (Wob) Context -> rootWob;
  451.     XSync(dpy, 0);
  452.     return (WOOL_OBJECT) WLNumber_make(menu);
  453. }
  454.  
  455. PlaceMenu(item, menu, x, y, wob)
  456. int     item;            /* item to place it */
  457. Menu    menu;            /* the menu */
  458. int    x,y;            /* mouse coordinates */
  459. Wob    wob;            /* triggering wob */
  460. {
  461.     int             oldx, oldy;
  462.     int             bw = 2 * menu -> box.borderwidth;
  463.  
  464.     if (item >= menu -> nbars)        /* if out put to last */
  465.     item = menu -> nbars - 1;
  466.     /* set pointer in item-th item */
  467.     oldx = menu -> box.x = x - menu -> box.width / 2;
  468.     oldy = menu -> box.y = y - (menu -> bars[item] -> box.y +
  469.                 menu -> bars[item] -> box.height / 2);
  470.     /* place full pop on screen */
  471.     if (menu -> box.x < 0)
  472.     menu -> box.x = 0;
  473.     if (menu -> box.y < 0)
  474.     menu -> box.y = 0;
  475.     if (menu -> box.x + menu -> box.width + bw > Context -> width)
  476.     menu -> box.x = Context -> width - menu -> box.width - bw;
  477.     if (menu -> box.y + menu -> box.height + bw > Context -> height)
  478.     menu -> box.y = Context -> height - menu -> box.height - bw;
  479.     if (!GWM_never_warp_pointer
  480.     && (menu -> box.x != oldx || menu -> box.y != oldy))
  481.     XWarpPointer(dpy, None, None, 0, 0, 0, 0,
  482.              menu -> box.x - oldx, menu -> box.y - oldy);
  483. }
  484.  
  485. WOOL_OBJECT
  486. CirculateWindowsDown()
  487. {
  488.     XCirculateSubwindowsDown(dpy, Context->root);
  489.     return NIL;
  490. }
  491.  
  492. WOOL_OBJECT
  493. CirculateWindowsUp()
  494. {
  495.     XCirculateSubwindowsUp(dpy, Context->root);
  496.     return NIL;
  497. }
  498.     
  499. /*
  500.  * the "current-window" functions
  501.  */
  502.  
  503. WOOL_OBJECT
  504. wool_current_window()
  505. {
  506.     if (TargetWindow)
  507.     return (WOOL_OBJECT) WLNumber_make(TargetWindow);
  508.     else
  509.     return NIL;
  510. }
  511.  
  512. WOOL_OBJECT
  513. wool_set_current_window(number)
  514. WOOL_Number     number;
  515. {
  516.     must_be_number(number, 0);
  517.     if (WobIsValid(number->number)
  518.     && (
  519.         (((Wob)(number->number))->type == ClientWindowClass)
  520.         || (((Wob)(number->number))->type == ScreenClass))) {
  521.     SetTarget(number -> number);
  522.     return (WOOL_OBJECT) number;
  523.     } else {
  524.         return wool_error(INTERNAL_ERROR, "Not a Window!");
  525.     }
  526. }
  527.  
  528. WOOL_OBJECT
  529. wool_current_window_is_mapped()
  530. {
  531.     if (TargetWindow -> mapped)
  532.     return TRU;
  533.     else
  534.     return NIL;
  535. }
  536.  
  537. WOOL_OBJECT
  538. wool_current_window_name()
  539. {
  540.     return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> windowname;
  541. }
  542.  
  543. WOOL_OBJECT
  544. wool_current_window_name_set(name)
  545. WOOL_String    name;
  546. {
  547.     XStoreName(dpy, NoRoot(TargetWindow) -> client, name -> string);
  548.     return (WOOL_OBJECT) name;
  549. }
  550.  
  551. WOOL_OBJECT
  552. wool_current_window_client_name()
  553. {
  554.     return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> clientname;
  555. }
  556.  
  557. WOOL_OBJECT
  558. wool_current_window_client_class()
  559. {
  560.     return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> clientclass;
  561. }
  562.  
  563. WOOL_OBJECT
  564. wool_current_window_machine_name()
  565. {
  566.     return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> machinename;
  567. }
  568.  
  569. WOOL_OBJECT
  570. wool_current_window_icon_name()
  571. {
  572.     return (WOOL_OBJECT) NoRoot(TargetWindow) -> cached_props -> iconname;
  573. }
  574.  
  575. WOOL_OBJECT
  576. wool_current_window_geometry(measure)
  577. int measure;
  578. {
  579.     Window          root;
  580.     unsigned int    measures[6];
  581.  
  582.     XGetGeometry(dpy, TargetWindow -> client,
  583.          &root, (int *)&measures[0], (int *)&measures[1], &measures[2],
  584.          &measures[3], &measures[4], &measures[5]);
  585.     return (WOOL_OBJECT) WLNumber_make(measures[measure]);
  586. }
  587.  
  588. /* sets Context to those of the root of a window */
  589.  
  590. int
  591. ContextOfXWindow(window)
  592. Window window;
  593. {
  594.     Window          root;
  595.     unsigned int     measures[6];
  596.     int result;
  597.  
  598.     XSetErrorHandler(NoXError);
  599.     result = XGetGeometry(dpy, window,
  600.                  &root, (int *)&measures[0], (int *)&measures[1], &measures[2],
  601.                  &measures[3], &measures[4], &measures[5]);
  602.     XSync(dpy, 0);
  603.     XSetErrorHandler(XError);
  604.     if (!result) 
  605.     return result;
  606.     result = ScreenOfRoot(root);
  607.     if (result == -1)
  608.     return result;
  609.     SetTarget(GWMManagedScreens[result] -> rootWob);
  610.     return 0;
  611. }
  612.  
  613. WOOL_OBJECT
  614. wool_current_client_x()
  615. {
  616.     return wool_current_window_geometry(0);
  617. }
  618.  
  619. WOOL_OBJECT
  620. wool_current_client_y()
  621. {
  622.     return wool_current_window_geometry(1);
  623. }
  624.  
  625. WOOL_OBJECT
  626. wool_current_client_width()
  627. {
  628.     return wool_current_window_geometry(2);
  629. }
  630.  
  631. WOOL_OBJECT
  632. wool_current_client_height()
  633. {
  634.     return wool_current_window_geometry(3);
  635. }
  636.  
  637. WOOL_OBJECT
  638. wool_current_client_borderwidth()
  639. {
  640.     return wool_current_window_geometry(4);
  641. }
  642.  
  643. WOOL_OBJECT
  644. wool_current_window_x()
  645. {
  646.     return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.x);
  647. }
  648.  
  649. WOOL_OBJECT
  650. wool_current_window_y()
  651. {
  652.     return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.y);
  653. }
  654.  
  655. WOOL_OBJECT
  656. wool_current_window_width()
  657. {
  658.     return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.width);
  659. }
  660.  
  661. WOOL_OBJECT
  662. wool_current_window_height()
  663. {
  664.     return (WOOL_OBJECT) WLNumber_make(TargetWindow -> box.height);
  665. }
  666.  
  667. /* returns client-managed icon window, if any, but first check that it exists
  668.  */
  669.  
  670. WOOL_OBJECT
  671. wool_current_window_icon_window()
  672. {
  673.     Window dummy_win;
  674.  
  675.     if (NoRoot(TargetWindow) -> cached_props -> wm_hints.flags
  676.     & IconWindowHint
  677.     && !TrapXErrors(XGetTransientForHint(dpy,
  678.          TargetWindow -> cached_props -> wm_hints.icon_window,
  679.                          &dummy_win))
  680.     ) {
  681.     return (WOOL_OBJECT) WLNumber_make(
  682.               TargetWindow -> cached_props -> wm_hints.icon_window);
  683.     }
  684.     return NIL;
  685. }
  686.  
  687. /* each time this function is called, construct the icon pixmap from the hints
  688.  * (this to allow for applications changing their icons and user to change
  689.  * color via the foreground and background variables)
  690.  */
  691.  
  692. WOOL_OBJECT
  693. wool_current_window_icon_bitmap()
  694. {
  695.     if (TargetWindow -> cached_props -> wm_hints.flags & IconPixmapHint) {
  696.     WOOL_Pixmap pixmap = WLPixmap_make(TargetWindow -> cached_props ->
  697.                     wm_hints.icon_pixmap);
  698.     if (TargetWindow -> cached_props -> wm_hints.flags & IconMaskHint) {
  699.           Window root;
  700.           int x_hot, y_hot;
  701.       unsigned int width, height, bw, depth;
  702.           GC gc;
  703.           Pixmap mask = TargetWindow -> cached_props -> wm_hints.icon_mask;
  704.           XGetGeometry(dpy, mask, &root, &x_hot, &y_hot,
  705.                        &width, &height, &bw, &depth);
  706.           pixmap -> mask = XCreatePixmap(dpy, root, width, height, depth);
  707.           gc = XCreateGC(dpy, pixmap -> mask, 0, 0);
  708.           XCopyArea(dpy, mask, pixmap -> mask, gc, 0, 0,
  709.                     width, height, 0, 0);
  710.     }
  711.     return (WOOL_OBJECT) pixmap;
  712.     } else {
  713.     return NIL;
  714.     }
  715. }
  716.  
  717. WOOL_OBJECT
  718. wool_current_window_icon_bitmap_id()
  719. {
  720.     if (TargetWindow -> cached_props -> wm_hints.flags & IconPixmapHint) {
  721.     return (WOOL_OBJECT) WLNumber_make(TargetWindow -> cached_props ->
  722.               wm_hints.icon_pixmap);
  723.     } else {
  724.     return NIL;
  725.     }
  726. }
  727.  
  728. WOOL_OBJECT
  729. wool_current_window_US_position()
  730. {
  731.     if (NoRoot(TargetWindow) -> status & IconStatus) {
  732.     if (TargetWindow -> cached_props -> wm_hints.flags & IconPositionHint)
  733.         return TRU;
  734.     } else {
  735.     if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags
  736.         & USPosition)
  737.         return TRU;
  738.     }
  739.     return NIL;
  740. }
  741.  
  742. WOOL_OBJECT
  743. wool_current_window_US_size()
  744. {
  745.     if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags 
  746.       & USSize)
  747.     return TRU;
  748.     else
  749.     return NIL;
  750. }
  751.  
  752. WOOL_OBJECT
  753. wool_current_window_P_position()
  754. {
  755.    if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags
  756.        & PPosition)
  757.      return TRU;
  758.    else
  759.      return NIL;
  760. }
  761.  
  762. WOOL_OBJECT
  763. wool_current_window_P_size()
  764. {
  765.     if (TargetWindow && TargetWindow -> cached_props -> normal_hints.flags 
  766.       & PSize)
  767.     return TRU;
  768.     else
  769.     return NIL;
  770. }
  771.  
  772. WOOL_OBJECT
  773. wool_current_window_is_transient_for()
  774. {
  775.     if (NoRoot(TargetWindow) 
  776.     && TargetWindow -> cached_props -> transient_for) {
  777.     return TargetWindow -> cached_props -> transient_for;
  778.     } else {
  779.     return NIL;
  780.     }
  781. }
  782.  
  783. WOOL_OBJECT
  784. wool_window_map_as_icon_get()
  785. {
  786.     if ((TargetWindow && TargetWindow -> cached_props -> wm_hints.flags
  787.      & StateHint)
  788.     && (TargetWindow -> cached_props -> wm_hints.initial_state == 3))
  789.     return TRU;
  790.     else
  791.     return NIL;
  792. }
  793.  
  794. WOOL_OBJECT
  795. wool_window_map_as_icon_set(flag)
  796. WOOL_OBJECT    flag;
  797. {
  798.     if (TargetWindow) {
  799.     TargetWindow -> cached_props -> wm_hints.flags |= StateHint;
  800.     TargetWindow -> cached_props -> wm_hints.initial_state
  801.         = (flag == NIL ? 1 : 3);
  802.     }
  803.     return flag;
  804. }
  805.  
  806. /*
  807.  * set focus on
  808.  *     current client if no arg (do nothing if input hint is false)
  809.  *     other window's client if arg
  810.  *     if arg = NIL, rootwindow
  811.  */
  812.  
  813. WOOL_OBJECT
  814. wool_set_focus(argc, argv)
  815. int    argc;
  816. WOOL_Number    argv[];
  817. {
  818.     ClientWindow    cw = TargetWindow;
  819.  
  820.     if (!cw)
  821.     return NIL;
  822.     if (argc) {
  823.     if (argv[0] == (WOOL_Number) NIL) {
  824.         XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
  825.                CurrentTime);
  826.         return TRU;
  827.     } else {
  828.         cw = (ClientWindow) argv[0] -> number;
  829.     }
  830.     }
  831.     if (GWM_No_set_focus)
  832.     return NIL;
  833.     if (GWM_check_input_focus_flag
  834.     || ((cw -> cached_props -> wm_hints.flags & InputHint)
  835.         &&
  836.         (cw -> cached_props -> wm_hints.input) && cw -> client)) {
  837.     TrapXErrors(XSetInputFocus(dpy, cw -> client, RevertToPointerRoot,
  838.                    CurrentTime));
  839.     } 
  840.     if (cw -> type == ClientWindowClass) {
  841.     if (cw -> cached_props -> wm_take_focus) {
  842.         send_protocol_message(cw -> client, XA_WM_TAKE_FOCUS,
  843.                   GWMTime, 0, 0);
  844.          if ((cw -> cached_props ->wm_hints.flags & InputHint) &&
  845.         (cw -> cached_props -> wm_hints.input)) {
  846.         TrapXErrors(XSetInputFocus(dpy, cw -> client,
  847.                        RevertToPointerRoot, CurrentTime));
  848.          }
  849.     }
  850.     } else {
  851.     TrapXErrors(XSetInputFocus(dpy, cw -> hook, RevertToPointerRoot,
  852.                    CurrentTime));
  853.     }
  854.     return TRU;
  855. }
  856.  
  857. /*
  858.  * returns [x y modifiers screen]
  859.  */
  860.  
  861. WOOL_OBJECT
  862. wool_current_mouse_position()
  863. {
  864.     unsigned int    ptrmask;    /* state of ptr when queried */
  865.     Window          root, sub_window;
  866.     int             root_x, root_y, cur_x, cur_y;
  867.     WOOL_List        wl_list = wool_list_make(4);
  868.  
  869.     root=0;
  870.     XQueryPointer(dpy,
  871.           Context->root, &root, &sub_window,
  872.           &root_x, &root_y, &cur_x, &cur_y, &ptrmask);
  873.     increase_reference(wl_list -> list[0] = (WOOL_OBJECT)
  874.     WLNumber_make(cur_x));
  875.     increase_reference(wl_list -> list[1] = (WOOL_OBJECT)
  876.     WLNumber_make(cur_y));
  877.     increase_reference(wl_list -> list[2] = (WOOL_OBJECT)
  878.     WLNumber_make(ptrmask));
  879.     increase_reference(wl_list -> list[3] = (WOOL_OBJECT)
  880.         (root ? WLNumber_make(ScreenOfRoot(root))
  881.           : WLNumber_make(0)));
  882.     return (WOOL_OBJECT) wl_list;
  883. }
  884.  
  885. /* warps pointer to pos
  886.  * (warp-pointer x y [window-relative-to])
  887.  */
  888.  
  889. WOOL_OBJECT
  890. wool_warp_pointer(argc, argv)
  891. int        argc;
  892. WOOL_Number    argv[];
  893. {
  894.     Window          dest_w = None;
  895.  
  896.     if (argc < 2 || argc > 3)
  897.     wool_error(BAD_NUMBER_OF_ARGS, argc);
  898.     must_be_number(argv[0], 0);
  899.     must_be_number(argv[1], 1);
  900.     if (argc == 3) {
  901.     must_be_number(argv[2], 2);
  902.     dest_w = ((Wob) (argv[2] -> number)) -> hook;
  903.     }
  904.     if (!GWM_never_warp_pointer) {
  905.     XWarpPointer(dpy, None, dest_w,
  906.              0, 0, 0, 0, argv[0] -> number, argv[1] -> number);
  907.     }
  908.     return NIL;
  909. }
  910.  
  911. /*
  912.  * logical size of a window is size divided by resize increments (+ base)
  913.  */
  914.  
  915. WOOL_OBJECT
  916. wool_window_logical_size_get()
  917. {
  918.     WOOL_List       wl_list = wool_list_make(2);
  919.     unsigned int    w = 0, h = 0;
  920.  
  921.     if (TargetWindow -> client) {
  922.     pixel_to_logical_size(&(TargetWindow -> cached_props -> normal_hints),
  923.      TargetWindow -> inner_width, TargetWindow -> inner_height, &w, &h);
  924.     }
  925.     increase_reference(wl_list -> list[0] = (WOOL_OBJECT) WLNumber_make(w));
  926.     increase_reference(wl_list -> list[1] = (WOOL_OBJECT) WLNumber_make(h));
  927.     return (WOOL_OBJECT) wl_list;
  928. }
  929.  
  930. WOOL_OBJECT
  931. wool_window_logical_size_set(list)
  932. WOOL_List    list;
  933. {
  934.     unsigned int    w, h;
  935.  
  936.     if (list -> type != WLList || list == (WOOL_List) NIL || list -> size != 2
  937.     || list -> list[0] -> type != WLNumber
  938.     || list -> list[1] -> type != WLNumber)
  939.     bad_argument(list, 0, "list of two numbers");
  940.     logical_to_pixel_size(&(TargetWindow -> cached_props -> normal_hints),
  941.               ((WOOL_Number) list -> list[0]) -> number,
  942.               ((WOOL_Number) list -> list[1]) -> number,
  943.               &w, &h);
  944.     XResizeWindow(dpy, TargetWindow -> client, w, h);
  945.     ReconfigureClientWindow(TargetWindow, TargetWindow -> client);
  946.     return NIL;
  947. }
  948.  
  949. /* moves a window at x,y and gravity
  950.  * WARNING: xpt & yptr are pointers on SHORTS
  951.  */
  952.  
  953. PlaceWinWithGravity(w, gravity, anchor_x, anchor_y, xptr, yptr, width, height, 
  954.             borderwidth)
  955. Window  w;
  956. int     gravity, anchor_x, anchor_y;
  957. short   *xptr, *yptr;
  958. unsigned int width, height, borderwidth;
  959. {
  960.     int x = *xptr, y = *yptr;
  961.  
  962.     switch((gravity - 1) % 3) {
  963.     case 0:
  964.     x = anchor_x;
  965.     break;
  966.     case 1:
  967.     x = anchor_x - width/2 - borderwidth;
  968.     break;
  969.     case 2:
  970.     x = anchor_x - width - 2*borderwidth;
  971.     break;
  972.     }
  973.     switch((gravity - 1) / 3) {
  974.     case 0:
  975.     y = anchor_y;
  976.     break;
  977.     case 1:
  978.     y = anchor_y - height/2 - borderwidth;
  979.     break;
  980.     case 2:
  981.     y = anchor_y - height - 2*borderwidth;
  982.     break;
  983.     }
  984.     if (*xptr != x || *yptr != y) {
  985.     *xptr = x;
  986.     *yptr = y;
  987.     XMoveWindow(dpy, w, x, y);
  988.     }
  989. }
  990.