Late Night's Top Ten X11 Questions Dave Lemke (lemke@ncd.com) Stuart Marks (smarks@sun.com) 1. Why doesn't my program draw anything? I create the window and draw into it, but it's always blank. In order to get a window on the screen, you must map it first, using the XMapWindow() call. Drawing into a window and then mapping it won't work in most cases. 1a. But I do map the window before drawing into it, and the window is still blank. The problem here is that if the window is a child of the root window, XMapWindow() doesn't actually map the window; it sends a message to the window manager asking it to map the window. If you having drawing requests right after the XMapWindow() call, they will probably be processed before the window manager has actually mapped the window. In order to get around this delayed mapping effect, you must wait for an Exposure event from the server. This event indicates that your window is on the screen and ready to receive graphics. In general, you should always draw in response to Exposure events. 2. Why does my program display in inverse-video on some servers? You're assuming that 1 is black and 0 is white or vice-versa. The relationship between pixels 0 and 1 and the colors black and white is implementation-dependent. They may be reversed, or they may not even correspond to black and white at all. For instance, an 8-bit grayscale server might choose to have 0 be black and 255 be white. If you want to draw in black and white, set the foreground and background pixels in the GC using BlackPixel() and WhitePixel() macros instead of 0 and 1. This will help ensure that your application is portable amongst different servers. 3. Can I get the background pixel/pixmap of a window using GetWindowAttributes? No. Once set, the background pixel or pixmap of a window cannot be re-read by clients. The reason for this is that a client can create a pixmap, set it to be the background pixmap of a window, and then free the pixmap. The window keeps this background, but the pixmap itself is destroyed. If you're sure a window has a background pixel (not a pixmap), you can use XClearArea() to clear a region to the background color and then use XGetImage() to read back that pixel. However, this action alters the contents of the window, and it suffers from race conditions with exposures. 4. Why doesn't my program get keystrokes? I select input for KeyPress events, but my program never gets them. (Alternatively, my program works under uwm, but not under ...) The window manager controls how the input focus is transferred from one window to another. In order to get keystrokes, your program must ask the window manager for the input focus. To do this, you must set up what are called "hints" for the window manager. If your applications is Xlib-based, you can use something like the following: XWMHints wmhints; ... wmhints.flags = InputHint; wmhints.input = True; XSetWMHints(dpy, window, &hints) If your application is based on the Xt Intrinsics, you can use something like the following: Arg arglist[MAXARGS]; Cardinal nargs = (Cardinal) 0; ... XtSetArg(arglist[nargs++], XtNinput, TRUE); ... XtCreatePopupShell(...); 5. I encountered a breakpoint when I was debugging a program, and now everything is hung. I can still move the mouse around on the screen, but I can't type anything or get any mouse clicks to do anything. HELP! The debugger stopped your program while it was in the middle of what is called a "grab". There are various flavors of grabs, but the important effect of all of them is that the grabbing client gets serviced at the expense of other clients in the system. This kind of feature is necessary for doing highly interactive things like pop-up menu tracking. The problem arises because the program you're debugging grabbed some server resource, such as the keyboard, and then hit a breakpoint. The debugger is sharing the same resource with the debugged program, which has grabbed the keyboard away from the debugger. You can't type debugger commands to continue the program, and thus you're stuck. To get around this problem, you might try to iconify the debugged program's window by using the mouse or the keyboard, whichever isn't grabbed. When the window goes iconic, any grabs on that window will be deactivated by the server. If the debugged program is in the middle of a server grab, you're really stuck. A server grab grabs *all* of the server's resources. Thus, you have to attack the problem by going outside of the server. Killing the debugged program and its debugger will release the grab and get you unstuck, but you obviously can't continue debugging. You might also try making a special debugging-mode option to your program so that it doesn't grab the server while you're debugging it. If you can't do that, your only choice is to debug the offending program from somewhere outside the server it's displaying on, e.g. another workstation or a terminal. If you're running X11/NeWS from Sun, you can run a SunView shelltool on top of the server; it will be unaffected by server grabs. 6. How do I do XOR drawing to work properly? It doesn't work at all on some servers, and I get funny colors on other servers. It depends on what you mean by "properly." For the most part, when you do XOR drawing, you want to do some transient animation that won't disturb the contents of the window. You can do this with XOR because the first XOR operation will change the contents to something different, and then the second XOR operation will restore the original contents. The trick is to set up the GC source pixel so that the "something different" contrasts properly with the surroundings. Confusion arises because XOR drawing uses the GC foreground field as the source pixel for the XOR operation. If you use your actual foreground pixel as the source for XOR, the result will probably be something off in a random section of whatever colormap is installed. Unless you've set up and installed your own colormap, the color you end up with will be some unlikely value over which you don't have any control. What's often appropriate is to interchange the foreground color with the background color. If your graphics has the concept of a foreground and a background, you can do XOR animation that switches foreground and background by setting the GC foreground pixel to the XOR of the foreground and background pixels. In C, this would be XGCValues gcvalues; gcvalues.foreground = fgpixel ^ bgpixel; XChangeGC(dpy,gc,GCForeground,&gcvalues); For monochrome graphics, you can use gcvalues.foreground = BlackPixel(dpy,DefaultScreen(dpy))^WhitePixel(dpy,DefaultScreen(dpy)); 7. I create and draw into a pixmap, but when I copy it to the screen with XCopyArea, I get nothing but garbage. The initial contents of pixmaps is undefined. This means that most servers will allocate the memory and leave around whatever happens to be there -- which is usually garbage. You probably want to clear the pixmap first using XFillRectangle() with an alu function of GXcopy and a foreground pixel of whatever color you want as your background (or 0L if you are using the pixmap as a mask). 8. My color program always fails on XAllocColorCells(). But it works on other servers. Your program is assuming that the default colormap for the screen is a dynamic one, that is, one out of which you can allocate nonshared color cells via XAllocColorCells(). Some servers have a static colormap as their default colormap, so XAllocColorCells() will fail. You have several alternatives. One possibility is to change your program to use XAllocColor(). You won't be able to alter the color once you've allocated it, but you may not have needed to do that in the first place. You should use XAllocColor() in preference to XAllocColorCells() if you simply want to get colors on the screen. The reason is that XAllocColor() allows the same colors to be shared amongst different clients. If you really need to allocate and change colormap cells, then you still need to use XAllocColorCells() or XAllocColorPlanes(). For these calls to work, you must search the server's visual list for a visual that supports dynamic colormaps. Then, you must create a colormap against this visual and allocate colors out of this colormap. If the server doesn't have any dynamic visuals, your program simply won't work on this server. If you successfully create and use your own dynamic colormap, you'll also have to create a window using the same visual and set that window's colormap attribute to be your newly created colormap. Don't forget to set up WM_COLORMAP_WINDOWS so the window manager can install your colormap. 9. My program worked fine in R3, but fails in X11R4 with an error in ChangeWindowAttributes. Also, my Andrew and Interviews code stopped working with the same error. A likely problem is the value given to a window's do_not_propagate mask. R3 allowed bogus values to be set, and early version of both Andrew and Interviews did just that. X11R4 and several productized servers catch this error and complain. The events that can be suppressed are: KeyPress, KeyRelease, ButtonPress, ButtonRelease, PointerMotion, ButtonMotion and Button[1-5]Motion 10. I set my windows to have BackingStore, yet they still get exposures. There are several things that can be going on here. The most important thing to remember is that backing store is a hint. You may have asked for backing store on your window, but the server may not have enough memory to service your request. If this is the case, the server will go ahead and create and window without backing store, and then send you an Exposure event to tell you to draw into it. Other behavior that could possibly be counterintuitive is that, if you create a window with BackingStore == Always, you will get an Exposure event as soon as you create the window. The server does this to let you know that the initial contents of the window need to be filled. It does this even before you have mapped the window. Some servers will throw away backing store if they start running out of memory. A window may start out with backing store, but then have it thrown away by the server because of a memory shortage. This window will then start getting Exposure events. Another possibility is a window manager with a 'Refresh' function. Some window managers implement this function by doing a ClearArea with the Exposure flag set. This will force the server the send an Exposure event, even if the window still has backing store. The bottom line is that clients must *always* be prepared to repaint their windows in response to Exposure events. Backing store is a hint, and it is only useful to reduce the number of Exposures on the window; it doesn't guarantee that none will ever occur. If you need to keep an image in the server, but not on the screen, use pixmaps. [@(#)answers.txt 1.3 89/12/15]