1 XKEYCAPS 
Graphically display and edit the X keyboard mapping - Version 2.29 - May 95

SYNOPSIS

 $ xkeycaps  [-toolkitoption ...] [-option ...]
2 DESCRIPTION
The xkeycaps program displays a keyboard.  Moving the mouse over a 
key describes the keysyms and modifiers that that key generates.  Clicking
left on a key simulates a KeyPress event.  Clicking right on a key brings
up a menu of operations, including a command to change the keysyms that
the key generates.  This program is, in part, a graphical front-end to
xmodmap (1).

2 OPTIONS
xkeycaps accepts all of the standard toolkit options, and also accepts the
following options:
 
    -keyboard keyboard-name or -kbd keyboard-name
Specifies the type of keyboard to display.  There are many different computer
keyboards in the world, and xkeycaps must know which one you are using 
in order to function correctly.  Case does not matter when specifying a 
keyboard name.

If you're running on the console display of a Sun or HP, then xkeycaps
will interrogate the attached keyboard hardware directly to determine
what keyboard you're using.  But if you're running remotely, or on another
type of machine, then you must specify a keyboard somehow.
 
    -help
Lists the recognised values for the -keyboard option.
 
    -gutterwidth number or -gw number
Specifies the number of pixels of space to leave between each key.
 
    -font fontname
Specifies the font to use to display the keycaps.

The following standard X Toolkit command line arguments are commonly 
used with xkeycaps:
 
    -display host:dpy
This option specifies the X server to contact.
 
    -geometry geometry
This option specifies the preferred size and position of the window.
 
    -bg color
This option specifies the color to use for the background of the window.
The default is light gray.
 
    -fg color
This option specifies the color to use for the foreground of the window.
The default is black.
 
    -bw number
This option specifies the width in pixels of the border surrounding 
the window.
 
    -xrm resourcestring
This option specifies a resource string to be used.  This is especially
useful for setting resources that do not have separate command line options.

2 DISPLAY
The bottom part of the window is a drawing of a keyboard.  In the top left of
each key is printed the string which actually appears on the surface of the
key.  In the bottom right of the key is the (hexadecimal) keycode that this
key generates.

At the top of the screen are several lines of text describing the key
under the mouse (or the most recently typed key.)  These lines are:
 
   KeyCode:
This displays the text printed on the physical key, and the keycode generated
by that key in hex, decimal, and octal.
 
   KeySym:
This displays the set of KeySyms that this key currently generates.  
 
   ASCII:
This displays the ASCII equivalent of this key, taking into account the
current modifier keys which are down.
 
   Modifiers:
this displays the modifier bits which this key generates.  If a key generates
modifiers, it is a chord-key like Shift or Control.
 
   AutoRepeat:
Whether the X server claims that this key autorepeats.  I
say ``claims'' because the OpenWindows X server is the only one I
have encountered for which this information is accurate.  The per-key
autorepeat flag seems to be almost-universally ignored.

2 COMMANDS
There are several buttons in the upper left corner of the window.  They are:
 
   Quit
Exits the program.
 
   Select Keyboard
Pops up a dialog box from which you can change which keyboard is displayed.
The left column lists the known types of keyboards, and the right column
lists the known layouts (mappings) of those keyboards.
 
   Type At Window
After selecting this, you are asked to click on some other window.  After
doing this, clicking on keys on the keyboard display will simulate key
events on the window you selected.  Selecting the root window or
the xkeycaps window turns this off.

If you are using a window manager (twm, for example) in which you
can lock the keyboard focus on a window and still click on other windows
without having the focus change, then you can accomplish the same thing
merely by focusing on another window and clicking on the keys in
the xkeycaps window.
 
   Restore Default Map
This command restores the keyboard to its default state.  If you execute
this command while displaying a keyboard which is not the type of keyboard
you are really using, your keymap will be in a nonsensical state.  There is
no way for xkeycaps to tell what keyboard you are using except by
taking your word for it, so don't lie.
 
   Write Output
This command writes an xmodmap input file representing the current
state of the keyboard (including all of your changes) to the standard output.
It prompts you with a dialog box: you can either write an xmodmap 
file representing the state of every key, or you can write a smaller
file which describes only the changes.

You can arrange for these bindings to be installed each time you log in
by placing the command

 $ xmodmap the-file-written-by-xkeycaps

in the appropriate init file.  If you don't know where that is, ask your
system administrator.

Clicking left on a key simulates a KeyPress event.  Releasing the button
simulates a KeyRelease event.  If you click left on a key and move the
mouse while the button is down, KeyPress and KeyRelease events 
will be simulated on every key you move the mouse over.  Think of the mouse 
as your finger: if you drag the mouse over several keys, they will go down
and up in turn.

Clicking left on a key which is associated with modifier bits (such as
Shift or Control) causes that key to ``lock'' down.  Clicking left again
releases the key.  In this way, you can generate key-chords with the mouse:
to generate Control-C, click left on the Control key, and then 
click on the C key.  Click on Control again to turn the control
modifier off.

Typing a key on the real keyboard simulates 
a KeyPress/KeyRelease event pair in the same way that
clicking on a key does.

You can also combine mouse and keyboard input: for example, if you use
the mouse to select the Shift key, and type a character, the event
that is simulated will have the Shift modifier set.  And if you
hold down the real Control key, and click on the C key in
the window, a Control-C event will be generated.  (Assuming, that 
is, that your window manager does not intercept control-left-button for its 
own purposes.)

Clicking right on a key pops up a menu of commands for the given key.
They are:
 
   Exchange Keys
After selecting this menu item, you are asked to click on another key.
That key and the key on which you brought up the menu will be exchanged.
This actually changes the current keyboard mapping.
 
   Duplicate Key
After selecting this menu item, you are asked to click on another key.
That key will be made a copy of the key on which you brought up the menu.
That is, the two keys will generate the same set of keysyms and modifiers.
This actually changes the current keyboard mapping.
 
   Disable Key
The key on which you brought up the menu will be made to generate no
keysyms and no modifiers.  This actually changes the current keyboard mapping.
 
   Restore Key To Default
The key on which you brought up the menu will be restored to its default
state; no other key will be altered.  This actually changes the current
keyboard mapping.
 
   Edit KeySyms of Key
This pops up the "Edit Key" window, which allows you to arbitrarily change
which keysyms and modifiers this key generates.

On the left side of the window is the list of the keysyms that this key
currently generates.  (A key may generate up to eight keysyms; the 
interpretation of these keysyms is described in the X protocol document,
and is summarized later in the KEYSYMS AND KEYCODES section of
this man page.)

The second column is a multiple-choice list of the eight modifier bits
that this key may generate.  For example, if you want a key to behave
as a ``control'' key, you should select the Control modifier.

The third and fourth column (the scrolling lists) are for changing the 
keysym associated with the key.  When you select a keysym-position from 
the first column, the character set and keysym will be displayed in
the scrolling lists.  Clicking on a keysym in the ``KeySym'' column will
install that keysym in the highlighted slot in the first column.

To select a keysym from a different character set, click on the character
set name in the second column.  (The Latin1 and Keyboard
character sets are the most commonly used.)

At the bottom of the window are three buttons: Undo, Abort, 
and Ok.  Clicking on Undo reverts the Edit Key window to the
current state of the key in question.  Abort closes the Edit Key
window without making any changes.  Ok closes the Edit Key window
and installs your changes (the current keyboard mapping is modified.)

2 X_RESOURCES
xkeycaps understands all of the core resource names and classes 
as well as:
 
   *Keyboard.keyboard (class Keyboard)
Which keyboard to display; this is the same as the -keyboard 
command-line option.  If this is not specified, the default keyboard
is guessed, based on the server's vendor identification string.
 
   *Keyboard.Keyboard.selectCursor (class Cursor)
The cursor to use when selecting a key or window with the mouse.
The default is the crosshair cursor.
 
   *Keyboard.Key.highlight (class Background)
The color to use to highlight a key when it is depressed.  If this is
the same as the background color of the key, it is highlighted with a
stipple pattern instead.
 
   *Keyboard.Key.keycapColor (class Foreground)
The color to paint the keycap string.
 
   *Keyboard.Key.keycodeColor (class Foreground)
The color to paint the keycode number.
 
   *Keyboard.Key.borderColor (class Color)
The color of the box around each key.
 
   *Keyboard.Key.keycapFont (class Font)
The font to use to draw the keycap string.
 
   *Keyboard.Key.keycodeFont (class Font)
The font to use to draw the keycode number.
 
   *Keyboard.Key.borderWidth (class Int)
The thickness of the box around each key.
 
   *Keyboard.Key.gutterWidth (class Int)
How many pixels to leave between this key and it's neighbors to the right
and bottom.

The class of each key widget is ``Key,'' as you see above.  The name of
each key is the string(s) printed on its face.  So if you wanted (for example)
the Shift keys to have wider borders, you could specify that with

  xkeycaps*Keyboard.Shift.borderWidth: 2

2 ACTIONS
It is possible to rebind the actions which happen when a key or mouse button
is pressed or released.  These actions are available on the Keyboard
widget:
 
   "HighlightKey(condition, arg)"
This places the key in question in the highlighted state.

If no argument is passed to this action, then the key is determined by
the event which invoked this action.  If this action is invoked by
a KeyPress or KeyRelease event, the key-widget is the key
corresponding to the key that the event represents.  If it is 
a ButtonPress, ButtonRelease, or PointerMotion event, 
then the key-widget is the one under the mouse.

The argument may be one of the words mouse, highlighted,
or displayed, meaning the key under the mouse, the key most recently
highlighted, or the key currently being described in the ``Info'' area
at the top of the window, respectively.

The condition may be one of the words ifmod, unlessmod,
iftracking, unlesstracking, ifhighlighted, or 
unlesshighlighted.  If ifmod was specified and the key in
question (as determined by the argument or by the invoking event) is 
not a modifier key, then this action is not executed.  The unlessmod 
condition is the opposite.  The iftracking and unlesstracking 
conditions allow you to do some actions only if (or unless) the key is 
being ``tracked'' with the mouse (see below.)  The ifhighlighted
and unlesshighlighted actions allow you to do some things only if
(or unless) the key in question is currently in the highlighted state.
 
   "UnhighlightKey(condition, arg)"
This places the key in question in the unhighlighted state.  Arguments
are as above.
 
   "ToggleKey(condition, arg)"
This makes the key be highlighted if it is unhighlighted, or unhighlighted 
if it is highlighted.  Arguments are as above.
 
   "SimulateKeyPress(condition, arg)"
This action makes a KeyPress event corresponding to the key be
synthesized on the focus window.  Arguments are as above.
 
   "SimulateKeyRelease(condition, arg)"
This action makes a KeyRelease event corresponding to the key be
synthesized on the focus window.  Arguments are as above.
 
   "TrackKey(condition, arg)"
This makes the key in question begin being ``tracked'', which means that
moving the mouse off of it will simulate a button-release action, and then
will simulate a button-press action on the key that the mouse has moved
on to.  This action may only be invoked from a ButtonPress
or ButtonRelease event.
 
   "UntrackKey(condition, arg)"
This makes the key in question no longer be ``tracked.''
 
   "DescribeKey(condition, arg)"
This action causes the key and its bindings to be displayed in the ``Info''
section at the top of the window, if it is not already described there.

The default actions for the Keyboard widget are:

 <Motion>:   DescribeKey(mouse,unlessTracking)      \\n\\
 \\
 <KeyDown>:  HighlightKey()                         \\
             DescribeKey(unlessMod)                 \\
             DescribeKey(displayed)                 \\
             SimulateKeyPress()                     \\n\\
 \\
 <KeyUp>:    UnhighlightKey()                       \\
             DescribeKey(displayed)                 \\
             SimulateKeyRelease()                   \\n\\
 \\
 <Btn1Down>: HighlightKey(unlessMod)                \\
             ToggleKey(ifMod)                       \\
             TrackKey(unlessMod)                    \\
             SimulateKeyPress(ifHighlighted)        \\
             SimulateKeyRelease(unlessHighlighted)  \\n\\
 \\
 <Btn1Up>:   UntrackKey(highlighted)                \\
             SimulateKeyRelease(highlighted,unlessMod) \\
             UnhighlightKey(highlighted,unlessMod)  \\n\\
 \\
 <Btn3Down>: XawPositionSimpleMenu(keyMenu)         \\
             MenuPopup(keyMenu)                     \\n
 
If you don't want a key to be described each time the mouse moves over
it, you can remove the <Motion> action.  In that case, you should
probably add DescribeKey() to the <Btn1Down> and <KeyDown>
actions.

If you want the key under the mouse to be described even while the mouse
is moving with a button down, then remove the unlessTracking
parameter from the DescribeKey action bound to <Motion>.

If you don't want the modifier keys to toggle, then change the Button1
actions to

xkeycaps*Keyboard.actions:  #override               \\
        <Btn1Down>: HighlightKey()                  \\
                    TrackKey(unlessmod)             \\
                    SimulateKeyPress()              \\n\\
        <Btn1Up>:   UntrackKey(highlighted)         \\
                    SimulateKeyRelease(highlighted) \\
                    UnhighlightKey(highlighted)     \\n

Remember that these actions exist on the Keyboard widget, not on
the Key widgets.  If you add actions to the Key widgets,
things will malfunction.

2 KEYSYMS_AND_KEYCODES
The following description is from the X Protocol document, and is reprinted
here for your convenience:

A list of KeySyms is associated with each KeyCode.  If that 
list (ignoring trailing NoSymbol entries) is a single KeySym ``K'',
then the list is treated as if it were the 
list ``K NoSymbol K NoSymbol''.  
If the list (ignoring trailing NoSymbol entries) is a pair 
of KeySyms ``K1 K2'', then the list is treated as if it were the 
list ``K1 K2 K1 K2''.  If the list (ignoring trailing NoSymbol 
entries) is a triple of KeySyms ``K1 K2 K3'', then the list
is treated as if it were the list ``K1 K2 K3 NoSymbol''.

The first four elements of the list are split into two groups
of KeySyms.  Group 1 contains the first and second KeySyms, 
Group 2 contains third and fourth KeySyms.  Within each group, if the
second element of the group is NoSymbol, then the group should be
treated as if the second element were the same as the first element, except
when the first element is an alphabetic KeySym ``K'' for which both
lowercase and uppercase forms are defined.  In that case, the group should
be treated as if the first element were the lowercase form of ``K'' and the
second element were the uppercase form of ``K''.

The standard rules for obtaining a KeySym from a KeyPress event make
use of only the Group 1 and Group 2 KeySyms; no interpretation of
other KeySyms in the list is given here.  (That is, the last four
KeySyms are unused.)

Which group to use is determined by modifier state.  Switching
between groups is controlled by the KeySym named Mode_switch.

By attaching that KeySym to some KeyCode and attaching 
that KeyCode to any one of the modifiers Mod1 
through Mod5.  This modifier is called the ``group modifier''.  
For any KeyCode, Group 1 is used when the group modifier is off, 
and Group 2 is used when the group modifier is on.

Within a group, which KeySym to use is also determined by
modifier state.  The first KeySym is used when the Shift 
and Lock modifiers are off.  The second KeySym is used when 
the Shift modifier is on, or when the Lock modifier is on 
and the second KeySym is uppercase alphabetic, or when the Lock
modifier is on and is interpreted as ShiftLock.  Otherwise,
when the Lock modifier is on and is interpreted as CapsLock,
the state of the Shift modifier is applied first to select
a KeySym, but if that KeySym is lowercase alphabetic, then 
the corresponding uppercase KeySym is used instead.

2 THE_MODIFIER_MAPPING
The following description is from the InterClient Communications 
Conventions Manual:

X11 supports 8 modifier bits,  of which 3 are pre-assigned to Shift,
Lock and Control.  Each modifier bit is controlled by the state
of a set of keys, and these sets are specified in a table accessed by
GetModifierMapping() and SetModifierMapping().

A client needing to use one of the pre-assigned modifiers should assume that
the modifier table has been set up correctly to control these modifiers.
The Lock modifier should be interpreted as Caps Lock 
or Shift Lock according as the keycodes in its controlling set
include XK_Caps_Lock or XK_Shift_Lock.

Clients should determine the meaning of a modifier bit from the keysyms
being used to control it.

A client needing to use an extra modifier,  for example Meta,  should:

Scan the existing modifier mappings.
If it finds a modifier that contains a keycode whose set of keysyms
includes XK_Meta_L or XK_Meta_R, it should use that modifier bit.

If there is no existing modifier controlled by XK_Meta_L 
or XK_Meta_R, it should select an unused modifier bit (one with an
empty controlling set) and:

If there is a keycode with XL_Meta_L in its set of keysyms, add that
keycode to the set for the chosen modifier, then

if there is a keycode with XL_Meta_R in its set of keysyms, add that
keycode to the set for the chosen modifier, then

if the controlling set is still empty,  interact with the user to
select one or more keys to be Meta.

If there are no unused modifier bits, ask the user to take corrective action.

This means that the Mod1 modifier does not necessarily mean Meta,
although some applications (such as twm and emacs 18) assume that.
Any of the five unassigned modifier bits could mean Meta; what matters is
that a modifier bit is generated by a keycode which is bound to the
keysym Meta_L or Meta_R.

Therefore, if you want to make a ``meta'' key, the right way is to make
the keycode in question generate both a Meta keysym, and some
previously-unassigned modifier bit.

2 ENVIRONMENT
 
   DISPLAY
to get the default host and display number.
 
   XENVIRONMENT
to get the name of a resource file that overrides the global resources
stored in the RESOURCE_MANAGER property.
 
   XKEYSYMDB
to get the location of the XKeysymDB file, which lists the 
vendor-specific keysyms.  

2 BUGS
Because this program has default colors that aren't "black" and "white",
the -rv command-line option doesn't work.  But the incantation

 $ xkeycaps -fg white -bg black -bd white

will do what you want on a monochrome screen.

The NeXT default map is believed to be incorrect; someone with access to 
a NeXT will need to debug this.

There is no portable way to be sure what keyboard is being used; this means
it will often not default to the correct one, and if the user makes changes
to the keymap while displaying a keyboard which is not the right one, very
bad things can happen.

If you depress more than a dozen keys at a time, many X servers get confused,
and don't transmit enough KeyRelease events; the result of this is
that the xkeycaps keys will get ``stuck'' until they are pressed again.
(Don't go like that.)

The AutoRepeat flag is apparently useless on all X servers except the
OpenWindows one (I've never seen another server that didn't ignore it.)

You don't get to select from the set of Vendor keysyms (those keysyms
which are defined in the XKeysymDB file) unless you're running X11r5
or newer.

NCD's non-US keyboards do not use the standard R4/R5 mechanism for attaching
more than two keysyms to one key; instead of simply having three or four 
keysyms attached to the keycode in question, the Compose key changes the
actual keycode of the key (it turns its high bit on.)  The xkeycaps program
doesn't really understand this.  Someone from NCD support told me that in
future releases they will do things the R4/R5 way instead of the way they
do things now, so hacking xkeycaps to understand the current behavior is 
probably not worth the effort.

The Type at Window command doesn't seem to work on the WreckStation
version of XTerm.  I assume some variation of the normal XTerm's
Allow SendEvents command is necessary.

If the popup menu is always greyed out, or doesn't correspond to 
the key that you bring it up over, it's probably because you're 
running xswarm, an old version of xautolock, or some other 
program that antisocially interferes with event-propagation.  (Don't go
like that.)

Because of the nonlinear way in which this program uses XLookupString,
there's no sensible way for it to do compose processing, and show you the 
results of ``dead'' key or Multi_key sequences.

The output should be written to a file instead of to standard-output; but
the Athena widget set doesn't seem to come with a file-requestor widget,
and I don't want to write one.

It needs to know about more keyboard types (and no doubt always will...)

L-shaped keys aren't drawn accurately.  We should use the Shape extension
for that.

In addition to displaying the ASCII version of the given character, it
should display the corresponding character in the character set (Latin2,
Kana, Greek, etc.)  This would require having fonts for all of those 
character sets, though, and as far as I can tell, they don't all come
standard.

When running on a Sun and talking to an OpenWindows server, we should parse
the appropriate file from $OPENWINHOME/etc/keytables/ to determine the
default keymap.  No doubt there are system-specific ways of doing this in
other environments as well.

The HP C compiler complains about "invalid pointer initialization" in the
header files.  This is a bug in that compiler, not in xkeycaps.  This compiler
bug goes away if you invoke HP's cc with the the -Aa (ANSI) option.

The xmodmap program still sucks.  Since its ADD and REMOVE
directives take keysyms as arguments instead of keycodes, there are things
that you can do with XKeyCaps that you can't represent in
an xmodmap script (at least, not without great pain.)

The xmodmap program has no commands for changing the autorepeat status
of keys, so that information is not written in the output.  Perhaps we could
write out an appropriate xset command instead.

Some versions of OpenWound use a nonstandard mechanism for specifying which
keys have toggle (lock-like) behavior (whereas most other X servers base this
behavior on the keysym: if Caps_Lock or Shift_Lock is generated, the key
locks, otherwise it does not.)  XKeyCaps doesn't know how to change
the lock status on these servers.  This is because I don't know how, either.
If you know what system calls are necessary to hack this behavior, tell me.

The XKB interface of X11R6 looks to provide most of the information
which xkeycaps needs to know, but I haven't had time to investigate this yet.

2 COPYRIGHT
Copyright (co 1991-1994 by Jamie Zawinski.  Permission to use, copy, modify, 
distribute, and sell this software and its documentation for any purpose is 
hereby granted without fee, provided that the above copyright notice appear 
in all copies and that both that copyright notice and this permission notice
appear in supporting documentation.  No representations are made about the 
suitability of this software for any purpose.  It is provided "as is" without
express or implied warranty.

2 AUTHOR
Jamie Zawinski <jwz@netscape.com>, 10-nov-91.
Please let me know if you find any bugs or make any improvements.

Thanks to:
Jonathan Abbey,
David Axmark,
Eric Benson,
Markus Berndt,
Roger Binns,
black@westford.ccur.com,
Volker Bosch,
Dave Brooks,
Francois Regis Colin,
Christopher Davis,
Michael Elbel,
Joe English,
Carson Gaspar,
Christian F. Goetze,
Dan R. Greening,
Magnus Hammerin,
Tom Ivar Helbekkmo,
Hide Horiuchi,
Dirk Jablonowski,
Chris Jones,
Benedikt Kessler,
Philippe Kipfer,
John Knox,
Frederic Leguern,
Simon Leinen,
Michael Lemke,
Torbj|rn Lindgren,
Tony Lindstrom,
Richard Lloyd,
Cliff Marcellus,
Tom McConnell,
Grant McDorman,
Jason Merrill,
Pekka Nikander,
Todd Nix,
Steven W. Orr,
Daniel Packman,
Chris Paulson-Ellis,
Todd Richmond,
Pavel Rosendorf,
Andreas Schuch,
Joerg Stippa,
Juergen Stuber,
Markus Stumpf,
Anthony Thyssen,
Christoph Tietz,
Gord Vreugdenhil,
Jan Wedekind,
Bj|rn Wennberg,
Mats Wichmann,
Stephen Williams,
Carl Witty,
and
Kazutaka Yokota.

2 VMS_PORT
Patrick Moreau - CENA/Athis-Mons - FRANCE

pmoreau@cena.dgac.fr
