[comp.windows.x] R4 Sun color cursor bug

rbd@lamont.ldgo.columbia.edu (roger davis) (01/14/90)

			  X Window System Bug Report
			    xbugs@expo.lcs.mit.edu


VERSION:
    R4

CLIENT MACHINE and OPERATING SYSTEM:
    Various Sun/3 and Sun/4 workstations running 4.0.3

DISPLAY TYPE:
    cgtwo0, cgfour0

WINDOW MANAGER:
    twm

AREA:
    Xlib/Xsun

SYNOPSIS:
    XCreatePixmapCursor, XDefineCursor

DESCRIPTION:
    When creating and installing a cursor with XCreatePixmapCursor()
    and XDefineCursor() on a color display, the cursor foreground and
    background colors are reversed.

REPEAT BY:

    Compile and run the following short program with
    % cc -o cursor cursor.c -lX11
    % cursor

    This program, which will run on any Sun monochrome or 8-bit color
    display, creates a 100x100 background-colored window with a small
    foreground-colored rectangle drawn in its center. An upper-left-pointing
    foreground-colored arrow cursor is installed.

    On a monochrome display where foreground is black and background
    is white, everything works properly -- the black arrow cursor is
    visible above the white background and invisible above the black
    foreground rectangle.

    On a color display, where foreground is set to green and background
    is set to red, this code breaks -- the arrow cursor is drawn in the
    red background color instead of the desired green foreground color,
    and is thus invisible above the red background and visible above the
    green foreground rectangle.

    If the fgxc and bgxc arguments to the XCreatePixmapCursor() call are
    swapped, the problem disappears on the color display. Unfortunately,
    this breaks on the monochrome display where the program worked
    properly to begin with.

    Under X11R3, this program works properly on both color and monochrome
    Sun displays.

    /*
       cursor.c -- demonstrates color cursor problem
    */
    #include <X11/Xlib.h>
    
    char *fgstr= "green";
    char *bgstr= "red";
    
    main()
    {
    	Display *dpy;
    	Window win;
    	Cursor curs;
    	Pixmap curspm;
    	unsigned long fgpix, bgpix;
    	XEvent event;
    	int screen;
    	unsigned long plane_mask;
    	Colormap cmap;
    	XColor fgxc, bgxc;
    	XGCValues gcv;
    	GC gc;
    
    	if ((dpy= XOpenDisplay((char *) 0)) == (Display *) 0)
    		exit(-1);
    	screen= DefaultScreen(dpy);
    	cmap= DefaultColormap(dpy, screen);
    
    	/* set up foreground and background */
    	if (DisplayCells(dpy, screen) > 2) {
    		if (XParseColor(dpy, cmap, fgstr, &fgxc) &&
    		    XParseColor(dpy, cmap, bgstr, &bgxc) &&
    		    XAllocColorCells(dpy, cmap, True, &plane_mask, 1, &bgpix, 1)) {
    			bgxc.pixel= bgpix;
    			XStoreColor(dpy, cmap, &bgxc);
    			fgxc.pixel= fgpix= bgpix | plane_mask;
    			XStoreColor(dpy, cmap, &fgxc);
    		}
    		else
    			exit(-1);
    	}
    
    	/* use black and white on a monochrome display */
    	else {
    		fgxc.pixel= fgpix= BlackPixel(dpy, screen);
    		bgxc.pixel= bgpix= WhitePixel(dpy, screen);
    	}
    
    	/* create window */
    	win= XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 100, 100, 100, 100, 2, fgpix, bgpix);
    
    	/* create and clear cursor pixmap */
    	curspm= XCreatePixmap(dpy, DefaultRootWindow(dpy), 16, 16, 1);
    	gcv.foreground= 0;
    	gc= XCreateGC(dpy, curspm, GCForeground, &gcv);
    	XFillRectangle(dpy, curspm, gc, 0, 0, 16, 16);
    
    	/* draw upper-left-pointing arrow into cursor pixmap */
    	gcv.foreground= 1;
    	gc= XCreateGC(dpy, curspm, GCForeground, &gcv);
    	XDrawLine(dpy, curspm, gc, 0, 0, 15, 15);
    	XDrawLine(dpy, curspm, gc, 0, 0, 0, 5);
    	XDrawLine(dpy, curspm, gc, 0, 0, 5, 0);
    
    	/* create and install new cursor */
    	XQueryColor(dpy, cmap, &fgxc);
    	XQueryColor(dpy, cmap, &bgxc);
    	curs= XCreatePixmapCursor(dpy, curspm, curspm, &fgxc, &bgxc, 0, 0);
    	XDefineCursor(dpy, win, curs);
    
    	/* create a GC to draw the rectangle */
    	gcv.foreground= fgpix;
    	gc= XCreateGC(dpy, win, GCForeground, &gcv);
    
    	XSelectInput(dpy, win, ExposureMask);
    	XMapWindow(dpy, win);
    
    	/* on exposure, draw a small filled rectangle with the foreground
    	   color in the middle of an area of background color to aid in
    	   the display of the otherwise invisible cursor */
    	for (;;) {
    		XNextEvent(dpy, &event);
    		if (event.type == Expose) {
    			XClearWindow(dpy, win);
    			XFillRectangle(dpy, win, gc, 30, 30, 40, 40);
    		}
    	}
    }

-- 
Roger Davis
Lamont-Doherty Geological Observatory
rbd@lamont.ldgo.columbia.edu

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (01/14/90)

    When creating and installing a cursor with XCreatePixmapCursor()
    and XDefineCursor() on a color display, the cursor foreground and
    background colors are reversed.

Not quite a correct statement (both colors are sometimes being allocated to
the same colormap entry, actually), but there's certainly a bug.  This is a
software cursor bug (so it won't show up on servers with hardware cursors).
The guy who wrote this code clearly didn't think hard enough, I'll have to
razz him.  I haven't come up with a trivial fix, but I'll note that if the
colors have been pre-allocated read-only in the colormap, it will work right.