From: dbl@ics.com (David B. Lewis) Newsgroups: comp.windows.x,news.answers,comp.answers Subject: comp.windows.x Frequently Asked Questions (FAQ) 6/6 Date: 11 Apr 1995 13:37:36 GMT Organization: ICS Approved: news-answers-request@MIT.Edu Expires: Sun, 14 May 1995 00:00:00 GMT Message-ID: <3me0n0$qeq@ics.com> Reply-To: faq%craft@uunet.uu.net (X FAQ maintenance address) Summary: useful information about the X Window System Archive-name: x-faq/part6 Last-modified: 1995/04/10 ---------------------------------------------------------------------- Subject: 120) Why can't I link to the Xlib shape routines? When I try to compile certain programs, I get the following link error: Undefined: _XShapeQueryExtension _XShapeCombineMask These routines are actually part of the Shape Extension to X (SHAPE) which was introduced in the X11R4 distribution and allows non-rectangular windows. Like the other sample server extensions, the shape extension will only run on a server which supports it. Pre-X11R4 servers, as well as many vendor-supplied servers, do not support the shape extension, in which case they will display rectangular windows anyway. In order to use the shape extension, you must link to the library libXext.a. In the X11R4 distribution, this library and the associated includes will be in the mit/extensions directory. If you do not have these files, do not despair: many freeware programs which use the shape extension can also be compiled without it by removing the -DSHAPE define from the Makefile; you can probably do this and compile successfully against your older vendor-supplied X libraries. [from John B. Melby, melby%yk.fujitsu.co.jp@uunet.uu.net, 3/91] ---------------------------------------------------------------------- Subject: 121) What are these problems with "_XtInherit not found" on the Sun? When I link a X program that I wrote on a SunOS 4.0.3 or 4.1 machine I get the error "ld.so: symbol not found _XtInherit". What you are seeing is a side-effect of a kludge in the R4 libXt.a to get Sun shared libraries working. Apparently, you can't share a function that is both called and compared, as _XtInherit is. This was handled by putting _XtInherit in the same file as a function that is always used, thereby guaranteeing that it would be loaded -- that is, in Initialize.c, where XtToolkitInitialize() and XtInitialize() reside. These routines would normally be called. You are probably seeing this error because your program is not a normal Xt-based program and does not call XtToolkitInitialize() anywhere. 1) it may be a program that uses Xt functions but never opens a connection to the X server. [OSF/Motif's 1.1.0 UIL had this problem; it called XtMalloc() and other Xt functions.] The solution is to add the call to your program; the function does not have to be executed, just linked in. 2) alternatively, your program doesn't need any Xt functions and is correct in not calling XtToolkitInitialize() -- it may be an Xlib or XView program. In this case, you can remove -lXt from your link command. It should not be necessary to link the shared libraries statically, although this will certainly solve the problem. [from Jordan Hayes (now jordan@MooreNet.COM) and Danny Backx (db@sunbim.be); 11/90] You may also see this error compiling X11R5 programs on a SunOS 4.1.3 machine; be sure to set OSTeenyVersion to 3 in the config/sun.cf file. ---------------------------------------------------------------------- Subject: 122) TOPIC: PROGRAMMING PROBLEMS AND PUZZLES ---------------------------------------------------------------------- Subject: 123) Why doesn't my program get the keystrokes I select for (sic)? 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, &wmhints) If your application is based on the Xt Intrinsics, you can set the XtNinput resource to be True (as you probably want to in any case); if you don't have source, you can start up the application with the resource '*input:True'. Certain window managers, notably dxwm and olwm, are very picky about having this done. If you are using Sun's OpenWindows olwm, you can also add this resource to your defaults file to use clients that aren't ICCCM-compliant. OpenWindows.FocusLenience: true [mostly courtesy Dave Lemke of NCD and Stuart Marks of Sun] ---------------------------------------------------------------------- Subject: 124) How do I deiconify a window? To de-iconify a window, map it with XMapWindow(). To iconify a window, use XIconifyWindow(). ---------------------------------------------------------------------- Subject: 125) How do I figure out what window manager is running? You can't reliably tell; whatever mechanism you could use could be spoofed in any case. For most cases, you shouldn't care which window manager is running, so long as you do things in an ICCCM-conformant manner. There are some cases in which particular window managers are known to do things wrong; checking for particular hints placed on the window by the window manager so that you can sidestep the problem may be appropriate in these cases. Alternatively, it may be appropriate to determine which window manager is running in order to take advantage of specific *added* features (such as olwm's push-pin menus) in order to give your program *added* functionality. Beware of usurping the window manager's functions by providing that functionality even when it is missing; this surely leads to future compatibility problems. ---------------------------------------------------------------------- Subject: 126) Is there a skeleton X program available? There is no general framework such as the TransSkel program for the Macintosh which handles lots of the odds and ends and overhead of development under a window system and which can be used as a platform for additional development. In X, the problem is typically solved by using an interactive application builder tool or by using cut&paste on existing X applications. Good applications which you might look to manipulate when you want to "test just this one little thing" include contrib/clients/xskel, a simple R4 program that puts up a window and allows sketching in it and offers a starting point for quick hacks, the Xaw examples in the examples/ directory in the R3 and R4 distributions, and the Xlib "Hello World" example in the R3 doc/HelloWorld and R4 doc/tutorials/HelloWorld; an updated version of this program which uses R4 Xlib calls and current ICCCM conventions was posted in 2/90 to comp.windows.x by Glenn Widener of Tektronix. [3/90] In addition, a sample Xt program (for Xaw or Xm) by Rainer Klute showing how to open multiple displays and how to catch a broken display connection is available on ftp.x.org in contrib/mdisp.tar.Z. [4/92] A sample multi-display Xt/Xaw program by Oliver Jones is on ftp.x.org in contrib/MultiUserVote.tar.Z. (See also his article in The X Resource, Issue 3, "Multi-User Application Software Using Xt".) ---------------------------------------------------------------------- Subject: 127) How can I incorporate an Xlib program in my Xt program? As older Xlib programs are ported to Xt it often makes sense to preserve their Xlib-ness while still having Xt-based menus, scrollbars, and other GUIisms of current Xt toolkits. The basic problem in merging the two models is in the event-delivery mechanism. In an Xt program, the application enters an infinite loop in XtAppMainLoop() and Xt thereafter dispatches events to widgets without the application's intervention; in contrast, Xlib programs typically track the set of events they are interested in and the possible windows on which those events can occur and hence call XNextEvent directly and then determine what action to take on the event received. One possible solution may be to widgetize the Xlib application. A faster solution is probably to break XtAppMainLoop() into its components: void XtAppMainLoop(app) XtAppContext app; { XEvent event; for (;;) { XtAppNextEvent(app, &event); XtDispatchEvent(&event); } } and then change the dispatch call to be something like if (!XtDispatchEvent(&event)) dispatch_xlib_events(); That is, if Xt isn't interested in dispatching the event, it must be an event on one of the windows created via the code incorporated from the Xlib program and can be dispatched in the same way as in the original program. ---------------------------------------------------------------------- Subject: 128) Why does XtGetValues not work for me (sic)? The XtGetValues interface for retrieving resources from a widget is sensitive to the type of variable. Your code may be doing something like this: { Arg args[3]; int i; int sensitive; /* oops; wrong data type */ i=0; XtSetArg (args[i], XtNsensitive, &sensitive); i++; XtGetValues(widget, args, i ); ... } But XtNsensitive is a Boolean, which on most machines is a single byte; declaring the variable "sensitive" as Boolean works properly. This problem comes up often when using particular toolkits that redefine the Xt types Dimension and Position; code that assumes they are int will have similar problems if those types are actually short. In general: you are safe if you use the actual type of the resource, as it appears in the widget's man page. [11/90] ---------------------------------------------------------------------- Subject: 129) Why don't XtConfigureWidget/XtResizeWidget/XtMoveWidget work? You're probably trying to use these functions from application code. They should be used only internally to widgets; these functions are for a parent Composite widget to change the geometry of its children. An application which calls XtMoveWidget, for example, effectively defeats geometry negotiation and the Composite parent's internal state (if any) will no longer be correct. (The Xt specification goes into more detail.) The only way for your application to request a geometry change for a widget is to issue an XtSetValues call setting some of the geometry resources. Although this call will result in the widget-internal functions' being called, your application code must use the standard XtSetValues interface or risk the widgets' data becoming corrupted. Note that functions defined in , as these are, are typically reserved for use by widgets. Other promising functions, XtMakeGeometryRequest() and XtMakeResizeRequest(), are also for use only by widgets, in this case by a child to request a change from its parent. The Xlib calls XMoveWindow() and XResizeWindow() should similarly be avoided; they shouldn't be used to change XtNx, XtNy, XtNwidth, or XtNheight. ---------------------------------------------------------------------- Subject: 130) Why isn't there an XtReparentWidget call like XReparentWindow? Although there are various details of the current implementation of the Xt internals which make reparenting difficult, the major reason that no such call exists is that it remains undefined what the set of resources for the "new" widget should be. Resources are typically set based on the location in the instance hierarchy; what resources should change if the instance moves? What should happen to the widget's children? And by the time such semantics are defined, there would probably be little advantage over destroying the old widget and creating a new widget in the correct location with the desired resources, as setting the resources correctly is the majority of work in creating a new widget. Note that reparenting is possible in the OI toolkit. ---------------------------------------------------------------------- Subject: 131) I'm writing a widget and can't use a float as a resource value. Float resources are not portable; the size of the value may be larger than the size of an XtPointer. Try using a pointer to a float instead; the Xaw Scrollbar float resources are handled in this way. ---------------------------------------------------------------------- Subject: 132) Is this a memory leak in the X11R4 XtDestroyWidget()?! Yes. This is the "unofficial" fix-19 for the X11R4 Destroy.c: *** Destroy.c.1.37 Thu Jul 11 15:41:25 1991 --- lib/Xt/Destroy.c Thu Jul 11 15:42:23 1991 *************** *** 1,4 **** --- 1,5 ---- /* $XConsortium: Destroy.c,v 1.37 90/09/28 10:21:32 swick Exp $ */ + /* Plus unofficial patches in revisions 1.40 and 1.41 */ /*********************************************************** Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, *************** *** 221,239 **** */ int i = 0; ! DestroyRec* dr = app->destroy_list; while (i < app->destroy_count) { if (dr->dispatch_level >= dispatch_level) { Widget w = dr->widget; if (--app->destroy_count) bcopy( (char*)(dr+1), (char*)dr, ! app->destroy_count*sizeof(DestroyRec) ); XtPhase2Destroy(w); } else { i++; - dr++; } } } --- 222,245 ---- */ int i = 0; ! DestroyRec* dr; while (i < app->destroy_count) { + + /* XtPhase2Destroy can result in calls to XtDestroyWidget, + * and these could cause app->destroy_list to be reallocated. + */ + + dr = app->destroy_list + i; if (dr->dispatch_level >= dispatch_level) { Widget w = dr->widget; if (--app->destroy_count) bcopy( (char*)(dr+1), (char*)dr, ! (app->destroy_count - i) * sizeof(DestroyRec) ); XtPhase2Destroy(w); } else { i++; } } } [from Donna Converse, converse@x.org] ---------------------------------------------------------------------- Subject: 133) Is this a memory leak in the X11R4 deletion of work procs?! Apparently the X11R4 NextEvent.c`CallWorkProc fails to properly replace the work proc record back on the free list correctly. if (delete) { w->next = freeWorkRecs; freeWorkRecs = w->next; /* should be =w; */ } ---------------------------------------------------------------------- Subject: 134) Why does the process size of my X programs go up,up,up? Using "ps" may not show any decrease in memory size after a malloc/free pair. With most vendors' implementations of memory managers, the call to free does not return memory to the operating system; it is probably maintained on a free list for the process. In addition, ps may not be an accurate report of current memory usage requirements. ---------------------------------------------------------------------- Subject: 135) Are callbacks guaranteed to be called in the order registered? Although some books demonstrate that the current implementation of Xt happens to call callback procedures in the order in which they are registered, the specification does not guarantee such a sequence, and supplemental authoritative documents (i.e. the Asente/Swick volume) do say that the order is undefined. Because the callback list can be manipulated by both the widget and the application, Xt cannot guarantee the order of execution. In general, the callback procedures should be thought of as operating independently of one another and should not depend on side-effects of other callbacks operating; if a seqence is needed, then the single callback to be registered can explicitly call other functions necessary. [4/92; thanks to converse@x.org] ---------------------------------------------------------------------- Subject: 136) Why doesn't XtDestroyWidget() actually destroy the widget? XtDestroyWidget() operates in two passes, in order to avoid leaving dangling data structures; the function-call marks the widget, which is not actually destroyed until your program returns to its event-loop. ---------------------------------------------------------------------- Subject: 137) How do I query the user synchronously using Xt? It is possible to have code which looks like this trivial callback, which has a clear flow of control. The calls to AskUser() block until answer is set to one of the valid values. If it is not a "yes" answer, the code drops out of the callback and back to an event-processing loop: void quit(Widget w, XtPointer client, XtPointer call) { int answer; answer = AskUser(w, "Really Quit?"); if (RET_YES == answer) { answer = AskUser(w, "Are You Really Positive?"); if (RET_YES == answer) exit(0); } } A more realistic example might ask whether to create a file or whether to overwrite it. This is accomplished by entering a second event-processing loop and waiting until the user answers the question; the answer is returned to the calling function. That function AskUser() looks something like this, where the Motif can be replaced with widget-set-specific code to create some sort of dialog-box displaying the question string and buttons for "OK", "Cancel" and "Help" or equivalents: int AskUser(w, string) Widget w; char *string; { int answer=RET_NONE; /* some not-used marker */ Widget dialog; /* could cache&carry, but ...*/ Arg args[3]; int n = 0; XtAppContext context; n=0; XtSetArg(args[n], XmNmessageString, XmStringCreateLtoR(string, XmSTRING_DEFAULT_CHARSET)); n++; XtSetArg(args[n], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL); n++; dialog = XmCreateQuestionDialog(XtParent(w), string, args, n); XtAddCallback(dialog, XmNokCallback, response, &answer); XtAddCallback(dialog, XmNcancelCallback, response, &answer); XtAddCallback(dialog, XmNhelpCallback, response, &answer); XtManageChild(dialog); context = XtWidgetToApplicationContext(w); while ((RET_NONE == answer) || XtAppPending(context)) XtAppProcessEvent (context, XtIMAll); XtDestroyWidget(dialog); /* blow away the dialog box and shell */ return answer; } The dialog supports three buttons, which are set to call the same function when tickled by the user. The variable answer is set when the user finally selects one of those choices: void response(w, client, call) Widget w; XtPointer client; XtPointer call; { int *answer = (int *) client; XmAnyCallbackStruct *reason = (XmAnyCallbackStruct *) call; switch (reason->reason) { case XmCR_OK: *answer = RET_YES; /* some #define value */ break; case XmCR_CANCEL: *answer = RET_NO; break; case XmCR_HELP: *answer = RET_HELP; break; default: return; } } and the code unwraps back to the point at which an answer was needed and continues from there. Note that modifications are needed to handle receiving WM_DELETE_WINDOW on the window; possibly WM_DELETE_WINDOW can be handled by setting the "answer" variable. [Thanks to Dan Heller (now argv@z-code.com); note that the code in his book caches the dialog but neglects to make sure that the callbacks point to the current automatic "answer".] ---------------------------------------------------------------------- Subject: 138) How do I determine the name of an existing widget? I have a widget ID and need to know what the name of that widget is. Users of R4 and later are best off using the XtName() function, which will work on both widgets and non-widget objects. If you are still using R3, you can use this simple bit of code to do what you want. Note that it depends on the widget's internal data structures and is not necessarily portable to future versions of Xt, including R4. #include #include String XtName (widget) Widget widget; /* WILL work with non-widget objects */ { return XrmNameToString(widget->core.xrm_name); } [7/90; modified with suggestion by Larry Rogers (larry@boris.webo.dg.com) 9/91] ---------------------------------------------------------------------- Subject: 139) Why do I get a BadDrawable error drawing to XtWindow(widget)? I'm doing this in order to get a window into which I can do Xlib graphics within my Xt-based program: > canvas = XtCreateManagedWidget ( ...,widgetClass,...) /* drawing area */ > ... > window = XtWindow(canvas); /* get the window associated with the widget */ > ... > XDrawLine (...,window,...); /* produces error */ The window associated with the widget is created as a part of the realization of the widget. Using a window id of None ("no window") could create the error that you describe. It is necessary to call XtRealizeWidget() before attempting to use the window associated with a widget. Note that the window will be created after the XtRealizeWidget() call, but that the server may not have actually mapped it yet, so you should also wait for an Expose event on the window before drawing into it. ---------------------------------------------------------------------- Subject: 140) Where can I get documentation on Xaw, the Athena widget set? Check ftp.x.org in /pub/R5untarred/mit/hardcopy for the originals of documentation distributed with X11R5. In R6, see xc/doc/specs/Xaw or xc/doc/hardcopy/Xaw. ---------------------------------------------------------------------- Subject: 141) What's the difference between actions and callbacks? Actions and callbacks may be closely tied; the user may click a mouse-button in an object's window, causing an action procedure in that particular object to be called. As part of its processing of the event, the action procedure may inform the application via a callback registered on the object. However, callbacks can be given for any reason, including some that don't arise as a result of user action; and many actions don't result in any notification to the application. Callbacks generally are a means of interaction between the user interface (UI) and some other piece of code interested in the "results"; the interested party to which the data is communicated is usually the application's back-end functions but may be another widget in a related part of the UI. For example, a text widget invokes a callback to say "the user just entered this text string; never mind what I had to do to get it or what X events took place." In object-oriented programming terminology, callback lists are messages defined by the widget class by which the widget instance notifies another entity that something significant has happened to the widget. Actions, however, constitute a widget's repertoire of internal i/o behaviors. Actions are not about results; actions are about "how", not "what" gets done. The text widget may define a dozen or two actions which define how the user can manipulate the text; the procedures for removing a line of text or switching two words can be associated with particular X event sequences (and in fact often rely on particular types of events). Actions are (in OOP terminology) methods of the widget class by which the widget responds to some external stimulus (one or more X events). To avoid confusing yourself on the issue of actions vs. callbacks, try thinking of actions defined by an application as methods *of the application* -- applications may define actions, as well -- by which the application responds to one or more X events (and happens to be handed an object handle as part of the method argument list). Similarly, callback handlers registered by an application with a widget can be thought of as methods of the application which respond to messages from a widget or widgets. [Thanks to Michael Johnson (michael@maine.maine.edu) and to Kerry Kimbrough] ---------------------------------------------------------------------- Subject: 142) How do I simulate a button press/release event for a widget? You can do this using XSendEvent(); it's likely that you're not setting the window field in the event, which Xt needs in order to match to the widget which should receive the event. If you're sending events to your own application, then you can use XtDispatchEvent() instead. This is more efficient than XSendEvent() in that you avoid a round-trip to the server. Depending on how well the widget was written, you may be able to call its action procedures in order to get the effects you want. [courtesy Mark A. Horstman (mh2620@sarek.sbc.com), 11/90] ---------------------------------------------------------------------- Subject: 143) Can I make Xt or Xlib calls from a signal handler? No. Xlib and Xt have no mutual exclusion for protecting critical sections. If your signal handler makes such a call at the wrong time (which might be while the function you are calling is already executing), it can leave the library in an inconsistent state. Note that the ANSI C standard points out that behavior of a signal handler is undefined if the signal handler calls any function other than signal() itself, so this is not a problem specific to Xlib and Xt; the POSIX specification mentions other functions which may be called safely but it may not be assumed that these functions are called by Xlib or Xt functions. Setting a global variable is one of the few permitted operations. You can work around the problem by setting a flag in the interrupt handler and later checking it with a work procedure or a timer event which has previously been added or by using a custom event loop. R6 Xt has have support for signal handlers; there is a mechanism to set a flag in a signal handler, and XtAppNextEvent will notice that the flag has been set and call the associated callbacks. Note: the article in The X Journal 1:4 and the example in the first edition of O'Reilly & Associates' Volume 6 are in error. [Thanks to Pete Ware (ware@cis.ohio-state.edu) and Donna Converse (converse@x.org), 5/92] An alternate solution is to create a pipe and add the read side of the pipe as an input event with XtAppAddInput; then write a byte to the write side of the pipe with your signal handler (write is re-entrant). The callback for the read side of the pipe reads the byte and does the actual processing that you intended. You may want the byte to be the signal number unless your callback handles only one kind. [Thanks to Steve Kappel (stevek@apertus.com)] ---------------------------------------------------------------------- Subject: 144) What are these "Xlib sequence lost" errors? You may see these errors if you issue Xlib requests from an Xlib error handler, or, more likely, if you make calls which generate X requests to Xt or Xlib from a signal handler, which you shouldn't be doing in any case. ---------------------------------------------------------------------- Subject: 145) How can my Xt program handle socket, pipe, or file input? It's very common to need to write an Xt program that can accept input both from a user via the X connection and from some other file descriptor, but which operates efficiently and without blocking on either the X connection or the other file descriptor. A solution is use XtAppAddInput(). After you open your file descriptor, use XtAppAddInput() to register an input handler. The input handler will be called every time there is something on the file descriptor requiring your program's attention. Write the input handler like you would any other Xt callback, so it does its work quickly and returns. It is important to use only non-blocking I/O system calls in your input handlers. Most input handlers read the file descriptor, although you can have an input handler write or handle exception conditions if you wish. Be careful when you register an input handler to read from a disk file. You will find that the function is called even when there isn't input pending. XtAppAddInput() is actually working as it is supposed to. The input handler is called whenever the file descriptor is READY to be read, not only when there is new data to be read. A disk file (unlike a pipe or socket) is almost always ready to be read, however, if only because you can spin back to the beginning and read data you've read before. The result is that your function will almost always be called every time around XtAppMainLoop(). There is a way to get the type of interaction you are expecting; add this line to the beginning of your function to test whether there is new data: if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) return; But, because this is called frequently, your application is effectively in a busy-wait; you may be better off not using XtAppAddInput() and instead setting a timer and in the timer procedure checking the file for input. [courtesy Dan Heller (argv@ora.com), 8/90; mouse@larry.mcrcim.mcgill.edu 5/91; Ollie Jones (oj@pictel.com) 6/92] There are two alternatives: the simple one is to use XtAppAddTimeout instead of XtAppAddInput and check for input occasionally; the more complex solution, and perhaps the better one, is to popen or fork&exec a child which does blocking reads on the file, relaying what it has read to your application via a pipe or a socket. XtAppAddInput will work as expected on pipes and sockets. [Thanks to Kaleb Keithley (kaleb@x.org); 12/93] ---------------------------------------------------------------------- Subject: 146) What's this R6 error: X Toolkit Error: NULL ArgVal in XtGetValues? The application has a bug! A workaround is described in Section 3.4 of the R6 release notes. Here's the relevant excerpt: GetValuesBC Setting this variable to YES allows illegal XtGetValues requests with NULL ArgVal to usually succeed, as R5 did. Some applications erro- neously rely on this behavior. Support for this will be removed in a future release. ---------------------------------------------------------------------- Subject: 147) Why do I get a BadMatch error when calling XGetImage? The BadMatch error can occur if the specified rectangle goes off the edge of the screen. If you don't want to catch the error and deal with it, you can take the following steps to avoid the error: 1) Make a pixmap the same size as the rectangle you want to capture. 2) Clear the pixmap to background using XFillRectangle. 3) Use XCopyArea to copy the window to the pixmap. 4) If you get a NoExpose event, the copy was clean. Use XGetImage to grab the image from the pixmap. 5) If you get one or more GraphicsExpose events, the copy wasn't clean, and the x/y/width/height members of the GraphicsExpose event structures tell you the parts of the pixmap which aren't good. 6) Get rid of the pixmap; it probably takes a lot of memory. [10/92; thanks to Oliver Jones (oj@pictel.com)] ---------------------------------------------------------------------- Subject: 148) How can my application tell if it is being run under X? A number of programs offer X modes but otherwise run in a straight character-only mode. The easiest way for an application to determine that it is running on an X display is to attempt to open a connection to the X server: display = XOpenDisplay(display_name); if (display) { do X stuff } else { do curses or something else } where display_name is either the string specified on the command-line following -display, by convention, or otherwise is (char*)NULL [in which case XOpenDisplay uses the value of $DISPLAY, if set]. This is superior to simply checking for the existence a -display command-line argument or checking for $DISPLAY set in the environment, neither of which is adequate. [5/91] ---------------------------------------------------------------------- Subject: 149) How do I make a "busy cursor" while my application is computing? Is it necessary to call XDefineCursor() for every window in my application? The easiest thing to do is to create a single InputOnly window that is as large as the largest possible screen; make it a child of your toplevel window (which must be realized) and it will be clipped to that window, so it won't affect any other application. (It needs to be as big as the largest possible screen in case the user enlarges the window while it is busy or moves elsewhere within a virtual desktop.) Substitute "toplevel" with your top-most widget here (similar code should work for Xlib-only applications; just use your top Window): unsigned long valuemask; XSetWindowAttributes attributes; /* Ignore device events while the busy cursor is displayed. */ valuemask = CWDontPropagate | CWCursor; attributes.do_not_propagate_mask = (KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); attributes.cursor = XCreateFontCursor(XtDisplay(toplevel), XC_watch); /* The window will be as big as the display screen, and clipped by its own parent window, so we never have to worry about resizing */ XCreateWindow(XtDisplay(toplevel), XtWindow(toplevel), 0, 0, 65535, 65535, (unsigned int) 0, 0, InputOnly, CopyFromParent, valuemask, &attributes); where the maximum size above could be replaced by the real size of the screen, particularly to avoid servers which have problems with windows larger than 32767. When you want to use this busy cursor, map and raise this window; to go back to normal, unmap it. This will automatically keep you from getting extra mouse events; depending on precisely how the window manager works, it may or may not have a similar effect on keystrokes as well. In addition, note also that most of the Xaw widgets support an XtNcursor resource which can be temporarily reset, should you merely wish to change the cursor without blocking pointer events. [thanks to Andrew Wason (aw@cellar.bae.bellcore.com), Dan Heller (now argv@z-code.com), and mouse@larry.mcrcim.mcgill.edu; 11/90,5/91] ---------------------------------------------------------------------- Subject: 150) How do I fork without hanging my parent X program? An X-based application which spawns off other Unix processes which continue to run after it is closed typically does not vanish until all of its children are terminated; the children inherit from the parent the open X connection to the display. What you need to do is fork; then, immediately, in the child process, close (ConnectionNumber(XtDisplay(widget))); to close the file-descriptor in the display information. After this do your exec. You will then be able to exit the parent. Alternatively, before exec'ing make this call, which causes the file descriptor to be closed on exec. (void) fcntl(ConnectionNumber(XDisplay), F_SETFD, 1); [Thanks to Janet Anstett (anstettj@tramp.Colorado.EDU), Gordon Freedman (gjf00@duts.ccc.amdahl.com); 2/91. Greg Holmberg (holmberg@frame.com), 3/93.] ---------------------------------------------------------------------- Subject: 151) Why doesn't anything appear when I run this simple program? > ... > the_window = XCreateSimpleWindow(the_display, > root_window,size_hints.x,size_hints.y, > size_hints.width,size_hints.height,BORDER_WIDTH, > BlackPixel(the_display,the_screen), > WhitePixel(the_display,the_screen)); > ... > XSelectInput(the_display,the_window,ExposureMask|ButtonPressMask| > ButtonReleaseMask); > XMapWindow(the_display,the_window); > ... > XDrawLine(the_display,the_window,the_GC,5,5,100,100); > ... You are right to map the window before drawing into it. However, the window is not ready to be drawn into until it actually appears on the screen -- until your application receives an Expose event. Drawing done before that will generally not appear. You'll see code like this in many programs; this code would appear after the window was created and mapped: while (!done) { XNextEvent(the_display,&the_event); switch (the_event.type) { case Expose: /* On expose events, redraw */ XDrawLine(the_display,the_window,the_GC,5,5,100,100); break; ... } } Note that there is a second problem: some Xlib implementations don't set up the default graphics context to have correct foreground/background colors, so this program could previously include this code: ... the_GC_values.foreground=BlackPixel(the_display,the_screen); /* e.g. */ the_GC_values.background=WhitePixel(the_display,the_screen); /* e.g. */ the_GC = XCreateGC(the_display,the_window, GCForeground|GCBackground,&the_GC_values); ... Note: the code uses BlackPixel and WhitePixel to avoid 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. Also note that actually using BlackPixel and WhitePixel is usually the wrong thing to do in a finished program, as it ignores the user's preference for foreground and background. And also note that you can run into the same situation in an Xt-based program if you draw into the XtWindow(w) right after it has been realized; it may not yet have appeared. ---------------------------------------------------------------------- Subject: 152) What is the difference between a Screen and a screen? The 'Screen' is an Xlib structure which includes the information about one of the monitors or virtual monitors which a single X display supports. A server can support several independent screens. They are numbered unix:0.0, unix:0.1, unix:0.2, etc; the 'screen' or 'screen_number' is the second digit -- the 0, 1, 2 which can be thought of as an index into the array of available Screens on this particular Display connection. The macros which you can use to obtain information about the particular Screen on which your application is running typically have two forms -- one which takes a Screen and one with takes both the Display and the screen_number. In Xt-based programs, you typically use XtScreen(widget) to determine the Screen on which your application is running, if it uses a single screen. (Part of the confusion may arise from the fact that some of the macros which return characteristics of the Screen have "Display" in the names -- XDisplayWidth, XDisplayHeight, etc.) ---------------------------------------------------------------------- Subject: 153) Can XGetWindowAttributes get a window's background pixel/pixmap? 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. [courtesy Dave Lemke of NCD and Stuart Marks of Sun] Note that the same applies to the border pixel/pixmap. This is a (mis)feature of the protocol which allows the server to manipulate the pixel/pixmap however it wants. By not requiring the server to keep the original pixel or pixmap, some (potentially a lot of) space can be saved. [courtesy Jim Fulton, then of X Consortium] ---------------------------------------------------------------------- Subject: 154) How do I create a transparent window? A completely transparent window is easy to get -- use an InputOnly window. In order to create a window which is *mostly* transparent, you have several choices: - the SHAPE extension first released with X11R4 offers an easy way to make non-rectangular windows, so you can set the shape of the window to fit the areas where the window should be nontransparent; however, not all servers support the extension. - a machine-specific method of implementing transparent windows for particular servers is to use an overlay plane supported by the hardware. Note that there is no X notion of a "transparent color index". - a generally portable solution is to use a large number of tiny windows, but this makes operating on the application as a unit difficult. - a final answer is to consider whether you really need a transparent window or if you would be satisfied with being able to overlay your application window with information; if so, you can draw into separate bitplanes in colors that will appear properly. [thanks to der Mouse, mouse@lightning.McRCIM.McGill.EDU, 3/92; see also The X Journal 1:4 for a more complete answer, including code samples for this last option] ---------------------------------------------------------------------- Subject: 155) Why doesn't GXxor produce mathematically-correct color values? When using GXxor you may expect that drawing with a value of black on a background of black, for example, should produce white. However, the drawing operation does not work on RGB values but on colormap indices. The color that the resulting colormap index actually points to is undefined and visually random unless you have actually filled it in yourself. [On many X servers Black and White often 0/1 or 1/0; programs taking advantage of this mathematical coincidence will break.] If you want to be combining colors with GXxor, then you should be allocating a number of your own color cells and filling them with your chosen pre-computed values. If you want to use GXxor simply to switch between two colors, then you can take the shortcut of setting the background color in the GC (graphics context) to 0 and the foreground color to a value such that when it draws over red, say, the result is blue, and when it draws over blue the result is red. This foreground value is itself the XOR of the colormap indices of red and blue. [Thanks to Chris Flatters (cflatter@zia.aoc.nrao.EDU) and Ken Whaley (whaley@spectre.pa.dec.com), 2/91] ---------------------------------------------------------------------- Subject: 156) Why does every color I allocate show up as black? Make sure you're using 16 bits and not 8. The red, green, and blue fields of an XColor structure are scaled so that 0 is nothing and 65535 is full-blast. If you forget to scale (using, for example, 0-255 for each color) the XAllocColor function will perform correctly but the resulting color is usually black. [Thanks to Paul Asente, asente@adobe.com, 7/91] ---------------------------------------------------------------------- Subject: 157) Why do I get a protocol error when creating a cursor (sic)? You may have had this code working on a monochrome system by coincidence. Cursor pixmaps must always have a depth of 1; when you create the cursor pixmap use the depth of 1 rather than the default depth of the screen. ---------------------------------------------------------------------- Subject: 158) Why can't my program get a standard colormap? I have an image-processing program which uses XGetRGBColormap() to get the standard colormap, but it doesn't work. XGetRGBColormap() when used with the property XA_RGB_DEFAULT_MAP does not create a standard colormap -- it just returns one if one already exists. Use xstdcmap or do what it does in order to create the standard colormap first. [1/91; from der Mouse (mouse@larry.mcrcim.mcgill.edu)] ---------------------------------------------------------------------- Subject: 159) Why doesn't the shared-memory extension appear to work? Using the MIT shared-memory extension (MIT-SHM) is a fine way to speed up manipulation and display of images. But be aware that XShmQueryExtension(dpy) returns only information on whether or not the server to which your program is connected is capable of supporting the shared-memory extension -- it doesn't confirm that your application is running on the same machine on which you are running that server. The client and server have to be on the same machine to be able to use shared memory. Current documentation is available via ftp://ftp.x.org/pub/R6untarred/xc/doc/specs/Xext/mit-shm.ms. [thanks to Kaleb Keithley (kaleb@x.org); 3/95] ---------------------------------------------------------------------- Subject: 160) Why does the pixmap I copy to the screen show up as garbage? The initial contents of pixmaps are 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 a 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). [courtesy Dave Lemke of NCD and Stuart Marks of Sun] ---------------------------------------------------------------------- Subject: 161) How can I most quickly send an image to the X server? The fastest mechanism may be to use an XImage and the shared-memory extension to reduce the transmission time. The MIT-SHM code, documentation, and example client programs can be found on the X11R5 source tape; many vendors also support the extension. If bandwidth is a problem, the X Image Extension has facilities for transmitting compressed images. ---------------------------------------------------------------------- Subject: 162) How do I check whether a window ID is valid? My program has the ID of a window on a remote display. I want to check whether the window exists before doing anything with it. Because X is asynchronous, there isn't a guarantee that the window would still exist between the time that you got the ID and the time you sent an event to the window or otherwise manipulated it. What you should do is send the event without checking, but install an error handler to catch any BadWindow errors, which would indicate that the window no longer exists. This scheme will work except on the [rare] occasion that the original window has been destroyed and its ID reallocated to another window. You can use this scheme to make a function which checks the validity of a window; you can make this operation almost synchronous by calling XSync() after the request, although there is still no guarantee that the window will exist after the result (unless the sterver is grabbed). On the whole, catching the error rather than pre-checking is preferable. [courtesy Ken Lee (now kenton@esd.sgi.com), 4/90; 12/93] ---------------------------------------------------------------------- Subject: 163) Can I have two applications draw to the same window? Yes. The X server assigns IDs to windows and other resources (actually, the server assigns some bits, the client others), and any application that knows the ID can manipulate the resource (almost any X server resource, except for GCs and private color cells, can be shared). The problem you face is how to disseminate the window ID to multiple applications. A simple way to handle this (and which solves the problem of the applications' running on different machines) is in the first application to create a specially-named property on the root-window and put the window ID into it. The second application then retrieves the property, whose name it also knows, and then can draw whatever it wants into the window. [Note: this scheme works if and only if there is only one instance of the first application running, and the scheme is subject to the limitations mentioned in the Question about using window IDs on remote displays.] Note also that you will still need to coordinate any higher-level cooperation among your applications; you may find the Synchronization extension in R6 useful for this. Note also that two processes can share a window but should not try to use the same server connection. If one process is a child of the other, it should close down the connection to the server and open its own connection. Note also that Display IDs and GC values describe addresses local to an application and cannot be transmitted to another application; note also that if you are using Xt you may not share widget IDs, which are local to the client. Note also that several clients may draw to a window but for particular X events such as button-presses only one client can receive the event. [mostly courtesy Phil Karlton (karlton@wpd.sgi.com) 6/90] ---------------------------------------------------------------------- Subject: 164) Why can't my program work with tvtwm or swm? A number of applications, including xwd, xwininfo, and xsetroot, do not handle the virtual root window which tvtwm and swm use; they typically return the wrong child of root. A general solution is to add this code or to use it in your own application where you would normally use RootWindow(dpy,screen): /* Function Name: GetVRoot * Description: Gets the root window, even if it's a virtual root * Arguments: the display and the screen * Returns: the root window for the client */ #include Window GetVRoot(dpy, scr) Display *dpy; int scr; { Window rootReturn, parentReturn, *children; unsigned int numChildren; Window root = RootWindow(dpy, scr); Atom __SWM_VROOT = None; int i; __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False); XQueryTree(dpy, root, &rootReturn, &parentReturn, &children, &numChildren); for (i = 0; i < numChildren; i++) { Atom actual_type; int actual_format; long nitems, bytesafter; Window *newRoot = NULL; if (XGetWindowProperty(dpy, children[i], __SWM_VROOT, 0, 1, False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **) &newRoot) == Success && newRoot) { root = *newRoot; break; } } XFree((char *)children); return root; } [courtesy David Elliott (dce@smsc.sony.com). Similar code is in ssetroot, a version of xsetroot distributed with tvtwm. 2/91] A header file by Andreas Stolcke of ICSI on ftp.x.org:contrib/vroot.h functions similarly by providing macros for RootWindow and DefaultRootWindow; code can include this header file first to run properly in the presence of a virtual desktop. (Note the possible race condition.) ---------------------------------------------------------------------- Subject: 165) Can I rely on a server which offers backing store? You can assume only that the X server has the capability of doing backing store and that it might do so and keep your application's visuals up-to-date without your program's involvement; however, the X server can run out of resources at any time, so you must be able to handle the exposure events yourself. You cannot rely on a server which offers backing store to maintain your windows' contents on your behalf. ---------------------------------------------------------------------- Subject: 166) How do I catch the "close window" event to avoid "fatal IO error"? Several windows managers offer a function such as f.kill or f.delete which sends a message to the application that it should delete its window; this is usually interpreted as a shutdown message. The application needs to catch the WM_DELETE_WINDOW client message. There is a good example in the xcalc sources in X11R5. Motif-based applications should in addition set the resource XmNdeleteResponse on the top-level shell to XmDO_NOTHING, whether they are using the Motif window manager or not. If the application doesn't handle this message the window manager may wind up calling XKillClient, which disconnects the client from the display and typically gives an Xlib error along the lines of "fatal IO error 32 (Broken pipe)". [Thanks to Kaleb Keithley, kaleb@x.org; 11/93] ---------------------------------------------------------------------- Subject: 167) How do I keep a window from being resized by the user? Resizing the window is done through the window manager; window managers can pay attention to the size hints your application places on the window, but there is no guarantee that the window manager will listen. You can try setting the minimum and maximum size hints to your target size and hope for the best. Note that you may wish to reconsider your justification for this restriction. ---------------------------------------------------------------------- Subject: 168) How do I keep a window in the foreground at all times? It's rather antisocial for an application to constantly raise itself [e.g. by tracking VisibilityNotify events] so that it isn't overlapped -- imagine the conflict between two such programs running. The only sure way to have your window appear on the top of the stack is to make the window override-redirect; this means that you are temporarily assuming window-management duties while the window is up, so you want to do this infrequently and then only for short periods of time (e.g. for popup menus or other short parameter-setting windows). [thanks to der Mouse (mouse@larry.mcrcim.mcgill.edu); 7/92] ---------------------------------------------------------------------- Subject: 169) How do I make text and bitmaps blink in X? There is no easy way. Unless you're willing to depend on some sort of extension (as yet non-existent), you have to arrange for the blinking yourself, either by redrawing the contents periodically or, if possible, by playing games with the colormap and changing the color of the contents. [Thanks to mouse@larry.mcrcim.mcgill.edu (der Mouse), 7/91] ---------------------------------------------------------------------- Subject: 170) How do I get a double-click in Xlib? Users of Xt have the support of the translation manager to help get notification of double-clicking. There is no good way to get only a double-click in Xlib, because the protocol does not provide enough support to do double-clicks. You have to do client-side timeouts, unless the single-click action is such that you can defer actually taking it until you next see an event from the server. Thus, you have to do timeouts, which means system-dependent code. On most UNIXish implementations, you can use XConnectionNumber to get the file descriptor of the X connection and then use select() or something similar on that. Note that many user-interface references suggest that a double-click be used to extend the action indicated by a single-click; if this is the case in your interface then you can execute the first action and as a compromise check the timestamp on the second event to determine whether it, too, should be the single-click action or the double-click action. [Thanks to mouse@larry.mcrcim.mcgill.edu (der Mouse), 4/93] ---------------------------------------------------------------------- Subject: 171) How do I render rotated text? The X Logical Font Description was enhanced for R6 to allow embedding a transformation matrix in certain fields of an XLFD name. Thus arbitrary rotation, scaling, shearing, etc. are possible. To draw text along an arbitrarily sloped line, open a font with the appropriate rotation transformation and individually place and draw each character. Drawing text along a curve requires a different font for each character orientation needed. The overhead of opening so many fonts is somewhat mitigated by another XLFD extension which allows you to ask for a subset of the characters. See section 4 of xc/doc/specs/XLFD/xlfd.tbl.ms in the R6 distribution. Also see The X Resource, Issue Nine, p. 211, "New Font Technology for X11R6," by Nathan Meyers. (Note: due to changes after publication deadline, the information in the Meyers paper about the syntax of character set subsetting is out of date.) These capabilities are also available to an R5 X server using an R6 font server. If you are not using R6, your only choice, if you want to stay within the core X protocol, is to render the text into a pixmap, read it back via XGetImage(), rotate it "by hand" with whatever matrices you want, and put it back to the server via XPutImage(); more specifically: 1) create a bitmap B and write your text to it. 2) create an XYBitmap image I from B (via XGetImage). 3) create an XYBitmap Image I2 big enough to handle the transformation. 4) for each x,y in I2, I2(x,y) = I(a,b) where a = x * cos(theta) - y * sin(theta) b = x * sin(theta) + y * cos(theta) 5) render I2 Note that you should be careful how you implement this not to lose bits; an algorithm based on shear transformations may in fact be better. The high-level server-extensions and graphics packages available for X also permit rendering of rotated text: Display PostScript, PEX, PHiGS, and GKS, although most are not capable of arbitrary rotation and probably do not use the same fonts that would be found on a printer. In addition, if you have enough access to the server to install a font on it, you can create a font which consists of letters rotated at some predefined angle. Your application can then itself figure out placement of each glyph. [courtesy der Mouse (mouse@larry.mcrcim.mcgill.edu), Eric Taylor (etaylor@wilkins.bmc.tmc.edu), and Ken Lee (now kenton@esd.sgi.com), 11/90; Liam Quin (lee@sq.com), 12/90; Dave Wiggins (dpw@x.org), 5/94.] InterViews (C++ UI toolkit, in the X contrib software) has support for rendering rotated fonts in X. It could be one source of example code. [Brian R. Smith (brsmith@cs.umn.edu), 3/91] Another possibility is to use the Hershey Fonts; they are stroke-rendered and can be used by X by converting them into XDrawLine requests. [eric@pencom.com, 10/91] The xrotfont program by Alan Richardson (mppa3@syma.sussex.ac.uk) (posted to comp.sources.x July 14 1992) paints a rotated font by implementing the method above and by using an outline (Hershey) font. The xvertext package by Alan Richardson (mppa3@syma.sussex.ac.uk) is a set of functions to facilitate the writing of text at any angle. It is on ftp.x.org as contrib/xvertext.5.0.shar.Z. O'Reilly's X Resource issue 3 includes information from HP about modifications to the X fonts server which provide for rotated and scaled text. The modifications are on ftp.x.org in contrib/hp_xlfd_enhancements. Bristol Technology's XPrinter product has extensions to Xlib to rotate text. Send email to info@bristol.com for more details. ---------------------------------------------------------------------- Subject: 172) Why doesn't my multi-threaded X program work (sic) ? Support in Xlib and Xt for multi-threaded X programs is included in X11R6. See the documentation for XInitThreads, XtToolkitThreadInitialize, section 2.7 of the Xlib specification, section 7.12 of the Xt specification, and the article "Multi-Threaded Xlib," The X Resource, Issue 5, by Stephen Gildea. The following discussion applies only to pre-R6 libraries: You cannot use non-thread aware, non-reentrant libraries with threads. If you must do this, you have only one choice: call the functions from the initial thread only. Why opening windows from other threads causes protocol errors can be explained easily: you are accessing shared resources (the display structure, the connection to the display, static data in the Xlib) from a number of threads at the same time, without using any form of exclusive access control. [Thanks to casper@fwi.uva.nl (Casper H.S. Dik)] ---------------------------------------------------------------------- Subject: 173) What is the X Registry? (How do I reserve names?) There are places in the X Toolkit, in applications, and in the X protocol that define and use string names. The context is such that conflicts are possible if different components use the same name for different things. The X Consortium maintains a registry of names in these domains: orgainization names, selection names, selection targets, resource types, application classes, and class extension record types; and several others. The list as of April 1994 is in the file xc/registry in the R6 distribution. The current Registry is also available by sending "send docs registry" to the xstuff mail server. To register names (first come, first served) or to ask questions send to xregistry@x.org; be sure to include a postal address for confirmation. [11/90; condensed from Asente/Swick Appendix H; 1/94] ---------------------------------------------------------------------- David B. Lewis faq%craft@uunet.uu.net "Just the FAQs, ma'am." -- Joe Friday