%
% VirtKeys.tex -- Documents the Virtual Keysym Mechanism within LessTif
%
% (c) 1996 The Hungry Programmers
% (c) 1996 Harald Albrecht (albrecht@igpm.rwth-aachen.de)
% See the file PUBLIC for details.
%
\chapter[When the Keyboard Goes Wild]{When the Keyboard Goes Wild\\}
\by{Harald Albrecht}

\section{Introduction}

To some extent, the way X treats keyboard input is more complicated
than handling the pointing device events (or many other events). The
information about a key in the event structure isn't suitable for
immediate use, instead it has to go through one of several conversion
stages before it becomes useful to the application.  The main reason
is that X is designed to support all kinds of keyboards. However, the
drawback is increased complexity.

\index{keycode}\index{keysym}%
Keyboard input appears in three ``flavours'': as keycodes, keysyms or
keystrings. Naturally, \Motif{} adds a fourth one: the \CSF{} keysyms.
They are a special set of keysyms.  Figure \ref{Event_Processing}
shows how keycodes, keysyms and keystrings relate.

\begin{figure}[h]
\centerline{\includegraphics[scale=1.09]{EventProcessing}}
\caption{\label{Event_Processing}Keyboard event processing.}
\end{figure}

A keycode is a hardware-dependent coding of the key being pressed or
released. Thus, keycodes aren't really usefull to \LessTif{}
application writers. With the help of the keyboard mapping, every Xlib
and/or Xt intrinsics client converts the hardware-dependent keycodes
into hardware-independent keysyms. These keysyms are integers
representing the symbol engraved on a key (``a'', ``A'', ``+'' as well
as ``Shift'', ``PageDn'' and other ones). The keyboard mapping is read
from the server and cached to speed up look-ups and prevent
unnecessary round-trips to the server. The translation from keycodes
to keysyms can be done with \code{XtTranslateKeycode()}. This calls
the currently registered key translator procedure, which is
\code{XmTranslateKey()} by default. The translation manager calls the
key translator procedure, too.

Keysyms that represent printable characters can be further translated
into keystrings by calling \code{XTranslateKey()}. This mapping
between keysyms and keystrings is not stored in the X server, but
rather hardwired into the Xlib.

\section{The Virtual Bindings}

\index{virtual bindings}%
Unfortunately the concept of keysyms leaves too much room for
vendor-dependent interpretations on how to bind keycodes to keysyms. A
constant source for confusion and frustration is the key
\keycap{$\longleftarrow$} at the top right of the alphanumeric key
area. Some vendors bind this key to the keysym \code{XK\_BackSpace},
some others to the keysym \code{XK\_Delete}.

\index{virtual bindings}%
The simplest way would be to change the keyboard mapping of the
server. But this would affect all clients connected to that server --
especially the non-\LessTif{} ones. In order to reassert some (basic)
consistency, the \CSF{} introduced the ``\CSF{} keysyms''. The
\CSF{} keysyms form a special set of keysyms. Depending on the X server's
vendor, certain keycodes are translated into \CSF{} keysyms. The
mappings between keysyms and \CSF{} keysyms are also known as the
``virtual bindings'' (see figure \ref{VK_Mapping}). The conversion
between keypresses and keysyms takes place in \code{XmTranslateKey()}.

\begin{figure}[h]
\centerline{\includegraphics[scale=1.09]{VKMapping}}
\caption{\label{VK_Mapping}The ``virtual bindings'' take care of some
basic consistency between different keyboards.}
\end{figure}

\index{modifiers}\index{modifiers!fake}%
When converting ordinary innocent keysyms into \CSF{} keysyms the
modifiers must be taken into consideration. Unfortunately, we have to
cope with different kinds of modifiers when looking at the virtual
binding mechanism or the translation manager. An example shall
enlighten the problem arising from this. Suppose your new WYSIWYWAA
widget (\textsc{What You See Isn't What You Wanted After All}) also
features an ``undo'' operation. The undo is activated by pressing the
keys \keycap{ALT} and \keycap{$\longleftarrow$} together. Somewhere in
your widget's translation table you'll have to write:

\vspace{-1ex}
\begin{verbatim}
    Alt<Key>osfDelete:  undo()
    Meta<Key>osfDelete: undo()
\end{verbatim}
\vspace{-1ex}

As \LessTif{} -- or its ``alter ego'' \Motif{} -- converts some of the
standard keysyms into virtual keysyms, you can't use the standard
keysym name \code{Delete} but must use \code{osfDelete}. The
translation manager will never see the original keysym but only the
virtual keysym.

Although the ``\code{Alt}'' modifier preceeding the keypress translation
``\code{<Key>}'' looks suspiciously like any ordinary modifier
(e.g., \code{Shift}), it isn't one! X provides for eight modifiers
alltogether, but only \code{Shift}, \code{Lock}, and \code{Control}
are predefined. The remaining five modifiers \code{Mod1} up to
\code{Mod5} can be freely mapped to any key. Smart as the Xt intrinsics
are, they convert the translation \code{Alt<Key>osfDelete} into
a translation using the \keycap{Alt} {\em key} instead of a (ficious)
``Alt'' {\em modifier}. Unfortunately, many programmers aren't aware of
this.

Thus, when looking at translations, it is very important to distinct
between the two sets of \emph{real} modifiers and \emph{fake} modifiers:
The real modifiers are: \code{Shift}, \code{Lock}, \code{Ctrl},
\code{Mod1} up to \code{Mod5}, and the mouse buttons \code{Button1} up
to \code{Button5}, whereas fake modifiers are: \code{Alt},
\code{Meta}, \code{Super}, and \code{Hyper}.

During the process of converting keysyms into \CSF{} keysyms (in
\code{XmTranslateKey()}) no translation mechanism is present. All we have
is the current state of the modifiers recorded in the KeyPress
event. But only \code{Shift}, \code{Lock}, and \code{Control} are
predefined. So what to do with virtual bindings which are supposed to
translate \code{Alt}'ed keysyms into \CSF{} keysyms?

The \CSF{} decided to ignore the problem as good as possible when
developing \Motif{}, and depends on the user mapping the \keycap{Alt}
key on the keyboard to the \code{Mod1} modifier. You can test this by
changing your mapping such, that \keycap{Alt} maps to \code{Mod2}. The
respective virtual bindings won't work any longer.

\LessTif{} is much smarter than \Motif{} (What?! Impossible!). Unfortunately,
the \code{XmTranslate\-Key()} converter can't maintain the current
keyboard state of the \keycap{Alt} and \keycap{Meta} keys as it gets
called from the translation manager many times even for every {\em
single} keystroke. Thus, during startup \LessTif{} tries to find out
to which modifier the \keycap{Alt} key has been bound to. \LessTif{}
does this basically by scanning the modifier mapping (as returned by
\code{XGetModifierMapping()}) for the modifier bound to the keysyms
\code{XK\_Alt\_L} or \code{XK\_Alt\_R}.  If none can be found
\LessTif{} falls back to use \code{Mod1}. The whole procedure is so
easy to implement, I can't understand why the \CSF{} didn't get the trick
in the past. If you're interested how \LessTif{} does it, take a
look at the file \code{\textdollar(LESSTIF\_ROOT)/libXm/VirtKeys.c}.
The source is commented (really!).

\section{Managing the Modifier Mappings}

\index{modifiers!get mapping for display}%
\index{modifiers!invalidate mapping cache}%
\index{mapping chache}%
There are three functions available for messing about with the current
mapping of the \code{Alt} modifier (remember that these ones are
\LessTif{}-specific!):

\index{\_XmGetModifierMappingsForDisplay@\code{\_XmGetModifierMappingsFor-\\Display}}%
\index{\_XmInvalidateModifierMappingsForDisplay@\code{\_XmInvalidateModifierMappings-\\ForDisplay}}%
\codeindex{\_XmRefreshVirtKeys}%
\begin{verbatim}
XmModifierMaskSetReference _XmGetModifierMappingsForDisplay(Display *dpy);
void _XmInvalidateModifierMappingsForDisplay(Display *dpy);
void _XmRefreshVirtKeys(Widget w);
\end{verbatim}

You'll normally use only
\code{\_XmGetModifierMappingsForDisplay()}. This function reports the
current mapping as a pointer to a \code{XmModifiersMaskSet} (and
surely gets an olympic medal for its name's length). This set is
simply an array that holds the modifier masks for the \keycap{Alt},
\keycap{Meta}, \keycap{Super}, and \keycap{Hyper} modifier keys. If
\LessTif{} can't find a binding for the \keycap{Alt} key it will
fall back to the \code{Mod1} modifier mask as the \code{Alt} modifier
mask.

To get the modifier mask of the \code{Alt} modifier, just use the
index \code{ALTModifier} into the array:

\begin{verbatim}
#ifdef LESSTIF_VERSION
#include <Xm/VirtKeysP.h>
    XmModifierMaskSetReference ModifierMasks;
#endif
    Modifiers                  Alt, someModifierFlags;

#ifdef LESSTIF_VERSION
    ModifierMasks = _XmGetModifierMappingsForDisplay(dpy);
    Alt           = ModifierMasks[ALTModifier];
#else
    Alt           = Mod1Mask;
#endif

    someModifierFlags = ... ;
    if ( someModifierFlags & Alt ) {
        .... ;
    }
\end{verbatim}

The result of \code{\_XmGetModifierMappingsForDisplay()} is cached so
all but the first request won't result in a round-trip to the X
server. The modifier mask set belongs to the cache, so be sure to
never free it.

When the user changes the modifier mapping during the lifetime of a
\LessTif{} based application, \LessTif{} receives a MappingNotify
event and updates its modifier cache as well as the virtual bindings
by calling \code{\_XmRefreshVirtKeys()}. If for any reason you must
invalidate the modifier mapping cache, you can call
\code{\_XmInvalidate\-ModifierMappingsFor\-Display()}. Any pointer to the
modifier mapping array for the respective display then gets invalid!

\section{Managing the Virtual Bindings}

The virtual binding mechanism in \code{VirtKeys.c} provides four additional
(``undocumented'') functions to mess with:

\codeindex{\_XmVirtualToActualKeysym}%
\codeindex{\_XmVirtKeysInitialize}%
\codeindex{\_XmVirtKeysLoadFileBindings}%
\codeindex{\_XmVirtKeysLoadFallbackBin-\\dings}%
\begin{verbatim}
void _XmVirtualToActualKeysym(Display *Dsp, KeySym VirtualKeysym,
                              KeySym *RealKeysymReturn,
                              Modifiers *ModifierReturn);
void _XmVirtKeysInitialize(Widget w);
Boolean _XmVirtKeysLoadFileBindings(String filename, String *binding);
int _XmVirtKeysLoadFallbackBindings(Display *Dsp, String *Bindings);
\end{verbatim}

These four functions are available with \Motif{} as well as with
\LessTif{}.  With \code{\_XmVirtualTo\-ActualKeysym()} you can check how
a virtual keysym would look like in real life. You also get back from
the function the necessary modifiers which must be active in order to
convert the real keysym into a \CSF{} keysym.

The contents of a file can be loaded into memory by means of the
\code{\_XmVirtKeysLoadFile\-Bindings()} function. The memory needed to
hold the contents is allocated by the function and must be freed when
it's not needed any more. If the function fails for any reason (file
not found, not enough memory available)
\code{\_XmVirtKeysLoadFileBindings()} returns \code{False}.

If for any reason you need to set up the
\code{\_MOTIF\_DEFAULT\_BINDINGS} property of the root window of a
given display, you can use \code{\_XmVirtKeysLoadFallbackBindings()}
for this task. If applicable, the function will load a vendor-specific
set of virtual bindings. Otherwise it will fall back to a generic set
of virtual bindings. \code{\_XmVirtKeysLoadFallbackBindings()} returns
in the parameter \code{Bindings} the current set of virtual
bindings. You are responsible for freeing the string with
\code{XtFree()} when you don't need it any longer. The most
interesting use of this function is within the \code{xmbind}
client. If no binding file is specified and there is no
\code{.motifbind} file available, then \code{xmbind} can install the
default fallback bindings in the
\code{\_MOTIF\_DEFAULT\_BINDINGS} property. More on this in the next
section.

You will hardly need to call \code{\_XmVirtKeysInitialize()}, as this sets
up the virtual bindings on a \code{XmDisplay} widget. It gets
automatically called during the initialising phase of this kind of
widget. This function is solely for use within the \LessTif{} modules
\code{VirtKeys.c} and \code{Display.c}.

\section{The xmbind Client}

The current virtual bindings are stored in one of two possible
properties on the root window of \emph{screen} \#0. There can be only
one set of active virtual bindings at the same time on a given
\emph{display} as there exists only \emph{one} keyboard per display.
Therefore the current bindings are always stored in a property of the
root window of screen \#0. Please note that they are \emph{not}
attached to the root window of the default screen, as the default
screen can be any screen of a given display and may even change from
application to application (see figure \ref{Bindings}). The storage
for the current virtual bindings is provided by one of the following
properties (both of type
\code{XA\_STRING}):

\begin{itemlist}
\item The property \code{\_MOTIF\_DEFAULT\_BINDINGS} (if existent)
contains the default virtual bindings for the display.
\item The property \code{\_MOTIF\_BINDINGS} contains virtual bindings
loaded either from the user's \code{\textdollar(HOME)/.motifbind} file or
from \code{xmbind.alias} (available in several good places).
\end{itemlist}

If none of the two properties exist, \LessTif{}'s startup-code first
tries to find user-specific bindings and if it succeeds, it sticks
them to the \code{\_MOTIF\_BINDINGS} property. Otherwise the
starup-code figures out the default virtual bindings (according to the
display) and loads them into the \code{\_MOTIF\_\-DEFAULT\_BINDINGS}
property. In every case, after starting a \LessTif{} application the
root window of screen \#0 contains a property specifying the current
virtual bindings.

The \code{xmbind} client can be used to change or setup the properties
related to the virtual bindings. This client is remarkable simple, as
most of the functionality needed is already laid down in the
\LessTif{} library (mostly in the form of ``undocumented'' functions).
Following is the pseudo-code of \code{xmbind} (the source resides in
\code{\textdollar(LESSTIF\_ROOT)/clients/xmbind/xmbind.c}):

\begin{verbatim}
    if (°user specified a file on the command line°) {
        °delete the° _MOTIF_DEFAULT_BINDINGS °property°
        °load the file into the° _MOTIF_BINDINGS °property°
    } else {
        if (°there is a° .motifbind °file°) {
            °delete the° _MOTIF_DEFAULT_BINDINGS °property°
            °load the file into the° _MOTIF_BINDINGS °property°
        } else {
            °delete the° _MOTIF_BINDINGS °property°
            °load fallback bindings into the ° _MOTIF_DEFAULT_BINDINGS °property°
        }
    }
    °flush the connection to the display and terminate°
\end{verbatim}

\begin{figure}[t]
\centerline{\includegraphics[scale=1.09]{Bindings}}
\caption{\label{Bindings}Displays, Screens and the Virtual Bindings.}
\end{figure}


% End of VirtKeys.tex
