

		X10 to X11 Protocol Converter
		       Todd Brunhoff
		      Tektronix, inc.
		      $Revision: 1.1 $
		      $Date: 88/02/25 23:42:32 $


This directory contains a Protocol Converter, or PC, for X10 clients
such that they may continue to run unaltered under X11.  This file
discusses installation, usage, implementation details and bugs.

Installation
------------
Place the source for the PC in X11/clients/x10tox11.  This directory,
when installed, will contain this README file, and Imakefile, one
C-language source file, and two subdirectories containing the X10 and
X11 halves to the PC.  If the rest of your X11 sources have been installed
correctly then doing a "make Makefiles" from the clients directory will
generate the appropriate Makefiles.  "Make depend" should be run as
well.

Usage
-----
The PC requires nothing to be present from the X10 environment to either
build or run; however, clients may require things like the rgb database
or a global keymap file.  Theoretically, the X10 client could exist on one
architecture, the X11 server on another and the PC could sit on a third
architecture, but this has not been tested.  The command line usage is
as follows:

	x10tox11 [Keyword ...] [flag ...]

	where keyword is any of
		Sync		call XSyncronize(dpy, True) for each
				connection.
		NoSync		call XSyncronize(dpy, False) for each
				connection (default).
		AllowGrabServer	Any X10 GrabServer requests will become
				X11 GrabServer requests (default).
		NoGrabServer	All X10 GrabServer requests are
				ignored (as are UngrabServer).
		AllowGrabMouse	Any X10 GrabMouse requests will become
				X11 GrabPointer requests (default).
		NoGrabMouse	All X10 GrabMouse requests are
				ignored (as are UngrabMouse).
		AllowGrab	Both AllowGrabServer and AllowGrabMouse.
		NoGrab		Both NoGrabServer and NoGrabMouse.

	where flag is a '+' (or '-') followed by any of the the following
	words.  The '+' means to turn on debugging for the corresponding
	item and '-' is the inverse.  The default state is off for all
	flags.
		All		Show (don't show) every all debug information.
		Events		Show all incomming X11 events and what
				X10 event they were mapped to.
		Requests	Show all incomming X10 requests and
				their reply.
		Fonts		Show the X10 requests Text, TextMask,
				GetFont, FreeFont, QueryFont, CharWidths
				StringWidth and FontWidths.
		EventMasks	Show the conversion of X10 to X11 event
				masks and vice-versa.
		ButtonMasks	Show the conversion of X10 to X11 button
				masks and vice-versa.
		Bitmaps		print out received bitmaps.
		Unimplemented	Show unimplemented features when they are
				needed.
		WinTree		On the creation of every window, show the
				corresponding X10 client's idea of what the
				tree of windows looks like.
		PromptForEachRequest
				Each request that is being debugged is followed
				by a prompt and will wait for a <return> from
				the user before further processing.
		PromptForEachEvent
				For each X11 event being debugged, prompt
				the user before delivering the event.  When
				prompted, if the first character typed is
				an 's', then the event is "suppressed" and
				not sent on to the X10 client.
		LineCoordinates	For the requests Line, Draw and DrawFilled,
				the coordinates of each point in the request
				and associated flags are printed.
		Sequence	Show sequence information and associated
				actions in the PC.
		<X11 event>	Show a particular X11 event and its mapping
				to an X10 event, such as +MotionNotify or
				-MappingNotify.
		<X10 request>	Show a particular X10 request and its
				associated reply, such as +MapWindow or
				-FontWidths.

In addition, by sending a keyboard interrupt to the PC, you can enter any
of the above commands, one per line, with the following additional commands:
		WinTree		(that is, no preceeding +/-) This prints
				out immediately the entire window tree
				for each X10 client.
		Quit		exit the PC.
		Continue	

	
Implementation
--------------
The distribution consists of two subdirectories, X10 and X11.  X10
contains portions of code taken from the sample X10 server to implement
X10-style socket connection, and request dispatch.  The file X10/dispatch.c
has only the structure of the large switch statement intact, but now calls
external routines to carry out the requests.  The X11 directory contains
several files to implement each of the protocol requests, one routine
per request (proto[1-4].c); a file to translate X11 events into X10
events (events.c); some files to aid in debugging and other files
to accomplish miscelaneous tasks.

The PC is IO driven.  Sockets are examined regularly for connections on
internet and unix domain sockets, input from the X10 clients, and input
from the X11 server.  X10 requests from clients are responded to as
they arrive, replying as necessary.  X11 events are translated
at appropriate times; in particular, just before replies to X10
requests are sent.  This maintains the assumption (for the most part)
that if an X10 client has made a request requiring a reply, all events
resulting from earlier requests, such as MapWindow, will be delivered
before the reply.

Bugs
----
This implementation uses the gc clip mask to implement the clipping
caused by Transparent windows in X10.  There are four requests that
use a bitmap mask in X10: PixFill, TileFill, BitmapBitsPut and
PixmapBitsPut.  PixFill and BitmapBitsPut can be implemented with
stipple tiling, but TileFill and PixmapBitsPut cannot be done in this
way, and must use the clip mask.  Currently, this use will invalidate
the clipping that would have been caused by the use of a transparent
window, but at least the origin of the window is correct. 

The X10 UnmapTransparent request is impossible to implement under X11 because
X11 will not allow you to suppress exposure events for other clients.  The
best that can be done is to suppress the events for the client issuing
the request.  In addition, UnmapTransparent left the bits on the screen
unchanged.  There are two ways that "SaveUnders" were implemented in X10:
     1) - PixmapSave area on Root window
	- Map window over saved area (usually a menu)
	- UnmapTransparent on the window
	- PixmapPut the saved area on the Root window

     2) - PixmapSave area on Root window
	- Map window over saved area (usually a menu)
	- PixmapPut the saved area on top of the menu window
	- UnmapTransparent the menu window

Both accomplished the same thing.  #1 works just fine through the protocol
converter.  #2 will leave any X10 clients unrestored because it is not
possible to unmap a window in X11 and leave the screen intact.  The solution
could be very complex:
     a) On every UnmapTransparent, save the area covered by the window,
	then do the UnmapTransparent followed by a copyarea on top of
	the old window region.  This could be slow for the same reason that
	PixmapSave is slow (see below), making the SaveUnder operation
	doubly slow.  This also penalizes #1 above for the sake of #2.
     b) Whenever a PixmapSave happens, make note of the region saved an
	watch for a window that gets mapped over the same region.
	If there is one, try to see if it gets PixmapPut'ed onto
	the window.  If so, then hang onto the Pixmap, and if it is followed
	by an UnmapTransparent, then PixmapPut it again.  This fixes #2.
     c) Rely on SaveUnders in X11.

PixmapGet is untested in its current implementation.

The PC does not even try to handle ReparentNotify, GravityNotify,
CirculateNotify, SelectionClear, SelectionNotify or SelectionRequest events,
although it would be easy.

When an X10 request would yield an event mask, no effort is made to use
the event mask provided in other X10 requests, such as SelectInput.
Instead, the X10 mask is interpolated from the X11 mask; but this
is not a one to one mapping.  In particular, ExposeWindow and ExposeRegion
are lost.  This could be fixed by looking up the window internally and
using the mask found there.

In the X10 CreateWindow request, the X10 spec does not say what the
border_pixmap should be if it is specified as 0 and the border width
is > 0.  The PC assumes the X11 CopyFromParent.

X10 brush width and height are colapsed into X11 line width.
This could be solved by looking at the slope of the line
and deciding:
     vertical:       X11 line width is X10 brush width
     horizontal:     X11 line width is X10 brush height
     0<slope<infite: X11 line width is some function of
                        X10 brush width and height
This will work for the X10 Line request, but this is an incomplete
solution for a series of points specifying several segments:
Draw and DrawFilled.

For the X10 request GetColorCells, the PC assumes that the default
colormap is of class PseudoColor,  in which case, the masks we get back
are exactly one bit apiece, and by or'ing them all we get the
``planemask'' that X10 knows.  We should check to be sure that class is
PseudoColor, and do something appropriate otherwise.

WhitePixel and BlackPixel in X10 were defined to be 1 and 0
respectively.  X11 makes no such guarentee.  If the X11 white and black
pixel are complementary, i.e., one is all 1's and the other is all 0's,
the PC does the appropriate thing, translating the graphics function
code if necessary.  This is always true with monochrome and should be
true for DirectColor and StaticGray.  StaticColor and TrueColor may or
may not have this property, but if not, there is nothing that can be
done.  GrayScale and PseudoColor are programmable, and hence a new
colormap could be issued with a white and black pixel assigned
appropriately, but the PC makes no effort at this.

For the X10 requests ChangeBackground and TileMode, there were four
possible combinations for tiling:
	1) TileModeRelative	no pixmap
	2) TileModeRelative	uniq pixmap
	3) TileModeAbsolute	no pixmap
	4) TileModeAbsolute	uniq pixmap
In X11, only 1 and 4 are possible because only a pixmap or ParentRelative
can be specified; and None is not applicable here.

The PC ignores inter-character pad and space pad for the Text and TextMask
requests.  For the Text request, the PC uses XDrawImageString which
is only correct if function == GCcopy.  This could be fixed will a little
work.

X11 EnterNotify and LeaveNotify events are too complex for X10.  Some
time could be spent to map them better from X11 to X10.

The X10 GrabMouse works always, whereas the X11 GrabPointer will fail
if the event window is not viewable.  This could be fixed by reselecting
another window for the Grab when it fails and relabeling events as they arrive,
but it would be a bit of work.  Probably a better solution would be to
allow the GrabMouse to succeed even though the X11 GrabPointer failed
and then simply wait for the event window to be mapped; then try
the GrabPointer again.
