DISPLAYNAME := [HOSTNAME] ':' DISPLAYNUM ['.' SCREEN] HOSTNAME := the local host resolve name DISPLAYNUM := which of the running servers SCREEN := the screen of the serverExamples: "barney.bedrock.net:1.3", ":0.0", "bill.microsoft.com:0.0"
You should be aware that two connections to one display using the same screen can share resources. Resources in a display that do not share the same screen can _not_ share anything, as the two screens might have different bit depths color setups and so on (monocolor vs. indexed color vs. truecolor).
Some of the properties of a window are the position, size, mapped/unmapped state, bit depth, inout/out class, and event interest. The mapped state is whether the window is active to the display, the inout class can limit windows just to take input from the user and not output graphics (invisible). The input-only windows are only interested in knowing how the mouse moves and what keys are pressed when the window is 'in focus' (keyboard events). Of course the window must have asked for those events. There are a few more cosmetic properties of a window, but they aren't interesting to us quite yet.
The XEvent type is a union of a bunch of different structs, all with with the first entries common to the XAnyEvent struct.
typedef struct { int type; unsigned long serial; /* # of last request processed by server */ Bool send_event; /* true if this came from a SendEvent request */ Display *display; /* Display the event was read from */ Window window; } XAnyEvent;For a complete list of the input event masks you might want to view the <X11/X.h> header, and <X11/Xlib.h> for the XEvent union's content. The function XSelectInput is used for registering interest in most of the different events. This is done by passing the bitwise OR of the event masks.
An example, it will open a window then live until a the window is clicked in.
typedef struct { int type; unsigned long serial; /* # of last request processed by server */ Bool send_event; /* true if this came from a SendEvent request */ Display *display; /* Display the event was read from */ Window window; int x, y; int width, height; int count; /* if non-zero, at least this many more */ } XExposeEvent;If you receive one expose event with a nonzero count, you're certain to get more. So you can wait until you've got one expose event with a count of zero until you redraw all of your window again. Or you might choose to just draw the parts that need exposure with the information contained about the location(x,y) and size(width, height) for each expose event.
typedef struct { int function; /* logical operation */ unsigned long plane_mask;/* plane mask */ unsigned long foreground;/* foreground pixel */ unsigned long background;/* background pixel */ int line_width; /* line width (in pixels) */ int line_style; /* LineSolid, LineOnOffDash, LineDoubleDash */ int cap_style; /* CapNotLast, CapButt, CapRound, CapProjecting */ int join_style; /* JoinMiter, JoinRound, JoinBevel */ int fill_style; /* FillSolid, FillTiled, FillStippled, FillOpaqueStippled*/ int fill_rule; /* EvenOddRule, WindingRule */ int arc_mode; /* ArcChord, ArcPieSlice */ Pixmap tile; /* tile pixmap for tiling operations */ Pixmap stipple; /* stipple 1 plane pixmap for stippling */ int ts_x_origin; /* offset for tile or stipple operations */ int ts_y_origin; Font font; /* default text font for text operations */ int subwindow_mode; /* ClipByChildren, IncludeInferiors */ Bool graphics_exposures; /* boolean, should exposures be generated * int clip_x_origin; /* origin for clipping */ int clip_y_origin; Pixmap clip_mask; /* bitmap clipping; other calls for rects */ int dash_offset; /* patterned/dashed line information */ char dashes; } XGCValues;Glancing through it, you see that a GC also keep information about font to use, different methods for filling solids, and bitmap controlled clipping. Plus of course a lot more that is hardly ever useful. :)
GCs are different from many other types in Xlib in that it isn't an ID for a resource on the display, but rather an opaque struct pointer that caches changes to commit them first when it need to (i.e. before drawing). This means that while you can share a gc between two clients, it is not recommended because they're not synced. And also Xlib makes it hard to do this by not having the interface to do it. (There is a possibility to get the resource ID of the GC with XGContextFromGC(), but you cannot build a GC from a GContext value.)
The trouble is in modifying the GC to your needs, for example, changing color or font. And colors under X11 is a pain, because this is supposed to be a portable system and programs should work on black and white displays as well as truecolor ones. The easy way out is to avoid using anything else than black and white in your program. Which is often ok and will maintain functionality, but it will not impress your friends. Either learn about the color system in X or get new friends.
Color classes:
Colormap Type Read/Write Read-only ----------------- ---------- ---------- Monochrome/Gray GrayScale StaticGray Single index RGB PseudoColor StaticColor Decomposed index RGB DirectColor TrueColor
An image viewer is an easy to imagine application to aquire a lot of colors. It would do best by creating it's own colormap with XCreateColormap() and make sure to allocate all colors in there, then change them to fit the need with XStoreColors(). The function XAllocColorCells() will allocate modifiable entries in an existing colortable. Colortables are associated with windows, refer to XCreateWindow() or XSetWindowAttributes().
Second example. This time something colorful and graphic happens. Click in the window to terminate the program.
What you need is a Font to write with. There is a list available if you type the command 'xlsfonts'. A user configured program need to XListFonts(), XLoadFont() and optionally XQueryFont() before it can do something useful. The function XLoadQueryFont() encapsulates all of this if the font name is known to exist.
With the XFontStruct obtained the client can measure the size of a string locally with XTextExtents(), XQueryExtents() would let the server do the measurement and that causes more network traffic. From the XCharStruct filled out the text height is ascent+descent. Remember that the x,y position when text is drawn is measured from the baseline of the text. The upper left corner will then be [x, y-ascent].
Internationalized text makes this worse, because it involves the whole locale subsystem of X11. You need to XSetLocaleModifiers(), create a resource-db with XrmGetFileDatabase(), XOpenOM(), and finally XCreateOC(). The latter have a particularly ugly interface. The OC (output context) is interchangeable with FontSets, so you can use it as argument to XmbDrawString/XwcDrawString. The first function is for multibyte and the second is wide-character encoding of unicode.
Internationalized input, now here we got a sweetie. As with output you need to have a correct locale set, called XOpenIM() and XCreateIC(). Then you have XwcLookupString() to do the same as XLookupString(). What adds greatly to the complexity is that not all methods of typing in glyphs give you the glyph directly. A single glyph could consist of a few keystrokes that the user wants to be able to edit. Or the input method could even supply a whole dictionary of all glyphs and provide means to point and click your way to the correct glyph. In the last case the input method want it's own window, this window needs a registered eventmask and a way to receive it's events. For this reason XFilterEvent() needs to be called after XNextEvent() to decide what events went to the input method and which did not.
As it seems internationalization adds a lot of complexity to a program. And it does, no doubt about it. But when it is done, and done good, it will seamlessly be able to understand American, Hebrew, Futhark, or Klingon for those with an inkling. I18n is simply a too technologically superior thing to be passed of by ignorance of other cultures.
Third example. The funny graphics is replaced with some text input-output. I18n avoided thank you. Click and type in the window. Escape terminates the program.
Another way is to create a so called pixmap that is drawn into with the same functions as with regular windows. Then paste this into windows with XCopyArea(). Pixmaps also have uses as in window background images and pattern for filling solids.
XImages have a basic putpixel interface for manipulation, XPutPixel() and XGetPixel(). This is slow but very portable to all the possible formats you might meet. If more juice is required, be ready to write a set of custom functions for each image configuration, like, format, depth and everything else the XImage struct holds. XPutImage() and XGetImage() pastes and copies part or whole images to/from the display.
That's all folks!