/* * Copyright status: This file is in the public domain. In * jurisdictions where a copyright holder cannot explicitly release IP * into the public domain, this should be interpreted as the closest * available approximation, probably something like "you are granted a * license to use this file in any way you see fit". * * This is a tiny test program to test for a common X server bug. * * The bug is that creating a pixmap cursor with a mask of None (which * is defined to display all pixels of the source) effectively extends * the source pixmap to the right with server-dependent data, * typically background pixels, to a width such as 16 or 32 pixels. * While this is not, strictly, contrary to the spec (cursor * components "may be transformed arbitrarily to meet display * limitations"), the same server typically does the right thing when * an explicit mask bitmap full of 1s is supplied as the mask, * demonstrating that there is no actual need to mangle the pixmap, * which is why I call this a bug. * * Compile this with whatever options are needed to find your X include * files and libraries, typically something like * * cc -o cursor-bug cursor-bug.c -lX11 * * (depending on your system, you may need a -I option as well). When * you run it you should get a 600x200 window. The middle third * should be black; the left and right thirds should be a checkerboard * grey (alternate pixels white and black - whether this looks like a * checkerboard or a uniform grey or what depends on your display and * in some cases your eyes). Each of the grey areas uses a 3x16 * cursor which is a 1x14 white vertical line with a black surround. * The left third uses an explicit pixmap full of 1s as the mask when * creating its cursor; the right third uses None for its. If the * cursor looks the same over the left and right thirds, great; the * bug isn't present in your server, or at least isn't manifesting for * you. If the left one looks fine but the right one is extended to * the right, typically with black, you've got the bug. */ #include #include #include extern const char *__progname; static Display *disp; static Screen *scr; static int depth; static Window rootwin; static GC wingc; static GC bitgc; static Colormap cmap; static Pixmap bgpm; static Window win; static Window goodwin; static Window badwin; static XColor cbg; static XColor cfg; static Pixmap cdata; static Pixmap cmask; static Cursor goodcurs; static Cursor badcurs; static void setup_colour(XColor *c, unsigned short int r, unsigned short int g, unsigned short int b) { c->red = r; c->green = g; c->blue = b; c->flags = DoRed | DoGreen | DoBlue; if (! XAllocColor(disp,cmap,c)) { fprintf(stderr,"%s: can't XAllocColor #%04hx%04hx%04hx\n",__progname,r,g,b); exit(1); } } int main(void); int main(void) { XSetWindowAttributes attr; disp = XOpenDisplay(0); scr = XDefaultScreenOfDisplay(disp); depth = XDefaultDepthOfScreen(scr); rootwin = XRootWindowOfScreen(scr); wingc = XDefaultGCOfScreen(scr); cmap = XDefaultColormapOfScreen(scr); setup_colour(&cbg,0,0,0); setup_colour(&cfg,65535,65535,65535); bgpm = XCreatePixmap(disp,rootwin,2,2,depth); XSetForeground(disp,wingc,cbg.pixel); XDrawPoint(disp,bgpm,wingc,0,0); XDrawPoint(disp,bgpm,wingc,1,1); XSetForeground(disp,wingc,cfg.pixel); XDrawPoint(disp,bgpm,wingc,0,1); XDrawPoint(disp,bgpm,wingc,1,0); cdata = XCreatePixmap(disp,rootwin,3,16,1); cmask = XCreatePixmap(disp,rootwin,3,16,1); bitgc = XCreateGC(disp,cdata,0,0); XSetForeground(disp,bitgc,0); XFillRectangle(disp,cdata,bitgc,0,0,3,16); XSetForeground(disp,bitgc,1); XFillRectangle(disp,cdata,bitgc,1,1,1,14); XFillRectangle(disp,cmask,bitgc,0,0,3,16); goodcurs = XCreatePixmapCursor(disp,cdata,cmask,&cfg,&cbg,1,8); badcurs = XCreatePixmapCursor(disp,cdata,None,&cfg,&cbg,1,8); attr.background_pixel = cbg.pixel; attr.colormap = cmap; win = XCreateWindow(disp,rootwin,0,0,600,200,0,depth,InputOutput, CopyFromParent,CWBackPixel|CWColormap,&attr); attr.background_pixmap = bgpm; attr.cursor = goodcurs; goodwin = XCreateWindow(disp,win,0,0,200,200,0,depth,InputOutput, CopyFromParent,CWBackPixmap|CWCursor,&attr); attr.background_pixmap = bgpm; attr.cursor = badcurs; badwin = XCreateWindow(disp,win,400,0,200,200,0,depth,InputOutput, CopyFromParent,CWBackPixmap|CWCursor,&attr); XMapSubwindows(disp,win); XMapRaised(disp,win); while (1) { XEvent e; XNextEvent(disp,&e); } }