home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gwm18a.zip / bar.c < prev    next >
C/C++ Source or Header  |  1995-07-03  |  22KB  |  674 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 Bar Wob class.    *
  9. *                           *
  10. \*********************************************/
  11.  
  12.  /* include */
  13. #include    "EXTERN.h"
  14. #include    "wool.h"
  15. #include    "wl_atom.h"
  16. #include    "gwm.h"
  17. #include    "wl_fsm.h"
  18. #include    "wl_pixmap.h"
  19. #include    "wl_cursor.h"
  20. #include    "wl_bar.h"
  21.  
  22.  /* local constants */
  23.  
  24.  /* external */
  25. extern Wob      NewWob();
  26. extern Plug     NewPlug();
  27. extern WOOL_METHOD WLMenu[];
  28. extern Bar BarOpen();
  29. extern BarEventHandler(), BarClose(), UpdateBarGeometry(), ReconfigureBar();
  30.  
  31. #ifdef SHAPE            /* compile with -I/usr/include/X11 AND
  32.                    -I/usr/include/X11/extensions to work on
  33.                    machines having shapes.h in either place */
  34. #include    <shape.h>
  35. extern BarIsShaped(), UpdateBarShape();
  36. #define TileIsShaped(tile) \
  37.     (tile && (tile)->type == WLPixmap) && ((WOOL_Pixmap) (tile)) -> mask
  38.  
  39. #endif /* SHAPE */
  40.  
  41. WOB_METHOD       BarClass[] = {
  42.                   0,    /* METHODS_ARRAY */
  43.                   WobEval,
  44.                   WobPrint,
  45.                   WobRelease,
  46.                   WobExecute,
  47.                   WobSet,
  48.                   WobGetCValue,
  49.                   (WOB_METHOD) BarOpen,
  50.                   BarClose,
  51.                   BarEventHandler,
  52.                               (WOB_METHOD) wool_undefined_method_1,
  53.                   WobGetDimensions,
  54.                               (WOB_METHOD) wool_undefined_method_2,
  55.                               (WOB_METHOD) wool_undefined_method_2,
  56.                               ReconfigureBar,
  57.             (WOB_METHOD) wool_undefined_method_2,
  58.             (WOB_METHOD) wool_undefined_method_1,
  59.             (WOB_METHOD) wool_undefined_method_1,
  60.             (WOB_METHOD) wool_undefined_method_1,
  61.             (WOB_METHOD) wool_undefined_method_1,
  62.             (WOB_METHOD) wool_undefined_method_1
  63. };
  64.  
  65.  /* routines */
  66.  
  67. /*
  68.  * NewBar
  69.  * Creates a new bar object from a WOOL_Bar description
  70.  * Warning: a plug may be NULL to indicate an extensible space
  71.  */
  72.  
  73. Bar 
  74. NewBar(parent, wl_bar, dir)
  75. Wob                     parent;
  76. WOOL_Bar        wl_bar;
  77. short                   dir;
  78. {
  79.     Bar             bar = (Bar) NewWob(sizeof(struct _Bar)
  80.                + sizeof(Plug) * Max(0, (wl_bar -> plugs_size - 1)));
  81.     int             i;
  82.     WOOL_OBJECT     object;
  83.  
  84.     wl_bar = (WOOL_Bar) wool_type_or_evaluate(wl_bar, WLBar);
  85.     bar -> type = BarClass;
  86.     bar -> parent = parent;
  87.     bar -> direction = dir;
  88.     bar -> elength = 0;
  89.     bar -> ewidth = (wl_bar -> plugs_size ? 1 : 0);
  90.  
  91.     /* set up the box info */
  92.     bar -> box.width = bar -> box.height = wl_bar -> min_width;
  93.     bar -> min_width = wl_bar -> min_width;
  94.     bar -> max_width = wl_bar -> max_width;
  95.     bar -> box.borderwidth = wl_bar -> borderwidth;
  96.     bar -> box.borderpixel = wl_bar -> borderpixel;
  97.     bar -> box.background = wl_bar -> background;
  98.     bar -> plug_separator = wl_bar -> plug_separator;
  99.     increase_reference(bar -> menu = 
  100.                        wool_type_or_evaluate(wl_bar -> menu, WLMenu));
  101.     increase_reference(bar -> property = (WOOL_OBJECT) wl_bar -> property);
  102.     increase_reference(bar -> bordertile =
  103.              wool_type_or_evaluate(wl_bar -> bordertile, WLPixmap));
  104.     increase_reference(bar -> fsm =
  105.                wool_type_or_evaluate(wl_bar -> fsm, WLFsm));
  106.     increase_reference(bar -> cursor =
  107.                wool_type_or_evaluate(wl_bar -> cursor, WLCursor));
  108.     increase_reference(bar -> tile = (wl_bar -> tile == TRU ? wl_bar -> tile :
  109.                wool_type_or_evaluate(wl_bar -> tile, WLPixmap)));
  110.  
  111.     /* then recursively sets plug infos */
  112.     bar -> nplugs = wl_bar -> plugs_size;
  113.     for (i = 0; i < wl_bar -> plugs_size; i++) {
  114.       object = (WOOL_OBJECT) wl_bar -> plugs[i];
  115.       if ((object != NIL) && 
  116.           (object -> type != WLBar) && 
  117.           (object -> type != WLPlug)) {
  118.     object = WOOL_send(WOOL_eval, object, (object));
  119.         if (object == UNDEFINED_WOOL_VALUE)
  120.           wool_error(UNDEFINED_VARIABLE, "");
  121.         else if ((object != NIL) && 
  122.                  (object -> type != WLBar) && 
  123.                  (object -> type != WLPlug))
  124.           bad_argument(object, 0, "PLUG or BAR");
  125.       }
  126.       if (object -> type == WLPlug) {
  127.         bar -> plugs[i] = (Wob) NewPlug(bar, object);
  128.         bar -> ewidth = 0;
  129.       }
  130.       else if (object -> type == WLBar) {
  131.         bar -> plugs[i] = (Wob) NewBar(bar, object, !dir);
  132.         if (((Bar) bar -> plugs[i]) -> ewidth) bar -> elength = 1;
  133.         if (!(((Bar) bar -> plugs[i]) -> elength)) 
  134.           bar -> ewidth = 0;
  135.       }
  136.       else {
  137.         bar -> plugs[i] = (Wob) NULL;
  138.         bar -> elength = 1;
  139.       }
  140.     }
  141.     if (bar -> ewidth == -1) 
  142.       bar -> ewidth = 0;
  143.     return bar;
  144. }
  145.  
  146. BarClose(bar)
  147. Bar             bar;
  148. {
  149.     int             i;
  150.  
  151.     if(!bar) return;
  152.     for (i = 0; i < bar -> nplugs; i++) {
  153.     if (bar -> plugs[i])
  154.           if (bar -> plugs[i] -> type == PlugClass)
  155.         PlugClose(bar -> plugs[i]);
  156.           else if (bar -> plugs[i] -> type == BarClass)
  157.         BarClose(bar -> plugs[i]);
  158.     }
  159.     WobRelease(bar);
  160. }
  161.  
  162. /*
  163.  * Open a Bar
  164.  */
  165.  
  166. Bar
  167. BarOpen(bar)
  168. Bar             bar;
  169. {
  170.     int             i;
  171.  
  172.     if(!bar)
  173.         return bar;
  174.     check_window_size(bar);
  175.     bar -> hook = XCreateSimpleWindow(dpy, bar -> parent -> hook,
  176.                       bar -> box.x, bar -> box.y,
  177.                       bar -> box.width, bar -> box.height,
  178.                       bar -> box.borderwidth,
  179.                       bar -> box.borderpixel,
  180.                       bar -> box.background);
  181.     if (bar -> parent -> type == ScreenClass)
  182.     bar -> status |= TopLevelXWindowStatus;
  183.     WobRecordHook(bar);
  184.     if (bar -> cursor != NIL)
  185.     XDefineCursor(dpy, bar -> hook,
  186.               ((WOOL_Cursor) bar -> cursor) -> cursor);
  187.     if (bar -> tile != NIL && bar -> tile != TRU)
  188.     XSetWindowBackgroundPixmap(dpy, bar -> hook,
  189.                    ((WOOL_Pixmap) bar -> tile) -> pixmap);
  190.     if (bar -> bordertile != NIL)
  191.     XSetWindowBorderPixmap(dpy, bar -> hook,
  192.               ((WOOL_Pixmap) bar -> bordertile) -> pixmap);
  193.  
  194.     bar -> curstate = (int) WOOL_send(WOOL_open, bar -> fsm, (bar -> fsm));
  195.     for (i = 0; i < bar -> nplugs; i++) {
  196.     if (bar -> plugs[i])
  197.         WOOL_send(WOOL_open, bar -> plugs[i], (bar -> plugs[i]));
  198.     }
  199.     bar -> input_mask = WobMask | ((WOOL_Fsm) bar -> fsm) -> mask;
  200.     XSelectInput(dpy, bar -> hook, bar -> input_mask);
  201. #ifdef SHAPE
  202.     if (BarIsShaped(bar)) {
  203.       bar -> shaped = 1;
  204.       UpdateBarShape(bar);
  205.     }
  206. #endif /* SHAPE */
  207.     XMapWindow(dpy, bar -> hook);
  208.     XMapSubwindows(dpy, bar -> hook);
  209.     return bar;
  210. }
  211.  
  212. int 
  213. CalcNaturalBarWidth(bar)
  214. Bar             bar;
  215. {
  216.     Plug  *plugs;
  217.     int             i, curr_width = 1;
  218.  
  219.     plugs = (Plug *) & ((bar -> plugs)[0]);
  220.  
  221.     if (bar -> direction == HORIZONTAL) {
  222.       if (!bar -> nplugs && bar -> tile != NIL && bar -> tile != TRU)     
  223.     curr_width = ((WOOL_Pixmap) bar -> tile) -> height; 
  224.       for (i = 0; i < bar -> nplugs; i++) {
  225.     if (plugs[i]) 
  226.           if (plugs[i] -> type == PlugClass) {
  227.             UpdatePlugGeometry(plugs[i]);
  228.             curr_width = Max(curr_width,
  229.                plugs[i] -> box.height + 2 * plugs[i] -> box.borderwidth);
  230.           } else {
  231.             curr_width = Max(curr_width,
  232.                CalcNaturalBarLength(plugs[i]) + 2 * plugs[i] -> box.borderwidth);
  233.           }
  234.       }
  235.       curr_width = Min(bar -> max_width, Max(bar -> min_width, curr_width));
  236.       return curr_width;
  237.     } else {
  238.       if (!bar -> nplugs && bar -> tile != NIL && bar -> tile != TRU)
  239.     curr_width = ((WOOL_Pixmap) bar -> tile) -> width; 
  240.       for (i = 0; i < bar -> nplugs; i++) {
  241.     if (plugs[i])
  242.           if (plugs[i] -> type == PlugClass) {
  243.             UpdatePlugGeometry(plugs[i]);
  244.             curr_width = Max(curr_width,
  245.                plugs[i] -> box.width + 2 * plugs[i] -> box.borderwidth);
  246.           } else {
  247.             curr_width = Max(curr_width,
  248.                CalcNaturalBarLength(plugs[i]) + 2 * plugs[i] -> box.borderwidth);
  249.           }
  250.       }
  251.       curr_width = Min(bar -> max_width, Max(bar -> min_width, curr_width));
  252.       return curr_width;
  253.     }
  254. }
  255.  
  256. int
  257. CalcNaturalBarLength(bar)
  258. Bar        bar;
  259. {
  260.     Plug  *plugs;
  261.     int   i, tmp;
  262.     int   current_pos = 0;
  263.     int   space_len = 0, n_spaces = 0;
  264.  
  265.     plugs = (Plug *) & ((bar -> plugs)[0]);
  266.     if (bar -> direction == HORIZONTAL) {
  267.       for (i = 0; i < bar -> nplugs; i++)
  268.     if (!plugs[i]) {
  269.           n_spaces++;
  270.           current_pos += space_len;
  271.         } else if (plugs[i] -> type == PlugClass) {
  272.           UpdatePlugGeometry(plugs[i]);
  273.           current_pos += plugs[i] -> box.width
  274.             + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  275.         } else {
  276.           tmp = CalcNaturalBarWidth(plugs[i]);
  277.           if (((Bar) plugs[i]) -> ewidth)
  278.             if (tmp > space_len) {
  279.               current_pos += n_spaces * (tmp - space_len);
  280.               n_spaces++;
  281.               space_len = tmp;
  282.             } else {
  283.               n_spaces++;
  284.               tmp = space_len;
  285.             }
  286.           current_pos += tmp
  287.             + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  288.         }
  289.       if (current_pos)
  290.     current_pos -= bar -> plug_separator;
  291.       else if (!bar -> nplugs && bar -> tile != NIL && bar -> tile != TRU)
  292.     current_pos = ((WOOL_Pixmap) bar -> tile) -> width; 
  293.       else
  294.         current_pos = 1;
  295.     } else {
  296.       for (i = 0; i < bar -> nplugs; i++)
  297.     if (!plugs[i]) {
  298.           n_spaces++;
  299.           current_pos += space_len;
  300.         } else if (plugs[i] -> type == PlugClass) {
  301.           UpdatePlugGeometry(plugs[i]);
  302.           current_pos += plugs[i] -> box.height
  303.             + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  304.         } else {
  305.           tmp = CalcNaturalBarWidth(plugs[i]);
  306.           if (((Bar) plugs[i]) -> ewidth)
  307.             if (tmp > space_len) {
  308.               current_pos += n_spaces * (tmp - space_len);
  309.               n_spaces++;
  310.               space_len = tmp;
  311.             } else {
  312.               n_spaces++;
  313.               tmp = space_len;
  314.             }
  315.           current_pos += tmp
  316.             + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  317.         }
  318.       if (current_pos)
  319.     current_pos -= bar -> plug_separator;
  320.       else if (!bar -> nplugs && bar -> tile != NIL && bar -> tile != TRU)
  321.     current_pos = ((WOOL_Pixmap) bar -> tile) -> height; 
  322.       else
  323.         current_pos = 1;
  324.     }
  325.     return current_pos;
  326. }
  327.  
  328. int
  329. CalcMinBarLength(bar)
  330. Bar        bar;
  331. {
  332.     Plug  *plugs;
  333.     int             i, current_pos = 0;
  334.  
  335.     plugs = (Plug *) & ((bar -> plugs)[0]);
  336.     if (bar -> direction == HORIZONTAL) {
  337.       for (i = 0; i < bar -> nplugs; i++)
  338.     if (plugs[i])
  339.           if (plugs[i] -> type == PlugClass) {
  340.             UpdatePlugGeometry(plugs[i]);
  341.             current_pos += plugs[i] -> box.width
  342.               + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  343.           } else {
  344.             current_pos += bar -> plug_separator + 2 * plugs[i] -> box.borderwidth
  345.               + (((Bar) plugs[i]) -> ewidth ? 1 : CalcNaturalBarWidth(plugs[i]));
  346.           }
  347.       if (current_pos) {
  348.     current_pos -= bar -> plug_separator;
  349.       }
  350.     } else {
  351.       for (i = 0; i < bar -> nplugs; i++)
  352.     if (plugs[i])
  353.           if (plugs[i] -> type == PlugClass) {
  354.             UpdatePlugGeometry(plugs[i]);
  355.             current_pos += plugs[i] -> box.height
  356.               + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  357.           } else {
  358.             current_pos += bar -> plug_separator + 2 * plugs[i] -> box.borderwidth
  359.               + (((Bar) plugs[i]) -> ewidth ? 1 : CalcNaturalBarWidth(plugs[i]));
  360.           }
  361.       if (current_pos) {
  362.     current_pos -= bar -> plug_separator;
  363.       }
  364.     }
  365.     return current_pos;
  366. }
  367.  
  368.  
  369. /*
  370.  * Called BEFORE adjusting the client
  371.  * Here we take a bar setup, and suppose that its box data is updated.
  372.  * Then we ask for the dimension of plugs and proceed to position them.
  373.  * Adjust the width of the bars
  374.  */
  375.  
  376. int
  377. UpdateBarWidth(bar)
  378. Bar        bar;
  379. {
  380.     Plug  *plugs;
  381.     int             i;
  382.  
  383.     if (!bar)
  384.     return 0;
  385.  
  386.     if (bar -> direction == HORIZONTAL) {
  387.     bar -> box.height = CalcNaturalBarWidth(bar);
  388.     } else {
  389.     bar -> box.width = CalcNaturalBarWidth(bar);
  390.     }
  391.    
  392.     return 2 * bar -> box.borderwidth + (bar -> direction == HORIZONTAL ?
  393.                                          bar -> box.height : bar -> box.width);
  394. }
  395.  
  396.  
  397. /*
  398.  * Called AFTER adjusting the client
  399.  * Adjust space in the length of the bar.
  400.  * If we encounter a NULL plug, treat it as an extensible space
  401.  */
  402.  
  403. UpdateBarLength(bar)
  404. Bar        bar;
  405. {
  406.     Plug  *plugs;
  407.     int             i, n = 0, current_pos = 0, n_spaces = 0;
  408.     int             total_space, delta = 0, shift = 0;
  409.  
  410.     if (!bar)
  411.     return;
  412.     plugs = (Plug *) & ((bar -> plugs)[0]);
  413.     for (i = 0; i < bar -> nplugs; i++)
  414.     if (!plugs[i])
  415.           n_spaces++;
  416.         else if ((plugs[i] -> type == BarClass) && ((Bar) plugs[i]) -> ewidth)
  417.           n_spaces++;
  418.     total_space = (bar -> direction == HORIZONTAL ? bar -> box.width
  419.          : bar -> box.height) - CalcMinBarLength(bar);
  420.     if (n_spaces && (total_space > 0)) {
  421.     shift = total_space / n_spaces;
  422.         delta = total_space % n_spaces;
  423.     }
  424.  
  425.     if (bar -> direction == HORIZONTAL) {
  426.       for (i = 0; i < bar -> nplugs; i++)
  427.     if (plugs[i])
  428.           if (plugs[i] -> type == PlugClass) {
  429.             plugs[i] -> box.x = current_pos;
  430.             plugs[i] -> box.y = (bar -> box.height
  431.                                  - plugs[i]->box.height - 2 * plugs[i] -> box.borderwidth) / 2;
  432.             current_pos += plugs[i] -> box.width
  433.               + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  434.           } else {
  435.             plugs[i] -> box.x = current_pos;
  436.             plugs[i] -> box.y = 0;
  437.             if (((Bar) plugs[i]) -> ewidth)
  438.               plugs[i] -> box.width = 1 + (++n == n_spaces ? shift+delta : shift);
  439.             else if (bar -> nplugs == 1)
  440.               plugs[i] -> box.width = bar -> box.width - 2 * plugs[i] -> box.borderwidth;
  441.             else
  442.               plugs[i] -> box.width = CalcNaturalBarWidth(plugs[i]);
  443.             plugs[i] -> box.height = bar -> box.height - 2 * plugs[i] -> box.borderwidth;
  444.             UpdateBarLength(plugs[i]);
  445.             current_pos += plugs[i] -> box.width
  446.               + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  447.           }
  448.         else {
  449.           current_pos += (++n == n_spaces ? shift+delta : shift);
  450.         }
  451.     } else {
  452.       for (i = 0; i < bar -> nplugs; i++)
  453.     if (plugs[i])
  454.           if (plugs[i] -> type == PlugClass) {
  455.             plugs[i] -> box.y = current_pos;
  456.             plugs[i] -> box.x = (bar -> box.width
  457.                                  - plugs[i]->box.width - 2 * plugs[i] -> box.borderwidth) / 2;
  458.             current_pos += plugs[i] -> box.height
  459.               + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  460.           } else {
  461.             plugs[i] -> box.y = current_pos;
  462.             plugs[i] -> box.x = 0;
  463.             if (((Bar) plugs[i]) -> ewidth)
  464.               plugs[i] -> box.height = 1 + (++n == n_spaces ? shift+delta : shift);
  465.             else if (bar -> nplugs == 1)
  466.               plugs[i] -> box.height = bar -> box.height - 2 * plugs[i] -> box.borderwidth;
  467.             else
  468.               plugs[i] -> box.height = CalcNaturalBarWidth(plugs[i]);
  469.             plugs[i] -> box.width = bar -> box.width - 2 * plugs[i] -> box.borderwidth;
  470.             UpdateBarLength(plugs[i]);
  471.             current_pos += plugs[i] -> box.height
  472.               + bar -> plug_separator + 2 * plugs[i] -> box.borderwidth;
  473.           }
  474.         else {
  475.           current_pos += (++n == n_spaces ? shift+delta : shift);
  476.         }
  477.     }
  478. }
  479.  
  480. int
  481. NaturalBarLength(bar)
  482. Bar        bar;
  483. {
  484.     Plug  *plugs;
  485.     int             i;
  486.  
  487.     if (!bar)
  488.     return 0;
  489.     if (bar -> direction == HORIZONTAL) {
  490.       bar -> box.width = CalcNaturalBarLength(bar);
  491.     } else {
  492.       bar -> box.height = CalcNaturalBarLength(bar);
  493.     }
  494.     return 2 * bar -> box.borderwidth + (bar -> direction == HORIZONTAL ?
  495.                                          bar -> box.width : bar -> box.height);
  496. }
  497.  
  498. BarEventHandler(bar, evt)
  499. Bar    bar;
  500. XEvent    *evt;
  501. {
  502.     int             i;
  503.  
  504.     switch (evt -> type) {
  505.     case Expose:
  506.     XClearWindow(dpy, bar -> hook);
  507.     break;
  508.     case GWMUserEvent:            /* TODO: no more test on plugs masks*/
  509.     WLFsm_action(bar -> fsm, bar, evt);
  510.     if (GWM_Propagate_user_events)
  511.         for (i = 0; i < bar -> nplugs; i++)
  512.         if ((bar -> plugs[i])) {
  513.             WOOL_send(WOOL_process_event, bar -> plugs[i],
  514.                   (bar -> plugs[i], evt));
  515.         }
  516.     break;
  517.     default:
  518.     WLFsm_action(bar -> fsm, bar, evt);
  519.     }
  520. }
  521.  
  522. ReconfigureBar(bar, culprit)
  523. Bar    bar;
  524. Wob    culprit;        /* parent or plug */
  525. {
  526.     int             i, width, height, must_resize = 1;
  527.  
  528.     if (!bar)
  529.     return;
  530.     width = bar -> box.width;
  531.     height = bar -> box.height;
  532.     if (culprit != (Wob) bar -> parent) {    /* from plug or bar below */
  533.     UpdateBarWidth(bar);
  534.         WOOL_send(WOOL_reconfigure, bar -> parent, (bar -> parent, bar));
  535.     }
  536.     else {                                      /* from above */
  537.       if (culprit && culprit -> type != BarClass)
  538.         UpdateBarLength(bar); 
  539.       XMoveResizeWindow(dpy, bar -> hook, bar -> box.x, bar -> box.y,
  540.                         bar -> box.width, bar -> box.height);
  541.       for (i = 0; i < bar -> nplugs; i++)
  542.     if (bar -> plugs[i])
  543.           if (bar -> plugs[i] -> type == PlugClass)
  544.         ReconfigurePlug(bar -> plugs[i], bar);
  545.           else
  546.             ReconfigureBar(bar -> plugs[i], bar);
  547. #ifdef SHAPE
  548.       if (bar -> shaped || (bar -> shaped = BarIsShaped(bar)))
  549.         UpdateBarShape(bar);
  550. #endif /* SHAPE */
  551.       XClearWindow(dpy, bar -> hook);
  552.     }
  553. }
  554.  
  555. set_bar_bitmap(bar, wl_pixmap)
  556. Bar     bar;
  557. WOOL_OBJECT     wl_pixmap;
  558. {
  559.     int shaped_tile = 0;
  560.     if (((wl_pixmap -> type == WLAtom) && (wl_pixmap != TRU) && (wl_pixmap != NIL))
  561.          || wl_pixmap -> type == WLList)
  562.     return;
  563.     if (bar -> tile == TRU)
  564.       shaped_tile = -1;
  565.     else if (TileIsShaped(bar -> tile))
  566.       shaped_tile = 1;
  567.     decrease_reference(bar -> tile);
  568.     increase_reference(bar -> tile = wl_pixmap);
  569.     if ((shaped_tile == -1) && (bar -> tile == TRU))
  570.       shaped_tile = 0;        /* No reconfigure necessary if it remains TRU */
  571.     else if ((bar -> tile == TRU) || TileIsShaped(bar -> tile))
  572.       shaped_tile = 1;
  573.     if (wl_pixmap == NIL) 
  574.       XSetWindowBackground(dpy, bar->hook, bar -> box.background);
  575.     else if (wl_pixmap -> type == WLPixmap)
  576.       XSetWindowBackgroundPixmap(dpy, bar->hook,
  577.                                  ((WOOL_Pixmap) wl_pixmap) -> pixmap);
  578.     /* Reconfigure only if anything will change */
  579.     if (shaped_tile || 
  580.         ((!bar -> nplugs) &&
  581.          ((bar -> direction == HORIZONTAL ? bar -> box.height : bar -> box.width) != CalcNaturalBarWidth(bar)))) {
  582.         ReconfigureBar(bar, 0);
  583.     }
  584.     XClearWindow(dpy, bar -> hook);
  585. }
  586.  
  587. #ifdef SHAPE
  588. /* non-rectangular extension */
  589.  
  590. int
  591. BarIsShaped(bar)
  592. Bar     bar;
  593. {
  594.   int i;
  595.   if ((bar -> tile == TRU) || TileIsShaped(bar -> tile))
  596.     return 1;
  597.   for (i = 0; i < bar -> nplugs; i++)
  598.     if (bar -> plugs[i])
  599.       if (bar -> plugs[i] -> type == PlugClass) {
  600.         if (((Plug) bar -> plugs[i]) -> graphic -> type == WLPixmap
  601.             && (((WOOL_Pixmap) (((Plug) bar -> plugs[i]) -> graphic))->mask))
  602.           return 1;
  603.       } else {
  604.         if (((Bar) bar -> plugs[i]) -> shaped)
  605.           return 1;
  606.       }
  607.   return 0;
  608. }
  609.  
  610. UpdateBarShape(bar)
  611. Bar     bar;
  612. {
  613.   XRectangle rect, rect2;
  614.   Plug *plugs;
  615.   int i;
  616.   int shaped_tile = TileIsShaped(bar -> tile);
  617.  
  618.   rect.x = - bar -> box.borderwidth;
  619.   rect.y = - bar -> box.borderwidth;
  620.   rect.width = bar -> box.width + 2 * bar -> box.borderwidth;
  621.   rect.height = bar -> box.height + 2 * bar -> box.borderwidth;
  622.   XShapeCombineRectangles(dpy, bar -> hook, ShapeBounding, 
  623.                           0, 0,
  624.                           &rect, 1, ShapeSet, 0); 
  625.                     /* transparent tile */
  626.   if (bar -> tile == TRU || shaped_tile) {
  627.     rect2.x = 0;
  628.     rect2.y = 0;
  629.     rect2.width = bar -> box.width;
  630.     rect2.height = bar -> box.height;
  631.     XShapeCombineRectangles(dpy, bar -> hook, ShapeBounding,
  632.                             0, 0,
  633.                             &rect2, 1, ShapeSubtract, 0);
  634.   }
  635.                     /* shaped tile */
  636.   if (shaped_tile) {
  637.       int x_offset, y_offset;
  638.       /* we do the tiling ourselves by hand */
  639.       for (x_offset = 0; x_offset < bar -> box.width; 
  640.              x_offset += ((WOOL_Pixmap) (bar -> tile)) -> width) {
  641.       for (y_offset = 0; y_offset < bar -> box.height; 
  642.                  y_offset += ((WOOL_Pixmap) (bar -> tile))->height) {
  643.           XShapeCombineMask(dpy, bar -> hook, ShapeBounding,
  644.                 x_offset, y_offset,
  645.                 ((WOOL_Pixmap) (bar -> tile)) -> mask,
  646.                 ShapeUnion);
  647.       }
  648.       }
  649.   }
  650.  
  651.   plugs = (Plug *) & ((bar -> plugs)[0]);
  652.   for (i = 0; i < bar -> nplugs; i++)
  653.     if (plugs[i]) {
  654.         rect2.x = plugs[i] -> box.x + plugs[i] -> box.borderwidth;
  655.         rect2.y = plugs[i] -> box.y + plugs[i] -> box.borderwidth;
  656.         rect2.width = plugs[i] -> box.width;
  657.         rect2.height = plugs[i] -> box.height;
  658.         XShapeCombineRectangles(dpy, bar -> hook, ShapeBounding,
  659.                                 0, 0,
  660.                                 &rect2, 1, ShapeSubtract, 0); 
  661.         XShapeCombineShape(dpy, bar -> hook, ShapeBounding,
  662.                            rect2.x, 
  663.                            rect2.y, 
  664.                            plugs[i] -> hook, ShapeBounding,
  665.                            ShapeUnion);
  666.     }
  667.   XShapeCombineRectangles(dpy, bar -> hook, ShapeBounding, 
  668.                           0, 0,
  669.                           &rect, 1, ShapeIntersect, 0); 
  670. }
  671.  
  672. #endif /* SHAPE */
  673.  
  674.