This file documents the use and the internals of shX, the Shared X library for X11 release 3.

Copyright (C) 1990, Digital Equipment Corporation

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Introduction
************

This manual documents how to use, install and port shX, and how to report bugs.

Copyright
*********

Copyright © 1990 Digital Equipment Corporation

Permission to use, copy, modify, and distribute this software and its documentation without fee is hereby granted, but only for non-profit  use and distribution,  and provided  that the copyright notice and this notice is preserved on all copies.

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

What is shX?
************

The name shX stands for Shared X and I hope this gives you a hint what it is good for.  If not, here's a short explanation.

With the term shared we don't mean a shareable library, but we mean a modified Xlib that allows window sharing in X across multiple workstations.

I've implemented shX in the context of computerbased learning/training to provide online help from remote tutors.  The tutor will get a replica of the course on the display (see, that's my problem) and will then demonstrate the solution by manipulating the replica (see, that's the solution).

You can think of other scenarios where window sharing could be useful, e.g. remote debugging or tele conferencing.

The development of this modified library was guided by four major goals:

Transparency
     No modifications should be necessary to add this new functionality to an existing application.  The application should not be aware of being shared.

Dynamics
     Adding and removing displays to an application should be possible at any time.

WYSIWIS (What You See Is What I See)
     The output of a shared application should be identical on all displays.

Tolerance
     The modified library should compensate tolerable hardware differences (which manifest themselves in Visuals); e.g. it should be possible to replicate an application on a PseudoColor display that has been invoked on a StaticGray display.

The shX library is a modified version of the low-level programming interface to X, the Xlib.  This documentation will tell you how to install and use shX on your system.

Installing shX
**************

The Installation procedure
==========================

Here is the procedure for installing shX on a Unix system.

 1. Make a symbolic link named m.h to the machine description file for your machine.  It should be in the subdirectory ./machines and its name should be m-MACHINE.h. See Machines for a list of machines and corresponding machine description files.

     Example: If you have a Vax and run Ultrix, type

          ln -s ./machines/m-vax.h m.h

     See Internals if there is no machine description file for your machine.

 2. Copy the file config.h-dist to config.h.  This file contains information about your machine and configuration.  Edit it if necessary.  It includes m.h.

 3. Type make, lean back, and have a beer.

For successful compilation, you should use an ANSI C compiler, such as gcc.  If everything is ok, the resulting library is called libshX11.a.  See Trouble if you have trouble with an existing port.  See Internals if you want to port the shX library to a new machine.

To link an X application against shX, install the library in your default system directory for libraries (e.g.  /usr/local/lib) and type something like

gcc -o foo *.o [-lXaw -lXt ..] -lshX11

As work on shX was completed one week before X11R4 was released, note that this library is a X11R3 library (if you want to port it to R4, feel free to do so).

Make sure that your application includes the X11R3 header files from (TOP)/shXlib/X11.

Sharing is controlled by a separate application that I called the helper.  To build the helper, see file README in the helper directory.  See Share for how to use it.

List of successful ports
========================

This is a list of machines and operating systems, shX currently runs on.  It also says which machine description file from (TOP)/shXlib/machines to use if you want to build shX on a particular configuration.

VAX
     under Ultrix 3.2, 4.*.

     Use m-vax.h.

DECstation
     2100, 3100 and 5000 under Ultrix 4.*.

     Use m-mips.h.

SUN Sparc
     Use m-sparc.h.

SUN 3
     Use m-sun3.h

How to share an application
===========================

To share an application you need another X application, that we have called the helper.  It has three options:

Add a host
     To establish new connections to other X Displays dynamically and multiplex the output of a sharable application to these additional displays.  Usage:

             helper + <display> <display> ...

     When replication starts, the modified library will ring the bell.

     Don't do anything with the application you want to share during this interval (AND don't move or resize the application after replication; window management isn't implemented yet !!!).

     If the bell doesn't ring, your application is waiting for a useful event (it will not get informed about this "add-new-displays"-event); do some- thing "useful with it (like moving/clicking the mouse)

Remove a host
     Remove display connections that have previously been added.

             helper - <display> <display> ...

Pass the chalk
     Pass the input control to another display (or get the input control back).

             helper c[halk]

If you need more help on using or installing the standard helper, see file README in the helper directory.

Known Causes of Trouble with shX.
=================================

Here are some of the things that have caused trouble for people installing or using shX.

I did some very crude additions to make it link against the DECwindows Toolkit (dwt), but any call to XSelectAsyncInput or the VMS emulation will kill it.

I have spent a lot of time working on the color mapping stuff, but it will not work in all situations, because `some' applications (e.g. the ones that are using the Xt Intrinsics) are doing strange things (don't be alarmed if you get black text on black background).

Missing link options: if you compile the sources with -DDNET_CONN, make sure that you link the DECnet library (-ldnet) to your application.

As mentioned before, shX is a X11R3 library. and currently does not support any extensions.  If you link your application with -lXext, your linker might complain about some undefined symbols.  If you don't really need any of the Release~4 extensions, omit -lXext.

You are working on a node foo and want to share an application with your friend on node bar, but Xlib tells you:

     Xlib:  connection to "bar:0.0" refused by server
     Xlib:  Client is not authorized to connect to Server
     Error: Can't Open display

The command xhost +foo typed on node bar helps you.

If you pass the chalk to another display, and the application does not react on user input, you are not using the modified select system call. See Select for explanation how to use it.

Internals of shX
****************

One of our main goals was to allow a transparent multiplexing of applications.  There would be no problem if all the X communication was done via Xlib calls.  Alas, all toolkits bypass the Xlib layer for some reasons by using the select system call (See e.g the XtNextEvent routine in the Xt Intrinsics).

The Select Problem
==================

In this context transparent sharing means that we have to replace the select system call by our own version which simply adds the file descriptors of all additional displays (you will find the replacing code in the file io.c).  This can be done in two different ways:

 1. Mask all select system calls in an application

 2. Mask only the critical calls, i.e. select calls that deal with X connections.

To mask all select system calls, compile io.c with -DMY_OWN_SELECT.  Then there will be a routine select in this file that emulates the select system call.  The real system call is invoked by calling sElEcT.  This is the default if you use the standard installation procedures.  It also presupposes that there is an appropriate file ./select/sElEcT_MACHINE.o that you can use.  If not, here is a quick and dirty solution to get one.

 1. Extract the object file from the c library

                ar x /usr/lib/libc.a select.o

     nm select.o will tell you something like

          	U _cerror
          	T select

 2. Edit the file and replace the text symbol select with sElEcT.

 3. Put this modified file in your shXlib archive in ./select/sElEcT_MACHINE.o

 4. Create an appropriate machine description file ./machines/m-MACHINE.h.  Do this by copying an existing one and change the Symbol SOF to point to your new sElEcT object file.

 5. Recompile with make.

If you want to mask just the critical select calls, compile io.c without -DMY_OWN_SELECT.  Then there will be a routine sElEcT in io.o.  What you have to do then is to replace all critical select calls in your application by sElEcT calls.  To build a library of this version, you simply have to omit the definition of SOF in the machine description file you use.

The External Communication Interface
====================================

If you don't like the standard helper provided with this distribution, and you want to wrap a toolkit around it, this is the way the helper works.  I use the two "ipc" mechanisms X provides:

  * properties

  * sending events

On each top level window of an application that's passed through the shXbridge, three new properties are added:

 1. One is "called" (property type -->atom) XMUX_CPORT :== XMUX Communication PORT

 2. The second one is called XMUX_HOSTS

 3. The third is called XMUX_CHALKHOLDER

All three are of type STRING.

Adding/Removing Hosts
---------------------

XMUX_CPORT is used to add/remove hosts to your session.

If you want to add foo:0 and bar:0 to your session, change the value of the XMUX_CORT property on any top-level window to:

     +foo:0,bar:0

The list MUST start with a + (it's indicating that you want to ADD hosts), the display names have to be in compliance with X, and the names are separated by colons.

Removing hosts looks pretty much the same except that the + is replaced by a -:

     -foo:0,bar:0

Note that this property is consumed by the bridge, i.e. if this property has been changed by the helper to trigger addition/removal of hosts, the bridge will get the property with mode set to delete.

Current Status of your Session
------------------------------

The XMUX_HOSTS property contains --- as a string (see above) --- the list of all hosts that currently join this session separated by commas. XMUX_CHALKHOLDER contains the host that currently "holds the chalk", i.e. has the input control.  XMUX_CHALKHOLDER is added the first time you pass the chalk.  If XMUX_CHALKHOLDER doesn't exist, the primary display (i.e. the display where the application was started) has the chalk.

Passing the Chalk
-----------------

To pass the chalk to another host, the helper sends an event of type client message to the application.  All shX specific events have a special structure:

     type:		ClientMessage
     serial:		  ...
     send_event:	True
     display:		...
     window:		  ...
     message_type:	XMUX_MESSAGE   (--> atom)
     format:		32
     u.l[0]:		"message type"
     u.l[1]:		"message subtype"
     u.l[2]:		"detail"
     u.l[3]:		...
     u.l[4]:		...

``Passing the chalk to host n'' is encoded by:

     u.l[0]:		XMUXAction
     u.l[1]:		XMUXPassChalk
     u.l[2]:		n

XMUXAction and XMUXPassChalk are predefined constants; they are defined in the header file XmuX.h (This file should be included in the helper sources you have copied).  N refers to the POSITION of the host in the XMUX_HOSTS list (see above), e.g.

     XMUX_HOSTS = foo:0,bar:0,baz:0

If you want to pass the chalk to bar:0, n should be equal to 1 (the list starts with 0).

As you can see in the XmuX.h file, there's room for other ``features,'' but I didn't implement any of them.

I hope this description will give you enough information to build your own controlling interface.

Reporting Bugs
**************

Your bug reports play an essential role in making shX reliable.

Reporting a bug may help you by bringing a solution to your problem, or it may not.  But in any case the important function of a bug report is to help the entire community by making the next version of shX work better.  Bug reports are your contribution to the maintenance of shX.

In order for a bug report to serve its purpose, you must include the information that makes for fixing the bug.

Send bug reports for shX to one of these addresses:

     altenhofen@kampus.enet.dec.com
     KAMPUS::ALTENHOFEN

As a last resort, send bug reports on paper to:

     Michael P. Altenhofen
     Digital Equipment
     CEC Karlsruhe
     Vinzenz-Priessnitz-Str. 1
     D-7500 Karlsruhe 1
     Germany

The fundamental principle of reporting bugs usefully is this: report all the facts.  If you are not sure whether to state a fact or leave it out, state it!

Often people omit facts because they think they know what causes the problem and they conclude that some details don't matter.  Thus, you might assume that the name of the variable you use in an example does not matter.  Well, probably it doesn't, but one cannot be sure.  Play it safe and give a specific, complete example.  That is the easiest thing for you to do, and the most helpful.

Keep in mind that the purpose of a bug report is to enable me to fix the bug if it is not known.  It isn't very important what happens if the bug is already known.  Therefore, always write your bug reports on the assumption that the bug is not known.

Sometimes people give a few sketchy facts and ask, ``Does this ring a bell?''  Those bug reports are useless, and I urge everyone to refuse to respond to them except to chide the sender to report bugs properly.

To enable me to fix the bug, you should include all these things:

  * The version of shX.  You can get it by calling the function shXversion() or looking at file xmakefile.

     Without this, I won't know whether there is any point in looking for the bug in the current version of shX.

  * The name of the file that you used for m.h when you installed the library.

  * The type of machine you are using, and the operating system name and version number.

  * A complete description of what behavior you observe that you believe is incorrect.

  * If you wish to suggest changes to the shX source, send me context diffs.  If you even discuss something in the shX source, refer to it by context, not by line number.

     The line numbers in my development sources don't match those in your sources.  Your line numbers would convey no useful information to me.

  * Additional information from a debugger might enable me to find a problem on a machine which I do not have available myself. However, you need to think when you collect this information if you want it to have any chance of being useful.

  * A patch for the bug does help me if it is a good one.  But don't omit the necessary information, such as the test case, on the assumption that a patch is all I need.  I might see problems with your patch and decide to fix the problem another way, or I might not understand it at all.

Projects, Ports and other things left to do.
********************************************

  * Add cursor echoing.

  * Synchronize window management.

  * Port it to Release 4. This includes features like shared memory transport and shape extension.

  * Port to other platforms.

  * A more sophisticated control interface.

  * Link GNU Emacs against shX, and write the elisp functions that simulate the helper (e.g.: shX-add-node shX-del-node shX-pass-chalk).