[comp.windows.x.motif] PushButton Pixmap problems

jcw@hpfcbig.SDE.HP.COM (Judy Walker) (10/16/90)

I am having a problem now with using the PushButton
capabilities to display a pixmap image.  I read a pixmap file using 
XReadBitmapFile, set the XmNlabelPixmap resource to the pixmap, and 
set the argument XmNlabelType to XmPIXMAP.  When the server 
tries to display it, I receive this message:

Received fatal error from window system: BadMatch, invalid paramete
r attributes


I am doing everything that I know about by the
book.  What could be wrong?  Any ideas would be appreciated.

Here is the code:


     status = XReadBitmapFile(dpy, RootWindow(dpy, scr),
			      real_path,
			      &width, &height, &pix, &x_hot, &y_hot);

   XtSetArg(arglist[*n], XmNlabelPixmap, (XtArgVal) pix); (*n)++; 


   XtSetArg(arglist[n], XmNlabelType, (XtArgVal) XmPIXMAP); n++;


An XtSetValues is done later.

paulm@hpcvlx.cv.hp.com (Paul J. McClellan) (10/19/90)

Below is an example client illustrating how one can read a bitmap from
a bitmap file, create a pixmap from it, and set a XmLabel's labelPixmap
resource.  

 +--------------------------------------------------------------------+
 | Paul J. McClellan                 | paulm@cv.hp.com                |
 | Information Technology Operation  | {backbone}!hplabs!hp-pcd!paulm |
 | Hewlett Packard Co.               | (USA) (503) 750-2493  VOICE    |
 +--------------------------------------------------------------------+


/************************************************************************
 *  File:  label_pixmap.c
 *
 *  Reads a bitmap from a bitmap file and creates a label pixmap from it.
 ***********************************************************************/

#include <stdio.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <Xt/MwmUtil.h>
#include <Xm/Xm.h>
#include <Xm/Label.h>

/************************************************************************
 *  main
 ***********************************************************************/

main (argc, argv)
    int argc;
    char **argv;
{
    Widget    toplevel, label;

    /*
     *  Initialize the Intrinsics and create the Label widget.
     */
  
    toplevel =  XtInitialize (argv[0], "App-notes", NULL, 0, &argc, argv);

    label = XmCreateLabel (toplevel, "label", NULL, 0);
    XtManageChild (label);

    /*
     *  Read any specified bitmap file.  Construct the label pixmap from it.
     */

    if (argc && argv[1])
    {
	Display      *dpy;
	Screen       *screen;
        int           x, y, n;
        unsigned int  width, height;
        Arg           wargs[3];
        Pixmap        bitmap;

        dpy = XtDisplay (toplevel);
        screen = XtScreen (toplevel);
        if (XReadBitmapFile (dpy, RootWindowOfScreen (screen),
			     argv[1], &width, &height, &bitmap, &x, &y)
            != BitmapSuccess)
        {
            fprintf (stderr, "Unable to read bitmap file %s\n", argv[1]);
	    bitmap = NULL;
        }

        if (bitmap && (width == 0 || height == 0))
        {
            fprintf (stderr, "Invalid bitmap file %s\n", argv[1]);
	    bitmap = NULL;
        }

        if (bitmap)
	{
            Pixel         fg, bg;
            Pixmap        pixmap;
            GC            gc;
            XGCValues     gcv;

            /*
             * Get the foreground and background colors from the label widget.
             */

            n = 0;
            XtSetArg (wargs[n], XtNforeground, &fg); n++;
            XtSetArg (wargs[n], XtNbackground, &bg); n++;
            XtGetValues (label, wargs, n);

            /* 
             * Create a pixmap of the appropriate size, root, and depth.
             */

            pixmap = XCreatePixmap (dpy, RootWindowOfScreen (screen),
				    width, height,
                                    DefaultDepthOfScreen (screen));

            /*
	     * Create a GC and copy the bitmap to the pixmap.
             */

            gcv.foreground = bg;
            gcv.background = bg;
            gc = XCreateGC (dpy, pixmap, (GCForeground|GCBackground), &gcv);
   
            /*
	     * Fill in the background, set the foreground, copy the bitmap to 
	     * the pixmap, and free the gc.
             */

            XFillRectangle (dpy, pixmap, gc, 0, 0, width, height);
            XSetForeground (dpy, gc, fg);
            XCopyPlane (dpy, bitmap, pixmap, gc, 0, 0, width, height, 0, 0, 1L);
            XFreeGC (dpy, gc);
   
            /*
	     * Set the labelType and labelPixmap resources.
             */

            n = 0;
            XtSetArg (wargs[n], XmNlabelType, XmPIXMAP); n++;
            XtSetArg (wargs[n], XmNlabelPixmap, pixmap); n++;
            XtSetValues (label, wargs, n);
	}
    }

    /*
     *  Realize the widget hierarchy and enter the main loop.
     */

    XtRealizeWidget (toplevel);
    XtMainLoop ();
}

argv@turnpike.Eng.Sun.COM (Dan Heller) (10/19/90)

In article <12110003@hpfcbig.SDE.HP.COM> jcw@hpfcbig.SDE.HP.COM (Judy Walker) writes:
> I am having a problem now with using the PushButton
> capabilities to display a pixmap image.  I read a pixmap file using 
> XReadBitmapFile, set the XmNlabelPixmap resource to the pixmap, and 
> set the argument XmNlabelType to XmPIXMAP.  When the server 
> tries to display it, I receive this message:
> 
> Received fatal error from window system: BadMatch, invalid paramete
> r attributes

Chances are that the pixmap is 1-bit deep and your screen is more than
1-bit deep (e.g., it's color).  You can't mix pixmaps and windows
that have differing depths.  You can avoid this problem by using
XmGetPixmap rather than XReadBitmapFile().  However, the file must
be in one of a set of predesignated directories.  (I forget what the
specifics on this are, but it includes /usr/include/X11/bitmaps, I
believe).
--
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.

nazgul@alphalpha.com (Kee Hinckley) (10/19/90)

> that have differing depths.  You can avoid this problem by using
> XmGetPixmap rather than XReadBitmapFile().  However, the file must
> be in one of a set of predesignated directories.  (I forget what the
Actually you can pass XmGetPixmap a pathname and it will do the
right thing.

						-kee

meeks@osf.org (W. Scott Meeks) (10/22/90)

>From: argv@sun.com  (Dan Heller)
>
>Chances are that the pixmap is 1-bit deep and your screen is more than
>1-bit deep (e.g., it's color).  You can't mix pixmaps and windows
>that have differing depths.  You can avoid this problem by using
>XmGetPixmap rather than XReadBitmapFile().  However, the file must
>be in one of a set of predesignated directories.  (I forget what the
>specifics on this are, but it includes /usr/include/X11/bitmaps, I
>believe).
>--
>dan

In version 1.1 the restriction on the directories for XmGetPixmap are
actually loser than this implies.  First, the user can specify an
environment variable XBMLANGPATH which will be used to generate a set of
default paths.  Second, XmGetPixmap will recognize an absolute path on a
Unix system (a path beginning with '/') and use that as the file to open.
Finally, the current working directory is always searched by default if
neither an absolute path or XBMLANGPATH are specified.  If you have any
more questions on this please ask me.

W. Scott Meeks
Open Software Foundation
meeks@osf.org
(617) 621-7229

nazgul@alphalpha.com (Kee Hinckley) (10/22/90)

> In version 1.1 the restriction on the directories for XmGetPixmap are
> actually loser than this implies.  First, the user can specify an
> environment variable XBMLANGPATH which will be used to generate a set of
> default paths.  Second, XmGetPixmap will recognize an absolute path on a
> Unix system (a path beginning with '/') and use that as the file to open.
> Finally, the current working directory is always searched by default if
> neither an absolute path or XBMLANGPATH are specified.  If you have any
> more questions on this please ask me.

This is the same approach that XOpen took with the message catalog
system and it has a flaw.  Let's say I want to be nice to the user
and let them override the default icon, so I don't give it a full path.
However I store all of my application information in a particular
directory.  How do I reconcile those?  I can't override the XBMLANGPATH
because the user may have set it.  If I use a full path then XBMLANGPATH
won't be used.  I can't require the user to put my directory in the
environment variable. Ideally there should be a call to add a new 
directory to the search path - this makes life much easier.

While I'm on the subject, there are a couple of other calls of use 
here.  One is when I already have a pixmap and want to add it (with
a name) to the cache.  Another is to check and see if something is
already in the cache.

Finally, and more critically.  For many of my dialogs I need to add
a few buttons, so I use a selection dialog and add a child (be real
nice if I could add a child to a message dialog - but anyway...).
In those dialogs I want to use one of the standard icons.  It took
me a *long* time to figure out why most of the time the icons
never showed up - but occasionally they would.  It turns out that
the icons are not put in the cache until the first time a message 
dialog is created.  This really ought to be made more global.  As it
is I now have the following call at the beginning of my code:

    XtDestroyChild(XmCreateMessageBox(parent, "", NULL, 0));

It looks pretty silly, but it does the trick.