------------------------------------------------------------------------------- Using `editdres' in your applications You have to register an event handler named '_EditResCheckMessages' on each toplevel window in your application. This event handler is defined in libXmu.a. --- I don't think this is actually true! ------------------------------------------------------------------------------- Permanent Objects in X Server dpy: your existing connection tempdpy: a secondary connection dedicated to make something permanent. tempdpy = XOpenDisplay(DisplayName(dpy)); XSetCloseDownMode(tempdpy, RetainPermanent); create_something_to_be_permanent(tempdpy); XCloseDisplay(tempdpy); Don't do anything else with this second display connection, as you don't want anything else to become permanent. For more information, have a look in the Xmu source code for the creation of standard colormap atoms. DO NOT USE the dpy of a normal Xlib or Xt client to make something permanent. You would make things permanent you wouldn't like to leave on the display when your program is finished. ;-) For Example: If you open a window with the `RetainPermanent' connection, then after the client closes down the window will still be there. If the window manager then makes an explicite XKillClient() requests for that window, all of the permanent set of information will then be deleted. ------------------------------------------------------------------------------- ColorMap allocation XInstallColormap() call is used only be window managers to change the actual colormap. To set the color map an application uses use the call XSetWMColormapWindows() or XtSetWMColormapWindows() to set the WM_COLORMAP_WINDOWS property on the toplevel windows. NOTE: you must have the widgets realised before using this call in Xt ------------------------------------------------------------------------------- Color allocation notes * To convert a color range of 0-255 to a X11 color range of 0-65535 you must multiple by 257 not 256. The reason for this is that 255*257 => 65535 This would also result in color #aabbcc becoming #aaaabbbbcccc which is the correct solution as used by the RGB data base. * The reverse of the above can divide by either 256 or 257 due to the integer division of each color compenent. ------------------------------------------------------------------------------- Color Allocation My color program always fails on XAllocColorCells()! 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. ------------------------------------------------------------------------------- Drawing a large 'fat' point The Best method from the network is Draw a line of length 0, with a width of desired diameter and a cap style of rounded. Other methods are more difficult or slow. ------------------------------------------------------------------------------- Notes on Drawing Bitmaps * XCopyPlane copies a bitmap to a pixmap with the appropriate foreground and background colours of the GC. (0-back 1-fore) * XCopyArea copies a pixmap map to a destination of the SAME depth without any changes to the coloring of the output. * Icon bitmaps have to be given to the window manager as bitmaps as that is what is expected. A pixmap icon must be setup as a icon window instead of a true icon. :-( Results :- To set a bitmap for command widgets from an included data file (IE not via a resource setting) requires a pixmap to be created with the bitmap stored in it using the correct color scheme. I suggest the following (though there may be a better way).. 1/ Copy the bitmap data into a pixmap of depth 1 in the server. 2/ perform a XCopyPlane from this `bitmap' into a pixmap of the correct depth using a GC with the appropite foreground and background colors set. 3/ destroy the intermediate depth 1 pixmap if you don't what it for other purposes. WARNING: Label Widgets handle its image as a Bitmap is pixmap depth is equal to 1. This can produce an inverted image for pixmaps on some monocrome displays. (those with black pixel == 0) ------------------------------------------------------------------------------- Drawing non-rectangular bitmaps/pixmaps If you are using the XPM library then the mask is created for you when you are making the pixmap. Here is how to use it or another bitmap as a mask to what you are drawing. METHOD 1: Here is the clip mask method mentioned above... The solution is to use your bitmap as a clip mask in the Graphics context. What the mask does is only allow drawing on the pixels where 1's are in the bitmap. XSetClipMask( display, gc, bitmapmask ); XSetClipOrigin( display, gc, 0, 0 ); XCopyArea( display, pixmap, XtWindow(widget), gc, 0, 0, width, height, 0, 0 ); /* clean up */ XSetClipMask( display, gc, None ); x and y are the upper left corner of the rectangle where the bitmap is to be placed. The mask must be a 2 plane pixmap (i.e. a bitmap); These masks are automatically created by the Xpm libraries. This is slow due to mask convertsion to rectangle lists. -- Jason Schmidt leolore@iastate.edu METHOD 2: XCopyArea(display, pixmap, window, gcxor, 0, 0, w, h, x, y); XSetForeground(display, gcand, 0); XSetBackground(display, gcand, ~0); XCopyPlane(display, mask, window, gcand, 0, 0, w, h, x, y, 1L); XCopyArea(display, pixmap, window, gcxor, 0, 0, w, h, x, y); NOTE: pixmap = colour pixmap mask = 1 plane pixmap It is pretty quick and you don't need clip masks, shape extensions etc. -- Justin Kibell jck@jaguar.catt.citri.edu.au METHOD 3: Use the mask as a shapemask with the X11 Nonrectangular Shape Window Extension. Typically this is what should be done when the icon is used in a desktop. -- Arnaud Le Hors But you can do this witha widget window too. (See my IconLabel Widget) ------------------------------------------------------------------------------- Pixmap in a Label Widgets The label widget draws bitmaps differently to bitmaps, but it can't tell the difference on monochrome displays. Thus on some monochrome displays pixmaps are drawn inverted as the white and black pixel values don't match that of a normal bitmap (white=0 and black=1). IE: pixmaps in labels on SUN monochrome consoles are correct but are inverted on NCD monochrome displays. To fix this if ( display_depth == 1 || white_pixel == 1 ) Invert the colors of your pixmap before assigning to a label. NOTE: swapping white and black on a label is not a good solution as the internal spacing will then have the wrong color. Solution ...insert example here...anyone?... ------------------------------------------------------------------------------- X Pixmaps with the color None.. The Color None if not masked using the Mask Bitmap generated comes out as Pixel Value 0. This pixel value is white on Sun and Dec X servers but black on NCD's, and other X Terminals and many other workstations like Silicon Graphic machines. The simple fix is to use the following coding.. ======8<------ static XpmColorSymbol attr_nonesymbol[] = { {NULL, "none", 0} }; static unsigned long attr_valuemask = XpmColorSymbols | XpmReturnPixels | XpmCloseness; /* ...initialize... */ attr_nonesymbols[0].pixel = app_data.icon_trans; /* transparent color */ /* do the job */ item->attr.valuemask = attr_valuemask; item->attr.colorsymbols = attr_nonesymbols; item->attr.numsymbols = XtNumber(attr_nonesymbols); item->attr.closeness = 40000; status = XpmReadPixmapFile(display, DefaultRootWindow(display), item->fname, &item->pixmap, NULL, &item->attr); /* Now remove the transparent pixel from the pixel list ** Otherwise it will be freed later when it shouldn't. :-( */ { int i,j; for( i = j = 0; i < item->attr.npixels; i++ ) { if( item->attr.pixels[i] == app_data.icon_trans ) continue; /* don't include the none pixel color */ item->attr.pixels[j++] = item->attr.pixels[i]; } item->attr.npixels = j; /* the number of pixels now */ } ======8<------ WARNING: The above is not really as simple as it seems. See the latest xbmbrowser program and look at the Chnages made for version 4.4 of the program. NOTE: The XpmColorSymbol array elements has three items of which only two are ever used for the substitution. This means there are three ways the substitution can be performed. XpmColorSymbol Elements | name value pixel | Results in -------------------------------+------------------------------------ "symbol" "color" ? | symbol with the color "color" "symbol" NULL pixel | symbol with the specified pixel NULL "color" pixel | "color" with the value of pixel -------------------------------+------------------------------------ ------------------------------------------------------------------------------- Panning Pixmaps A pixmap that is larger than the window(viewport) and you can move it (display it) without having to do more redraws and heavy IO. 1) Draw into a pixmap, then do the panning by hand using XCopyArea() though this doesn't sound like something you want to do.. 2) Create a window. Create a subwindow. Draw into your pixmap. Set that pixmap as the background of the subwindow. Use XMoveWindow() to move the subwindow for panning. ------------------------------------------------------------------------------- Nonrectangular pointer zones (many) in window (non-orthogonal) It is perfectly feasible and pretty easy to do with the SHAPE routines. Another solution is to just draw all the zones in the englobbing rectangular window an track the pointer motion events and calculate manually in which zone the pointer is (to highlight it or do whatever you want). You should probably try the first solution first, but many X servers are a bit sluggish when dealing with non-rectangular windows (Clip mask problem). lecom@slhp1.epfl.ch (Claude Lecommandeur) ------------------------------------------------------------------------------- General Speedup hints Joe English (joe@trystero.art.com) : * Don't create and destroy widgets on the fly. Try to reuse them. (This will avoid many problems with buggy toolkits, too.) * Use a line width of 0 in GCs. On some servers this makes a HUGE difference. * Compress and collapse multiple Expose events. This can make the difference between a fast application and a completely unusable one. Francois Staes (frans@kiwi.uia.ac.be) : * Just a small remark: I once heard that using a better malloc function would greatly increase performance of Xt based applications since they use malloc heavily. They suggested trying out the GNUY malloc, but I didn't find the time yet. I did some tests on small programs just doing malloc and free, and the differences were indeed very noticeable ( somewhat 5 times faster) Joe Stewart (joes@lpi.liant.com) * for long button press actions -- fork off a sub-process to deal with the problem. This leaves the application running normally. Or start a WorkProc in Xt. ------------------------------------------------------------------------------- Icons and Window state There are three states for windows: Withdrawn, Normal, and Iconic. Newly created top-level windows are in the Withdrawn state. Withdrawn -> Any The client should map the window with WM_HINTS.initial_state being set to NormalState or IconicState as appropriate. Any -> Withdrawen The client should unmap the window and follow it with a synthetic UnmapNotify event to itself to allow correct event programming. R5 has a new library routine to do this properly for WM. Normal -> Iconic The client should send a client message to iconify itself. This is done for you by the Xlib routine XIconifyWindow to make this job easier. Iconic -> Normal The client should map the window. WM_HINTS.initial_state is irrelevent. --- der Mouse mouse@larry.mcrcim.mcgill.edu ------------------------------------------------------------------------------- Application Exits Note that in many Unix-based implementations of Xlib, there's a sort of race condition around XIO errors; because of the way the connection between the server and the client is implemented, you may get a SIGPIPE before the next time you try to interact with the X11 server, ie, before you notice the XIO error. Since the default action for SIGPIPE is to abort the program, this is something of a problem. --- Matt Landau matt@centerline.com For applications that do not use WM_DELETE_WINDOW, a I/O error handler that exits quietly instead of printing a noisy complaint first. should be used. IE: myIOerror(d) Display *d; { exit(0); } ... SetIOErrorHandler(myIOerror); --- der Mouse mouse@larry.mcrcim.mcgill.edu The problem with your (above) solution is that while it cures the single erroneous error, it also defeats the the reporting of other, real errors in the same "swell foop", which is why I said, "IMHO, programs that don't participate..." --- Kaleb Keithley kaleb@thyme.jpl.nasa.gov ------------------------------------------------------------------------------- Signal Handling in X There IS a reason not to do Xt or Xlib calls within a signal handler. It has to do with confusing the X protocol, as well as this, the libraries are not re-entrent. Two safe methods are 1/ Set a flag (the only truly safe method) and Check this flag in you Work Procedure, or a XtTimeer Proc. 2/ Create a pipe added to the event loop with XtAppAddInput(). This method seems most universal on the network. ----- How to use a pipe to handle signals * In your X application startup code create a pipe. * Attach the readable end of the pipe to the X event queue using XtAppAddInput. * Create a signal handler and register it with the signals you want to handle in the event loop. * In the signal handler code, build a message with the signal number and any other info you might need to handle the signal, then write() it to the writable end of the pipe. Now when you get a signal, your signal handler will write to the pipe which will make the event dispatcher call your input event handler that can really process the signal... --- Tom Horsley tahorsley@csd.harris.com ----- This is not totally safe unless you are careful about overflowing the buffering capacity of the pipe. And I don't think anyone guarantees how much buffering pipes have, or even that they have any at all. At the price of a few of extra syscalls per signal received, you can avoid assuming more than one byte of buffering.... --- der Mouse -- mouse@larry.mcrcim.mcgill.edu ------------------------------------------------------------------------------- Multiple Displays | I have an Xt application that uses multiple displays (one app context). | When I try to call XtOpenDisplay on a display that currently has the | xdm login prompt, my application hangs (waiting for XtOpenDisplay to | return). Sure, opening the display hangs, but only for a certain amount of time. You could interrupt it by winding up a timer, doing a setjump and then XtOpenDisplay. When the timer strikes you longjump back. And don't forget to cancel the timer if opening the display succeeded. signal (SIGALRM, XtOpenTimeout); if (setjmp (xtOpenJump)) { LogError ("XtOpenDisplay timeout expired for display %s.\n", d->name); signal (SIGALRM, SIG_DFL); alarm (0); return False; } else { alarm ((unsigned) d->openTimeout); argc = 0; d->display = XtOpenDisplay (applicationContext, d->name, "xlogin", "Xlogin", NULL, 0, &argc, NULL); signal (SIGALRM, SIG_DFL); alarm (0); if (d->display == NULL) return False; Debug (1, "XtOpenDisplay (%s) successful\n", DisplayString (d->display)); /* ... */ return True; } NOTE: I can't get this to work - Anthony ------------------------------------------------------------------------------- Ephemeral Annotations (Rubberbanding Color Screens) XOR On color screens XOR can produce `random' color selections which may or maynot be actually visiable. Only if you install your own color map can you be sure that this would would as expecated directly. 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)); --- X11 Top Ten Questions: Dave Lemke (lemke@ncd.com) XOR with color cycling XOR works poorly in pictures involving randomized or `grainy' data (such as satalite maps). --- rosenth@vision.ethz.ch (Lukas Rosenthaler) Although a XOR'ed line may be hard to see. A flashing one is almost certainly visible. While the annotation is up, continually erase and redraw it three times a second slightly different using an Xt timer proc. IE: XOR plane 1 then 2, 3, 4... and repeat. to remove just xor all the planes that is currently xor'ed. Even though the effect of XOR drawing in a random color map yields random colors, this technique should yield enough different random colors on your annotation lines over a period of a couple of seconds that users will see them clearly. --- Oliver Jones (miki.pictel.com) XOR with `ant' dash lines Same principle as above. Draw the annotation lines dashed, and redraw them continually as you reset the origin of the dash pattern. This will make the annotation lines crawl, the way lassos and marquees do on Mac drawing programs. --- Oliver Jones (miki.pictel.com) Overlay Color plane An alternative is to devote one or two color planes to be overlay planes. This means that you lose those planes for displaying colors for your main image, but you gain the ability of being able to "overlay" an image over your main image. I should also point out that this technique is further simplified by technology that allows you to selectively write to certain pixel planes, instead of all of them. I believe X supports this, via the XSetPlaneMask function. --- Doug Young Backing Plane This works by using the backing pixmap used for expose redraws, as a tiling pattern. Just draw your annotation as normal but to undraw from the backing pixmap use the following GC. function: GXcopy fill_style: FillSolid tile: the backing pixmap ts_x_origin: 0 ts_y_origin: 0 And draw the annotation again to erase it. --- Jim Mayer (mayer@wrc.xerox.com) ------------------------------------------------------------------------------- Double Buffering One method is to divid the color planes into two sections to flip between. This is used by the Xpilot program. Problem is, this solution requires num_colours * num_colours colours to be allocated, limiting you to 16 colours on a 256 color machine. Alternitively, you can add support for the MIT double buffering extension. This should give a noticeable increase in speed. Lacking that, I would implement it much like the original ICO did in that I would draw into pixmaps and copy them into the window as needed. ------------------------------------------------------------------------------- Xresources from Xlib programs If you just want to get resources, look at XGetDefault, which "[...] provides a simple interface for clients not wishing to use the X toolkit or the more elaborate interfaces provided by the resource manager [...].". If you want something more complicated, look at XResourceManagerString and XScreenResourceString (the latter does not exist pre-R5), XrmGetFileDatabase, XrmGetStringDatabase, and XrmGetResource. There are many other Xrm* functions; check out the Xlib documentation. (And don't forget to call XrmInitialize.) der Mouse --- mouse@mcrcim.mcgill.edu ------------------------------------------------------------------------------- Edge Actions.. Detect when mouse hits an edge so you can do some action. Simple way, create a 'input only' edge window edge[i]->win = XCreateWindow(obt_display, obt_root(ob_screen), r.x, r.y, r.width, r.height, 0, 0, InputOnly, CopyFromParent, CWOverrideRedirect, &xswa); XSelectInput(obt_display, edge[i]->win, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask); XMapWindow(obt_display, edge[i]->win); Events then tell you when the mouse 'hits the edge' -------------------------------------------------------------------------------