motifdeveloper.com
Sponsored by IST Limited
Formerly MW3: Motif on the World Wide Web [MW3 Logo]
Last Updated
November 18, 2002
 


X-Designer - The Leading X/Motif GUI Builder - Click to download a FREE evaluation
 

motifdeveloper.com
Home
About the site
Bulletin Board
News Archive
OpenGroup News
Events
Search
Frequently Asked Questions
The Motif FAQ
X/Motif FAQs
General FAQs
Ask Antony
Latest Q & A
All Q & As
Submit Question
Tips & Pointers
Code Examples
Software
OpenMotif
Widget Sets
GUI Toolkits & Libraries
Motif suppliers
Non-commercial S/W
Commercial Software
Multimedia
Miscellaneous
Organizations
Docs & Pubs
X/Motif Newsgroups
Security
Internationalization
Feedback
Feedback Form
Contributors
 

How do I change the cursor from an arrow to a watch?

05-Jan-01 10:00 GMT

Question: I'm trying to change the cursor from an arrow to a watch, but I cannot find a call to do that.

Introduction

There are a number of ways to create and display cursors. In essence, a cursor is simply an X image (XImage) which follows the pointer. As such, it is possible to create a cursor out of just about anything which is XImage based. This includes arbitrary font characters, and bitmaps.

X has a built-in set of cursor types which are indeed implemented using a standard font. A Cursor as a type is just an opaque handle associated with the particular XImage.

You can have as many cursors as you like: simply install a particular cursor when needed. Note that cursors are inherited through the widget hierarchy: in many cases all that is required is to install a cursor on the shell widget representing the dialog where the cursor is needed.

Creating a Cursor from the Standard Font

The file <X11/cursorfont.h> defines a set of offsets into the Standard Cursor Font. In order to use and apply one of the standard cursors, it is necessary to perform two steps.

  • Firstly, the Cursor must be loaded into the X server
  • Secondly, the Cursor must be applied to the Window where it is required

Loading the Cursor

A Standard Font Cursor is loaded using the routine XCreateFontCursor(), which is formally defined as follows:

	void XCreateFontCursor (Display *display, int offset)

Here the offset parameter is an index into the set of standard font characters. For example, to load the watch cursor from the Standard Font, we simply look up the index associated with the watch cursor (XC_watch) in the <X11/cursorfont.h> file, and then apply the above routine. The following code is all that is required:

	#include <X11/cursorfont.h>

	...

	extern Display *display;


	Cursor watch = XCreateFontCursor (display, XC_watch) ;

Applying the Cursor to a Window

Once the Cursor has been created/loaded, we can now install it on a Window. The routine to perform this step is XDefineCursor(), which is formally specified as follows:

	void XDefineCursor (Display *display,
			    Window   window,
			    Cursor   cursor)

Typically, the two steps are wrapped up into a single function. For example, the following two routines can be used to set the cursor to a watch, and subsequently restore the cursor to the default (a left pointing arrow). Usually, the widget parameter is a shell widget, so that the watch is applied by default to the whole dialog.

	static Cursor watch_cursor  = (Cursor) 0 ;
	static Cursor normal_cursor = (Cursor) 0 ;

	void SetWatchCursor (Widget widget)
	{
	    if (watch_cursor == (Cursor) 0) {
		watch_cursor = XCreateFontCursor (XtDisplay(widget), XC_watch) ;
	    }

	    XDefineCursor (XtDisplay (widget), XtWindow (widget), watch_cursor) ;
	}

	void SetNormalCursor (Widget widget)
	{
	    if (normal_cursor == (Cursor) 0) {
		normal_cursor = XCreateFontCursor (XtDisplay (widget), XC_left_ptr) ;
	    }

	    XDefineCursor (XtDisplay(widget), XtWindow (widget), normal_cursor) ;
	}

There are other ways of going about this: instead of explicitly assigning the left pointer to a Window when restoring the "normal" cursor, it is also possible to undefine a cursor using the routine XUndefineCursor(), so that the cursor associated with a given Window is again inherited from its parent. XUndefineCursor() is specified as follows:

	void XUndefineCursor (Display *display, Window window)

Pixmap and Glyph Cursors

Cursors can be created out of any Font or Pixmap. The routine XCreateGlyphCursor() will create a cursor from a source and optionally a mask Font character (which do not have to be even in the same Font). XCreatePixmapCursor() is similar, except you can create a cursor out of a bitmap (or a couple of bitmaps, if using a mask). These routines are defined as follows:

	Cursor XCreatePixmapCursor (Display     *display,
				    Pixmap       source,
				    Pixmap       mask,
				    XColor      *foreground,
				    XColor      *background,
				    unsigned int hotspot_x,
				    unsigned int hotspot_y)

	Cursor XCreateGlyphCursor (Display     *display,
				   Font         source,
				   Font         mask,
				   unsigned int source_index,
				   unsigned int mask_index,
				   XColor      *foreground,
				   XColor      *background)

Since both utilities require the creation and manipulation of several X data types (XColor, Font, Pixmap), a complete example of each cannot really be given in the space available. A brief example of XCreateGlyphCursor() is however given below.

Colored Cursors

The color of a cursor can be modified through the routine XRecolorCursor(), defined as follows:

	void XRecolorCursor (Display *display,
			     Cursor   cursor,
			     XColor  *foreground,
			     XColor  *background)

An XColor is simply a structure describing the red, green, blue (RGB) components of a color. Suppose we have an arbitrary Cursor, and a couple of Pixels. We could color the cursor by some code similar to the following example fragments:

	/* A routine to (roughly) convert from a Pixel to an XColor */
	void PixelToXColor(Display *display, Pixel pixel, XColor *xp)
	{
	    Colormap cmap = XDefaultColormap(display, DefaultScreen(display)) ;

	    xp->pixel = pixel ;
	    xp->flags = DoRed | DoGreen | DoBlue ;

	    XQueryColor(display, cmap, xp) ;
	}

	/* A routine to color a Cursor, given a couple of Pixels */
	void ColorCursor(Display *display, Cursor cursor, Pixel fg, Pixel bg)
	{
	    XColor fg_internal ;
	    XColor bg_internal ;

	    PixelToXColor(display, fg, &fg_internal) ;
	    PixelToXColor(display, bg, &bg_internal) ;

	    XRecolorCursor(display, cursor, &fg_internal, &bg_internal) ;
	}

Note that the Standard Cursor Font routine XCreateFontCursor() creates cursors which are black and white. However, it is possible to write a routine to create a cursor from the Standard Cursor Font in a particular color, since XCreateFontCursor() is nothing more than a wrapper onto XCreateGlyphCursor(). For example, we could define a new routine as follows:

	Cursor CreateColoredStandardCursor (Display *display, int offset, XColor *fg, XColor *bg)
	{
	    /*
	    ** The Standard Cursor Font contains the shape glyph followed by the mask glyph.
	    ** This is why definitions in <X11/cursorfont.h> increment by 2.
	    */

	    if (display->cursor_font == None) {
		/* Load the Standard Cursor Font */

		display->cursor_font = XLoadFont (display, "cursor") ;

		if (display->cursor_font == None) {
		    return None ;
		}
	    }

	    return XCreateGlyphCursor (display,
				       display->cursor_font,  /* Shape Font */
				       display->cursor_font,  /* Mask  Font */
				       offset,                   /* Shape Character Offset */
				       offset + 1,               /* Mask Character Offset */
				       fg,
				       bg) ;
	}

Freeing Cursors

Like all resources consumed by the X server and clients, Cursors should be deallocated when no longer required. The routine XFreeCursor() performs this task, and it is formally defined as follows:

	void XFreeCursor (Display *display, Cursor cursor)

Caveat

Note that a Cursor is applied to a particular Window, and so that it follows that it is not possible to define cursors for individual Gadgets, since they inherit a Window from their parent. Supposedly you could track pointer motion in the Gadget's parent, and define a cursor for the parent when the pointer is "over" a Gadget, although since the Manager class is already packed up with all sorts of event mechanisms as part of the Gadget implementation, this is more than likely to be somewhat expensive.

Secondly, depending on the nature of your application and environment, you may find that you have to explicitly flush the X queue (XFlush()) after defining a Cursor on a Window, so that the effect is immediate. XFlush() is specified as follows:

	void XFlush (Display *display)

Bibliography

The Standard Cursor Font is listed in a number of places, including the following:

	Xlib Reference Manual,
	Edited by Adrian Nye,
	O'Reilly and Associates, Inc.,
	ISBN 1-56592-006-6
	Buy it from Amazon.com or Amazon.co.uk

In particular, you should look at Appendix I, which is on page 891 in the Third Edition.

 


Sponsored by X-Designer - The Leading X/Motif GUI Builder - Click to download a FREE evaluation

 

Goto top of page

 

[IST Limited]
IST Limited is the
proud sponsor of motifdeveloper.com.
 

Thanks to all the contributors to these pages.

Privacy Policy

 
"Motif" is a registered trademark of The Open Group. All other trademarks are the property of their respective owners.

Some articles/papers here have their own copyright notice. All other information is copyright ©1999-2008 IST Limited

[CommerceOne] MW3 site originally by Ken Sall of Commerce One (formerly Century Computing).