lemke@SUN.COM (Dave Lemke) (10/05/88)
Having just seen the dozenth or so program that uses visuals incorrectly, I think its about time to try to make the X community pay closer attention to the problem. The MIT X servers all expose dynamic PseudoColor visuals as the default visual for multi-plane displays. This has led to people using contructs such as: if (DisplayCells(dpy) > 2) { /* must be color */ cmap = XCreateColormap(dpy, XDefaultRootWindow(dpy), XDefaultVisual(dpy, XDefaultScreen(dpy)), AllocNone); XAllocColorCells(dpy, cmap, .....); } This is WRONG. It will work on MIT X servers because of implementation details, but it is not a correct usage of the X protocol, and will fail on servers that have different implementation details. 1) More than 2 display cells doesn't mean you're on a color display. It may be an 4 bit static gray scale, for example. DisplayPlanes is also commonly used, and can also be the wrong thing in this situation. 2) Even if it was a color display, XAllocColorCells needs a colormap with a dynamic visual, and since the colormap was created with the default, the code will fail on servers where the default visual is a static visual. This often doesn't show up until the client tries to do the first StoreColors into the color cells, at which point there's an access error and Xlib (with the default error handler) exits the client. The proper solution is to use the Visual info calls described in section 10.8 of the Xlib manual. The exact usage depends on what the appication really needs dynamic color cells for, but if the client simply wants a dynamic visual, it could do the following: visinfo = (XVisualInfo *) 0; vlist = XGetVisualInfo(dpy, VisualNoMask, &vinfo_template, &num_vis); /* find the first dynamic visual and break out of the loop */ for (v = vlist; v < vlist + num_vis; v++) /* dynamic classed visuals are odd-numbered - see X.h */ if (v->class & 0x1) { visinfo = v; break; } if (visinfo == (XVisualInfo *) 0) [ fprintf(stderr,"couldn't get dynamic visual - exiting\n"); exit(0); } /* make the colormap with the proper visual */ cmap = XCreateColormap(dpy, XDefaultRootWindow(dpy), visinfo->visual, AllocNone); /* etc... */ Be aware also that all windows that wish to use this colormap also need to use the matched visual -- CopyFromParent may not work. People need to read the manual carefully. X is only portable if you make it portable. Its very easy to make the mistake of taking shortcuts to take advantage of implementation details which will cause your code to break on servers other than the one you developed the code on. Dave Lemke lemke@sun.com PS. and BlackPixel isn't necessarily 0, either...