home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / awm2 / part07 / Icons.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-20  |  14.2 KB  |  508 lines

  1.  
  2.  
  3.  
  4. #ifndef lint
  5. static char *rcsid_Icons_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/Icons.c,v 1.2 89/02/07 20:05:21 jkh Exp $";
  6. #endif  lint
  7.  
  8. #include "X11/copyright.h"
  9. /*
  10.  *
  11.  * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  12.  *
  13.  * Copyright 1987 by Jordan Hubbard.
  14.  *
  15.  *
  16.  *                         All Rights Reserved
  17.  *
  18.  * Permission to use, copy, modify, and distribute this software and its
  19.  * documentation for any purpose and without fee is hereby granted,
  20.  * provided that the above copyright notice appear in all copies and that
  21.  * both that copyright notice and this permission notice appear in
  22.  * supporting documentation, and that the name of Ardent Computer
  23.  * Corporation or Jordan Hubbard not be used in advertising or publicity
  24.  * pertaining to distribution of the software without specific, written
  25.  * prior permission.
  26.  *
  27.  */
  28.  
  29. /*
  30.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  31.  *
  32.  *                         All Rights Reserved
  33.  *
  34.  * Permission to use, copy, modify, and distribute this software and its
  35.  * documentation for any purpose and without fee is hereby granted,
  36.  * provided that the above copyright notice appear in all copies and that
  37.  * both that copyright notice and this permission notice appear in
  38.  * supporting documentation, and that the name of Digital Equipment
  39.  * Corporation not be used in advertising or publicity pertaining to
  40.  * distribution of the software without specific, written prior permission.
  41.  *
  42.  *
  43.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  44.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  45.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  46.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  47.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  48.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  49.  * SOFTWARE.
  50.  */
  51.  
  52.  
  53.  
  54. /*
  55.  * MODIFICATION HISTORY
  56.  *
  57.  * 000 -- L. Guarino Reid, DEC Ultrix Engineering Group
  58.  * 001 -- Jordan Hubbard, Ardent Computer
  59.  *  Many modifications for titled windows.
  60.  * 1.2 -- Jordan Hubbard, Ardent Computer.
  61.  * vPad and hPad usage corrected (Chris Thewalt fix).
  62.  * Clipping now set on right GC. 
  63.  * 1.3 -- Changed the way icon button events are handled.
  64.  * 1.4 -- Isaac J. Salzman, RAND Corp.
  65.  * reworked the way icons are handled - if IconsLabels is set, icons
  66.  * with pixmaps are labled at bottom & icons w/o pixmaps use a default
  67.  * pixmap w/a label instead of just a solid bg tile (i.e. twm style),
  68.  * otherwise old uwm style icons are used (typin and all).
  69.  * 1.5 -- Modified Isaac's changes to allow wm_option.icon.labels to
  70.  * work. This allows individual clients/classes to determine their
  71.  * icon style.  -jkh
  72.  */
  73.  
  74. #include "awm.h"
  75. #include "X11/Xutil.h"
  76.  
  77. extern XContext AwmContext;
  78.      extern void Warning();
  79.  
  80. /* the client should pass us a bitmap (single-plane pixmap with background=0
  81.  * and foreground = 1).  It is our responsibility to convert it to a pixmap
  82.  * of the appropriate depth for a window tile and also color it with the
  83.  * appropriate background and foreground pixels.
  84.  *
  85.  * we'll use the (global) IconGC for the fore/background pixels.
  86.  */
  87.  
  88. static Pixmap MakePixmapFromBitmap( bitmap, clipmask, width_return, height_return )
  89. Pixmap bitmap, clipmask;
  90. unsigned int *width_return, *height_return;
  91. {
  92.      Pixmap tile;
  93.      Window junkW;
  94.      int junk;
  95.      unsigned int width, height;
  96.      GC iGC;
  97.      XGCValues gcv;
  98.      
  99.      Entry("MakePixmapFromBitmap")
  100.       
  101.      if (!XGetGeometry( dpy, bitmap, &junkW, &junk, &junk,
  102.                &width, &height, &junk, &junk )) {
  103.       Warning( "client passed invalid pixmap for icon." );
  104.       Leave( NULL )
  105.      }
  106.      tile = XCreatePixmap( dpy, RootWindow(dpy, scr), width, height,
  107.               (unsigned) DefaultDepth(dpy, scr) );
  108.      gcv.foreground = ITextForeground;
  109.      gcv.background = ITextBackground;
  110.      iGC = XCreateGC(dpy, RootWindow(dpy, scr), (GCForeground | GCBackground),
  111.              &gcv);
  112.      if (clipmask)
  113.       XSetClipMask(dpy, iGC, clipmask);
  114.      XCopyPlane(dpy, bitmap, tile, iGC, 0, 0, width, height, 0, 0, 
  115.         (unsigned long) 1 );
  116.      XFreeGC(dpy, iGC);
  117.      if (width_return)
  118.       *width_return = width;
  119.      if (height_return)
  120.       *height_return = height;
  121.      Leave(tile)
  122. }
  123.  
  124. char *GetIconName(window)
  125. Window window;
  126. {
  127.      unsigned char *name;
  128.      Status status;
  129.      unsigned long len, after;
  130.      Atom a_type;
  131.      int a_form;
  132.      
  133.      Entry("GetIconName")
  134.      
  135.      status = XGetWindowProperty(dpy, window, XA_WM_ICON_NAME, 0L, 256L,
  136.                  False, XA_STRING, &a_type, &a_form, &len, &after,
  137.                  &name);
  138.      
  139.      if (status != Success) {
  140.       status = XGetWindowProperty(dpy, window, XA_WM_NAME, 0L, NAME_LEN,
  141.                       False, XA_STRING, &a_type, &a_form, &len,
  142.                       &after, &name);
  143.       if (status != Success)
  144.            Leave( DEF_NAME ) /* use default name */
  145.      }
  146.      if (a_form == 0)    /* we have no bananas */
  147.       Leave((char *)NULL)
  148.      if (a_form != 8) {
  149.       Warning("Window has icon_name in wrong format");
  150.       if (name)
  151.            free(name);
  152.       Leave((char *)NULL)
  153.      }
  154.      if (len > NAME_LEN) {
  155.       Warning("Window has icon_name greater than maximum length");
  156.       len = NAME_LEN;
  157.      }
  158.      if (!len)
  159.       Leave((char *)NULL)
  160.      name[len] = 0;
  161.      Leave((char *) name)
  162. }
  163.  
  164. Boolean IsIcon(icon, win)
  165. Window icon;
  166. Window *win;
  167. {
  168.      AwmInfoPtr awi;
  169.  
  170.      Entry("IsIcon")
  171.  
  172.      if (win)
  173.       *win = 0;
  174.      awi = GetAwmInfo(icon);
  175.      if (!awi)
  176.       Leave(FALSE)
  177.      if (awi->icon == icon) {
  178.       if (win)
  179.            *win = awi->client;
  180.       Leave(TRUE)
  181.      }
  182.      else if (awi->client == icon || awi->frame == icon) {
  183.       if (win)
  184.            *win = awi->icon;
  185.       Leave(FALSE)
  186.      }
  187.      Leave(FALSE)
  188. }
  189.  
  190. RemoveIcon(window)
  191. Window window;
  192. {
  193.      AwmInfoPtr awi;
  194.  
  195.      Entry("RemoveIcon")
  196.      
  197.      if ((awi = GetAwmInfo(window)) != NULL) {
  198.       XDeleteContext(dpy, awi->icon, AwmContext);
  199.       if (awi->own) {
  200.            XDestroyWindow(dpy, awi->icon);
  201.            if ((awi->iconPixmap != IBackPixmap) && 
  202.            (awi->iconPixmap != IDefPixmap))
  203.            XFreePixmap(dpy, awi->iconPixmap);
  204.       }
  205.       awi->icon = (Drawable)NULL;
  206.       awi->state ^= ST_ICON;
  207.       awi->state |= ST_WINDOW;
  208. #ifdef WMSTATE
  209.       awi->wm_state.icon=0;
  210.       awi->wm_state.state=NormalState;
  211.       XChangeProperty(dpy,awi->client,wm_state_atom,wm_state_atom,32,
  212.               PropModeReplace,(char *) &awi->wm_state,2);
  213. #endif /* WMSTATE */
  214.      }
  215.      Leave_void
  216. }
  217.  
  218. GetDefaultSize(window, icon_w, icon_h)
  219. Window window;
  220. int *icon_w, *icon_h;
  221. {
  222.      char *name;                /* Event window name. */
  223.  
  224.      Entry("GetDefaultSize")
  225.  
  226.      /*
  227.       * Determine the size of the icon window.
  228.       */ 
  229.      name = GetIconName(window);
  230.      *icon_h = IFontInfo->ascent + IFontInfo->descent;
  231.      if (name) {
  232.       *icon_w = XTextWidth(IFontInfo, name, strlen(name));
  233.       if (*icon_w == 0)
  234.            *icon_w = *icon_h;
  235.      }
  236.      else 
  237.       *icon_w = *icon_h = 0; /* set to zilch if bogus name! */
  238.      Leave_void
  239. }
  240.  
  241. Window MakeIcon(window, x, y, mousePositioned)
  242. Window window;                          /* associated window. */
  243. int x, y;                               /* Event mouse position. */
  244. Boolean mousePositioned;
  245. {
  246.      int icon_x, icon_y;        /* Icon U. L. X and Y coordinates. */
  247.      unsigned int icon_w, icon_h;    /* Icon width and height. */
  248.      unsigned int icon_bdr;        /* Icon border width. */
  249.      long mask;                /* Icon event mask */
  250.      XSetWindowAttributes iconValues;    /* for icon window creation */
  251.      unsigned long iconValues_mask;    /* for above */
  252.      XWMHints *wmhints;            /* see if icon position provided */
  253.      XWMHints *XGetWMHints();
  254.      Pixmap clip = 0;
  255.      Window AddIcon();
  256.      AwmInfoPtr awi;
  257.      int junk;
  258.  
  259.      Entry("MakeIcon")
  260.  
  261.      awi = GetAwmInfo(window);
  262.  
  263.      if (awi->attrs & AT_ICONLABEL) {    /* check for iconLables - twm style */
  264.       iconValues.background_pixmap = IDefPixmap;
  265.       mask = StructureNotifyMask;
  266.      }
  267.      else {                    /* uwm style */
  268.       iconValues.background_pixmap = IBackPixmap;
  269.       mask = (ExposureMask | StructureNotifyMask | KeyPressMask);
  270.      }
  271.  
  272.      /*
  273.       * Process window manager hints.
  274.       */ 
  275.      if (wmhints = XGetWMHints(dpy, window)) {
  276.       if (wmhints->flags & IconWindowHint)
  277.            Leave(AddIcon(window, wmhints->icon_window, FALSE,
  278.                  (StructureNotifyMask), (Pixmap)NULL));
  279.  
  280.        if (wmhints->flags & IconPixmapHint) {
  281.         if (wmhints->flags & IconMaskHint)
  282.              clip = wmhints->icon_mask;
  283.         iconValues.background_pixmap =
  284.              MakePixmapFromBitmap(wmhints->icon_pixmap, clip,
  285.                       &icon_w, &icon_h );
  286.         if (iconValues.background_pixmap)
  287.              mask = (StructureNotifyMask);
  288.          else {
  289.               iconValues.background_pixmap = IBackPixmap;
  290.               wmhints->flags &= ~IconPixmapHint;
  291.          }
  292.        }
  293.      }
  294.      
  295.      /*
  296.       * we now have a pixmap of some sort - either a background
  297.       *  tile or an actual image - get the dimensions...
  298.       */
  299.  
  300.      if (!XGetGeometry(dpy, iconValues.background_pixmap,
  301.                &junk, &junk, &junk,
  302.                &icon_w, &icon_h, &junk, &junk )) {
  303.       Warning( "can't get geom of pixmap in MakeIcon" );
  304.       Leave( NULL );
  305.      }
  306.      
  307.      if (awi->attrs & AT_ICONLABEL) {
  308.       char *s;
  309.       Pixmap p;
  310.       unsigned int nw, nh;
  311.       int tw, th, hoff, voff;
  312.        
  313.        if (s = GetIconName(window)) {
  314.         nw = icon_w;
  315.         nh = icon_h;
  316.  
  317.         /* find out dimensions of text, add padding */
  318.         tw = XTextWidth(IFontInfo, s, strlen(s)) + HIconPad;
  319.         th = IFontInfo->ascent + IFontInfo->descent + VIconPad;
  320.         
  321.         
  322.         /* calculate the size including the icon label */
  323.         if (nw < tw)    /* width >= text width */
  324.              nw = tw;
  325.         
  326.         /* always tack on extra for the label height */
  327.         nh += th;
  328.         
  329.         /* now that we have dimensions, create the pixmap
  330.            we want to eventually use as the icon window
  331.            */
  332.         
  333.         if (!(p = XCreatePixmap(dpy, RootWindow(dpy, scr), nw, nh,
  334.                     (unsigned) DefaultDepth(dpy, scr)))) {
  335.              Warning("can't create pixmap in MakeIcon.");
  336.              Leave( NULL )
  337.         }
  338.  
  339.         /* calculate horizontal offset of pixmap (center it!) */
  340.         if (hoff = (nw - icon_w))
  341.              hoff = (hoff+1)/2;
  342.         
  343.         /* if the label goes at the top, push the thing to the bottom
  344.          * otherwise leave it at the top
  345.              */
  346.         
  347.         voff = ILabelTop ? (th - (VIconPad+1)/2) : (VIconPad+1)/2;
  348.         
  349.         XCopyArea(dpy, iconValues.background_pixmap, p,
  350.               IconGC, 0, 0, icon_w, icon_h, 
  351.               hoff, voff);
  352.         
  353.         /* now that we have a centered pixmap draw
  354.          * some text on it....
  355.          */
  356.         
  357.         if (hoff = (nw - tw))
  358.              hoff = (hoff+1)/2;
  359.         else
  360.              hoff = (HIconPad ? (HIconPad+1)/2 : 1);
  361.         
  362.         /* see if string goes to top or bottom */
  363.         if (ILabelTop)
  364.              voff = th - (IFontInfo->descent-((VIconPad+1)/2));
  365.         else
  366.              voff = nh-(IFontInfo->descent+((VIconPad+1)/2));
  367.         
  368.         XDrawImageString(dpy, p, IconGC, hoff, voff, s, strlen(s));
  369.         
  370.         /*
  371.          * Now free up original pixmap and replace
  372.          * with this new one.
  373.          */
  374.         
  375.         icon_h = nh;
  376.         icon_w = nw;
  377.         
  378.         if ((iconValues.background_pixmap != IBackPixmap) &&
  379.             (iconValues.background_pixmap != IDefPixmap))
  380.              XFreePixmap(dpy, iconValues.background_pixmap);
  381.         iconValues.background_pixmap = p;
  382.        }
  383.      }         
  384.      else {             /* do it the old way.... */
  385.       int h, w;
  386.       
  387.       if (!wmhints || !(wmhints->flags & IconPixmapHint)) {
  388.            GetDefaultSize(window, &w, &h);
  389.             
  390.            if ((w==0) || (h==0)) { /* no label, use IDefPixmap */
  391.             iconValues.background_pixmap = IDefPixmap;
  392.              
  393.             /* get geom of ipixmap */
  394.             if (!XGetGeometry(dpy, iconValues.background_pixmap,
  395.                       &junk, &junk, &junk,
  396.                       &icon_w, &icon_h, &junk, &junk)) {
  397.              Warning("can't get geom of pixmap in MakeIcon");
  398.              Leave(NULL)
  399.             }
  400.            }
  401.            else { /* use small label icon + some padding */
  402.             icon_h = h+VIconPad;
  403.             icon_w = w+HIconPad;
  404.            }
  405.       }
  406.      }
  407.      /*
  408.       * Set the icon border attributes.
  409.       */ 
  410.      if (!wmhints || !(wmhints->flags & IconWindowHint)) {
  411.       icon_bdr = IBorderWidth;
  412.       iconValues.border_pixel = IBorder;
  413.      }
  414.      /*
  415.       * Determine icon position....
  416.       */
  417.      if (wmhints && (wmhints->flags & IconPositionHint)) {
  418.       icon_x = wmhints->icon_x;
  419.       icon_y = wmhints->icon_y;
  420.      } else {
  421.       if (mousePositioned) {
  422.            /*
  423.         * Determine the coordinates of the icon window;
  424.         * normalize so that we don't lose the icon off the
  425.         * edge of the screen.
  426.         */
  427.            icon_x = x - (icon_w >> 1) + 1;
  428.            if (icon_x < 0) icon_x = 0;
  429.            icon_y = y - (icon_h >> 1) + 1;
  430.            if (icon_y < 0) icon_y = 0;
  431.            if ((icon_x - 1 + icon_w + (icon_bdr << 1)) > ScreenWidth) {
  432.             icon_x = ScreenWidth - icon_w - (icon_bdr << 1) + 1;
  433.            }
  434.            if ((icon_y - 1 + icon_h + (icon_bdr << 1)) > ScreenHeight) {
  435.             icon_y = ScreenHeight - icon_h - (icon_bdr << 1) + 1;
  436.            }
  437.       }
  438.       else {
  439.            icon_x = x + (icon_w >> 1);
  440.            icon_y = y + (icon_y >> 1);
  441.       }
  442.       
  443.      }
  444.  
  445.      /*
  446.       * Create the icon window.
  447.       */
  448.      iconValues_mask = CWBorderPixel | CWBackPixmap;
  449.      /*
  450.       * Here we assume that if they want save unders, they'll also want
  451.       * backing store on the icons. Perhaps a dangerous assumption, but
  452.       * one we have to make at this point.
  453.       */
  454.      if (SaveUnder) {
  455.       iconValues.backing_store = WhenMapped;
  456.       iconValues_mask |= CWBackingStore;
  457.      }
  458.      Leave(AddIcon(window,
  459.            XCreateWindow(
  460.                  dpy, RootWindow(dpy, scr),
  461.                  icon_x, icon_y,
  462.                  icon_w, icon_h,
  463.                  icon_bdr, 0, CopyFromParent, CopyFromParent,
  464.                  iconValues_mask, &iconValues),
  465.            TRUE, mask, iconValues.background_pixmap))
  466. }
  467.  
  468. Window AddIcon(window, icon, own, mask, background)
  469. Window window, icon;
  470. Boolean own;
  471. long mask;
  472. Pixmap background;
  473. {
  474.      AwmInfoPtr awi;
  475.  
  476.      Entry("AddIcon")
  477.  
  478.      if (icon == NULL)
  479.       Leave(NULL)
  480.      /*
  481.       * Use the text cursor whenever the mouse is in the icon window, if
  482.       * it's a typein icon, otherwise use gumby....
  483.       */
  484.  
  485.      if (background == IBackPixmap)
  486.      XDefineCursor(dpy, icon, TextCursor);
  487.      else
  488.      XDefineCursor(dpy, icon, GumbyCursor);
  489.      
  490.      /*
  491.       * Select "key pressed", "window exposure" and "unmap window"
  492.       * events for the icon window.
  493.       */
  494.      XSelectInput(dpy, icon, mask | ButtonPressMask | ButtonReleaseMask);
  495.  
  496.      awi = GetAwmInfo(window);
  497.      awi->icon = icon;
  498.      awi->own = own;
  499.      awi->iconPixmap = background;
  500. #ifdef WMSTATE
  501.      awi->wm_state.icon=icon;
  502.      XChangeProperty(dpy,awi->client,wm_state_atom,wm_state_atom,32,
  503.              PropModeReplace,(char *) &awi->wm_state,2);
  504. #endif /* WMSTATE */
  505.      XSaveContext(dpy, icon, AwmContext, (caddr_t) awi);
  506.      Leave(icon)
  507. }
  508.