/**
*** Convenience function to get colors
**/
Pixel GetPixel( Widget w, int r, int g, int b)
{
Display *dpy;
int scr;
Colormap cmp;
XColor clr;
dpy = XtDisplay(w);
scr = DefaultScreen(dpy);
cmp = DefaultColormap(dpy);
clr.red = (short)r;
clr.green = (short)g;
clr.blue = (short)b;
clr.flags = DoRed | DoGreen | DoBlue;
/**
*** Note that the default black pixel of the display and screen
*** is returned if the color could not be allocated.
**/
return(XAllocColor(dpy,cmp,&clr) ? clr.pixel : BlackPixel(dpy,scr));
}
The default white and black pixels are defined as
Pixel BlackPixel( Display *dpy, int screen);
Pixel WhitePixel( Display *dpy, int screen);
and will work with any screen as a fallback.
The index (Pixel) returned by this function is not guaranteed to be the
same every time the application runs. This is because the colormap could be shared
between applications requesting colors in different orders. Each entry is allocated
on a next-available-entry basis. Sometimes, if you overwrite an existing entry in
a cell, you might actually see a change in a completely different application. So
be careful.
Applications can query the RGB components of a color by calling the function
XQueryColor( Display *display, Colormap *cmp, Xcolor *clr);
For many colors at one time, use
XQueryColors( Display *display, Colormap *cmp,
Xcolor *clr, int number);
At this time the application can modify the RGB components. Then you can store
them in the colormap with the call
XStoreColor( Display *display, Colormap *cmp,XColor *clr);
Recall that X11 has some strange names for colors in the /usr/lib/rgb.txt
file. Applications can get the RGB components of these names with a call to
XLookupColor( Display *display, Colormap cmp,
char *name,XColor *clr, XColor *exact);
The name is the string to search for in the rgb.txt file. The returned
value clr contains the next closest existing entry in the colormap. The
exact color entry contains the exact RGB definition in the entry in rgb.txt.
This function does not allocate the color in the colormap. To do that, use the call
XAllocNamedColor( Display *display, Colormap cmp,
char *name, Xcolor *clr, XColor *exact);
A Pixmap is like a window, but is off-screen and therefore invisible to the user.
This is usually the same depth of the screen. You create a Pixmap with the call
XCreatePixmap (Display *dp,
Drawable dw,
unsigned int width,
unsigned int height,
unsigned int depth);
A drawable can be either a Window (on-screen) or a Pixmap (off-screen). Bitmaps
are Pixmaps of a depth of one pixel. Look in
/usr/include/X11/bitmaps
for a listing of some of the standard bitmaps.
The way to copy Pixmaps from memory to the screen is via the call to XCopyArea.
The prototype for this call is
XCopyArea( Display dp,
Drawable Src, Drawable Dst,
GC gc, int src_x, int src_y,
unsigned int width, unsigned int height,
int dst_x, int dst_y);
The caveat with this XCopyArea is that the depth of the Src
and Dst drawables have to be of the same depth. To show a bitmap on a screen
with depth greater than 1 pixel, you have to copy the bitmap one plane at a time.
This is done via the call
XCopyPlane( Display dp,
Drawable Src, Drawable Dst,
GC gc, int src_x, int src_y,
unsigned int width, unsigned int height,
int dst_x, int dst_y, unsigned long plane);
where the plane specifies the bit plane to which this one-bit-deep bitmap must
be copied. The actual operation is largely dependent on the modes set in the GC.
For example, to show the files in the /usr/include/bitmaps directory
that have three defined values for a sample file called gumby.h:
- gumby_bits = pointer to an array of character bits.
- gumby_height and gumby_width = integer height and width.
First, create the bitmap from the data using the XCreateBitmapFromData()
call. To display this one-plane-thick image, copy the image from this plane to plane
1 of the display. You can actually copy to any plane in the window. A sample call
could be set for copying from your Pixmap to the Widget's plane 1 in the following
manner:
XCopyPlane( XtDisplay(w), yourPixmap, XtWindow(w), gc,
0,0, your_height, your_width, 0,0,1);
where it copies from the origin of the Pixmap to the origin of plane 1 of the
window.
There are other functions for working with images in X. These include the capability
to store device-dependent images on disk and the Xpm format.
This chapter covered the following topics:
- The basics of writing Motif applications
- The special naming conventions in Motif and X
- Writing and compiling your first Motif application
- An overview of the Motif Widget hierarchy
- Working with various common Widgets
- Designing layouts
- Creating pop-up menus and menu bars
- Creating simple dialog boxes
- How to use the mouse in event handling
- How to use colors in X
- How to draw lines and points
This chapter could easily expand into a book. (Please, do not tempt me!) I have
only covered the basics of writing Motif applications. However, given the vast number
of tools in Linux, you can see how you can port any existing Motif application code
to and from a Linux machine. Similarly, a Linux machine can also prove to be a good
development platform for developing Motif applications.