1
2X11 implementation notes
3------------------------
4
5(0) Errors.
6
7On the first call to connect to a server, I call XSetErrorHandler to
8install a non-fatal error handler.  This handler calls the on_error
9function set by p_handler, reporting a priority 1 error with an error
10message that begins with "Xlib: ".
11
12A more severe problem is the XSetIOErrorHandler routine, which must
13not return.  Such an error will result in the on_panic routine set by
14p_panic being called for each screen of the display.
15
16Status returns in Xlib are 0 on failure, non-0 on success.  Anything
17returning Status bypasses the error handler set by XSetErrorHandler,
18and must therefore be checked.
19
20(1) Fonts.
21
22-----------------------------
23
24At connect time, XListFonts is used to find as many fonts matching
25"courier", "times", "helvetica", "symbol", and "new century
26schoolbook" as possible.  Specifically, in the font list, an attempt
27is made to find medium, bold, italic (or oblique), and bold italic
28versions of all five fonts (this will never succeed with symbol), for
29a total of 20 possible typefaces.  For each typeface, I catalog all
30the sizes - in pixels! - the server can provide, sorted according to
31size.  For each available size, I store a copy of the font name that
32will retrieve that font later.  In the case of a scalable font, this
33name will have wildcard characters for the sizes.  (If more than one
34font matches, I take the first in the XListFonts list.)  After this
35search, I have recorded all the fonts of interest that exist on this
36server, with the means to retrieve them.  For scalable fonts, a call
37to XListFonts will still be necessary in order to get a specific size
38which is not prebuilt.
39
40If a requested typeface is not available, I first check if the
41non-bold, non-italic basic version is present.  If not, I check for
42any bold, italic, or bold-italic versions.  If none of these is
43available, I try first times, then new century, then helvetica, then
44courier in the requested face, and finally that same sequence in the
45basic face.  If this search comes up empty, I fall back to the GUI
46font (see below).  Once the typeface is found, I choose the pixel size
47closest to the request, or, if a scalable version is available, I
48construct the exact pixel size requested.
49
50I cache up to 6 fonts to allow switching among several fonts without
51loading and unloading.  When the cache is full, the least recently
52used font is unloaded.
53
54Additionally, there is a GUI font which I load at connect time.  If
55nothing better can be found, this will be the default font for the
56server (guaranteed to be loaded according to O'Reilly 6.2.2 volume
57one).
58
59-----------------------------
60
61The "standard" pixel sizes are:
62
63points            pixels
64            75 dpi       100 dpi
65   8           8           11
66  10          10           14
67  12          12           17
68  14          14           20
69  18          18           25
70  24          24           34
71
72The two 14 pixel fonts sometimes differ by one pixel in average width
73between the 75 and 100 dpi resolutions; I don't distinguish them, and
74use whichever happens to come first in XListFonts.  Therefore, a full
75installation of these standard fonts involves 11 sizes for each of 17
76fonts (no bold or italic symbol fonts), for a total of 187 typefaces.
77When scalable fonts are also available, this will be 204 font names to
78be catalogued.  X font names have 14 components:
79
80-foundry-family-wgt-slant-wid--pixels-pts-hres-vres-spacing-avgwid-char-set
81
82For the five fonts I care about, I have seen these variants:
83
84 adobe|bitstream-courier-medium|bold-o|i|r-normal--    m iso8859-1
85 adobe-times-medium|bold-i|r-normal--                  p iso8859-1
86 adobe-helvetica-medium|bold-o|r-normal--              p iso8859-1
87 adobe-symbol-medium|medium-r|r-normal--               p adobe-fontspecific
88 adobe-new century schoolbook-medium|bold-i|r-normal-- p iso8859-1
89
90-----------------------------
91
92Font rotation is painful.  The basic idea is to create an offscreen
93bitmap, draw to the bitmap, read the bitmap back as an XImage, rotate
94the XImage bitmap, then write the bitmap back to a second offscreen
95bitmap.  The weird part begins now: You can specify a "stipple"
96pattern when you fill an area; the bitmap containing the rotated text
97can be used as a stipple, so that a call to XFillRectangle actually
98paints the rotated text.  This actually perfectly simulates all the
99drawing options available for painting text -- except, of course, you
100can't stipple it (actually you could, by using a counter-rotated
101stipple pattern while drawing the text into the first bitmap).
102
103The hitch is that the XImage interface is botched.  The XFree86 source
104(and I suspect vendor X's as well) has a reasonably efficient
105XPutImage call to convert from the myriad image formats to the one
106required by the server.  However, XGetImage does not perform any
107conversion, so you get images back in whatever format the server uses
108- making efficient rotation a huge chore.  (XGetSubImage looks like it
109would perform the required format conversion, but it turns out to be
110implemented very inefficiently using XGetPixel and XPutPixel -- it's
111not obvious to me why the very same efficient routines used by
112XPutImage could not be used to make XGetSubImage just as efficient.
113It turns out the server doesn't translate either Get or Put requests
114-- this is just a client side issue.)  I decided this was an X
115problem, not a Gist problem, and assume that someday, efficient
116versions of XGetSubImage will become the norm.  My compromise was to
117use the same image format as the XCreateBitmapFromData functions --
118namely the format used in all the bitmap files supplied with the X
119distribution.  Presumably, this particular format will come early on
120any prioritization of optimizations.
121
122Note that X11 "default" bitmap is
123
124format=      XYPixmap
125bit_order=   LSBFirst
126byte_order=  LSBFirst (unused)
127bitmap_unit= 8
128bitmap_pad=  8
129xoffset=     0
130no extra bytes per line
131
132(This is what is required for input to XCreateBitmapFromData, and
133handled by XReadBitmapFile and XWriteBitmapFile.)
134
135-----------------------------
136
137
138(2) Colors.
139
140I support three color models: standard colors, palette colors, and rgb
141colors.  Palettes are restricted to 240 colors, which leaves room for
142up to 16 standard colors within a 256 color colormap.
143
144A huge amount of work is required to intelligently handle the case of
145the PseudoColor visual; the other visuals (StaticGray, GrayScale,
146StaticColor, TrueColor, and DirectColor) are relatively simple.
147
148First, for DirectColor or GrayScale, I create a single colormap (256
149r=g=b=index colors) at p_connect time, and arrange for it to be
150installed on every window.  This effectively reduces the case of
151DirectColor to TrueColor, and the case of GrayScale to StaticGray.  I
152do not support color table animation; therefore the TrueColor and
153StaticGray visuals are functionally equivalent to DirectColor and
154GrayScale, respectively.
155
156Now, for any visual other than PseudoColor, XAllocColor immediately
157gives the closest match possible to any rgb value on the display.
158
159For PseudoColor, I support two modes of operation for every toplevel
160window -- shared and private colormaps -- controlled by the P_PRIVMAP
161hint passed to the p_window function.  Shared colormap windows always
162use the default colormap for the screen; each private colormap window
163has its own colormap (they can't share each others maps).  In the case
164of private colormaps, I take care to reduce colormap flashing by
165allocating all the standard colors at the same pixel they have in the
166default colormap for the screen, and by allocating palette colors from
167the top down (since most X servers seem to allocate them from the
168bottom up).
169
170At the first reference to an rgb-model color in a PseudoColor window,
171I install a 5-9-5 (5 reds, 9 greens, 5 blues) colormap.  All
172subsequent palette-model or rgb-model colors are approximated as well
173as possible from within this 595 colormap.  (This matches Mesa's
174strategy for 8-bit deep screens.)  Once this 595 colormap is
175installed, it will persist, with p_palette calls allocating
176palette-model colors from this 595 map instead of changing colormap
177colors.  Destroying the window is the only way to return to a "normal"
178colormap in which an attempt is made to get the exact rgb values
179requested for palette-model colors.
180
181One final complexity is that offscreen pixmaps cannot have their own
182colormaps under X.  Thus, an offscreen uses the colormap of its parent
183window, and calls to p_palette or references to rgb-model colors when
184drawing to an offscreen pixmap will change the colormap of the parent
185window as a side effect.
186
187
188
189-----------------------------
190
191(3) Events.
192
193The x11_create function creates a new window, and attaches its p_win
194struct to the window via a hashtab for later retrieval.  There is one
195hashtab per display; the effect is the same as the XContext mechanism.
196The x11_create function also calls XSelectInput to determine which X
197events the window will receive.
198
199Toplevel windows additionally may require setting window properties to
200communicate with the window manager (WM_DELETE_WINDOW is the most
201important).  And menus require both the override_redirect property and
202save_under property.
203
204All button press events are selected with OwnerGrabButtonMask, and
205pointer grabs are made with owner_events True.  This forces the X
206server to do the geometry calculation.  However, I intend that the
207higher level platform independent event handlers will allow for some
208variation in the details of event delivery semantics.
209
210One "event" in the sense of the basic input event manager consists of
211all the data readable on the X socket, which may be several or many X
212events.  Callbacks for all of these occur without polling for any new
213input in between.
214
215-----------------------------
216
217(4) X Resources.
218
219Window class names for all resources is "Gist".  (Toplevel windows
220will have class "Gist", unless created with the P_DIALOG hint, in
221which case they have class "GistDialog".)  All resources can be
222overridden by setting external program variables before making a
223connection (via p_connect or, for the colors, p_multihead).
224
225X resources are:
226            X resource                     program override variable
227  --------------------------------------   -------------------------
228  boldfont (preferred) or font (or Font)          x_xfont
229  foreground (or Foreground)                      x_foreground
230  background (or Background)                      x_background
231  guifg                                           x_guifg
232  guibg                                           x_guibg
233  guihi                                           x_guihi
234  guilo                                           x_guilo
235
236defaults:
237  font: 9x15
238        fixed
239        <font in default GC on root window>
240  foreground: black
241  background: white  <if foreground closer to black than white>
242              black  <if foreground closer to white than black>
243  guifg: foreground
244  guibg: background
245  guihi: <none>
246  guilo: <none>
247    if the hilight or lolight color is not specified, use a 2x2
248      gray bitmap with FillOpaqueStipple to draw hi or lo regions
249    the fg color of the hi stipple is always white; the foreground
250      color of the lo stipple is always black
251    the bg color of the stipple (for either hi or lo) is the
252      "background" color, unless that is too close to white or black,
253      in which case the stipple bg is the "foreground" color
254
255A 3d effect is generated by drawing the top and left sides of boxes
256hi, and the bottom and right sides of boxes lo.
257