|
Department of Engineering |
|
|
Customising keyboards under X
[Non-motif applications]
[Motif applications]
[Other libraries and applications]
[SuSE]
The original was posted to comp.windows.x by Chuck Dillon (dillon@gcg.com).
Although this may seem like a simple issue it is in fact one of the most
complicated/convoluted things about X Windows - "If you're thinking that this is all senselessly complicated... you're right" - Jamie Zawinski, author of xkeycaps.
When you press a key on the
keyboard in a non-Motif program the following applies
- A code for the key is passed from the OS driver to the
X server. Those codes are specific to the operating
system. (i.e. BackSpace might be the value 79)
-
The X server translates those codes (together with the
state of the modifier keys - SHIFT, etc) to what are called
X keysyms (key symbols) which are OS independent. (e.g.
BackSpace becomes XK_BackSpace (=0xff08)). On
a Unix system, typing "xmodmap -pk" will show you the
mapping from the keycode (the identity of the physical key pressed) to the
keysym (the interpretation). A single keycode can generate up to 8 different keysyms. Programs can change this mapping but it will
affect all clients currently running.
- The keysym is converted to a string. This can be changed on a per-client-program basis.
Typing "man xmodmap" and "man xev" offers help on 2 useful programs
- xmodmap can be used to change the way the Xserver maps keyboard
code into X keysyms.
- xev can be of use while investigating what the Xserver is currently
mapping keyboard code to keysyms.
The
potential problem with using xmodmap is that all applications are affected so
remapping at that level could fix a problem
in one place (i.e. Motif apps) and break it in another (i.e. Athena or
OpenWindows apps or in xterm). If your investigation leads you to xmodmap
make sure you also check the capabilities of your Xserver. It may well
provide (under properties) a GUI based dialog for doing keycode mappings.
If you are talking about an xterm (or dtterm but dtterm is a Motif app so
the stuff below applies) you should also type "man stty" and investigate
how the tty is handling keyboard events. Also the "xkeycaps" program (which is free) is useful to check current settings. xkeycaps
creates a virtual keyboard which can be connected to another program's window.
On our teaching system some applications interpret the Backspace
key in unexpected ways. You can try
xmodmap -e "keycode 111=BackSpace"
to change that behaviour and
xmodmap -e "keycode 111=Delete"
to restore it.
In Motif the steps are slightly different
- A code for the key is passed from the OS driver to the
X server.
- The X server translates those codes into X keysyms
- These X keysyms are translated into Motif 'virtual keysyms'. (e.g.
BackSpace becomes osfBackSpace whose value is specific
to the particular process)
- These virtual keysyms are translated into actions to take. (i.e. osfBackSpace
in a textfield means call the delete-previous function)
On our system /usr/lib/X11/XKeysymDB lists some virtual keysyms.
For Motif applications the mapping in stage 3 is set up by default,
but users can override this by having a ~/.motifbind file.
Under Solaris, the default configuration file is at
/usr/dt/lib/bindings/sun_at.
The standard (built in) virtual bindings (mapping from X keysyms to virtual
keysyms) on a solaris machine (using the Sun provided Motif libraries) are
tailored to a Sun keyboard.
Copying sun_at to ~/.motifbind describes, to Motif, a mapping that is tailored
to a typical AT style PC keyboard. You might need to tweak the file depending
on how well that vanilla definition of an AT keyboard matches what you have.
NOTE: a binding file describes a particular keyboard. If you use more
than one desktop display/keyboard with different keyboards you may need two
or more binding files. For example, if you put sun_at in ~/.motifbind and
then sit in front of a Solaris machine with a Sun keyboard you will probably
see problems with Motif apps because the ~/.motifbind still describes a PC
keyboard. To solve this you need a more elaborate setup. Type "man VirtualBindings" for details. In a nutshell,
you can either explicitly assert the appropriate bindings using the "xmbind" program (e.g.
in your .login, .xinitrc, interactively or whatever) or you can set up
a 'binding alias' mechanism that maps the Xserver's 'vendor string' to a
specific binding file.
For a Motif application (Netscape for example) you can try putting
client-specific lines like the following in the X defaults files
Netscape*XmText.translations: #override\n\
<Key>osfDelete: delete-previous-character()\n\
<Key>Delete: delete-previous-character()\n\
<Key>Backspace: delete-previous-character()
Netscape*XmTextField.translations: #override\n\
<Key>osfDelete: delete-previous-character()\n\
<Key>Delete: delete-previous-character()\n\
<Key>Backspace: delete-previous-character()
- Widgets - graphics libraries like Xt and Xaw
can be used to create dialog panels. These panels can be customised so that
their interpretation of keypresses is different from that of the application's
main window. It's possible to customise a particular sub-hierarchy of panels
or a particular widget type. On our system we add the following to
the default X resources
Emacs*Text*translations: #override\n\
<Key>osfDelete: delete-previous-character()\n
so that Backspace deletes the character to the left of the cursor in all
editable text widgets used by Emacs dialog panels.
Xt can also support Multi_key a facility where pressing
one key, then 2 keys simultaneously can produce a single character.
Xt can also support Dead keys, where pressing a sequence of 2 keys produces a single character.
- Emacs - emacs can support Multi_key and Dead keys
even if the graphics library can't. It can intercept keypresses at a low level,
complicating some of the customisations mentioned above. The following are
possible
- (normal-erase-is-backspace-mode 0)
- Emacs supports "Keyboard translations", which are not the same as key
bindings in emacs keymaps. Emacs contains numerous keymaps that apply in
different situations (which are independant of the X keymaps mentioned earlier!), but there is only one set of keyboard
translations, and it applies to every character that Emacs reads from
the terminal. Keyboard translations take place at the lowest level of
input processing. The following can translate `C-h' to <DEL> - (keyboard-translate ?\C-h ?\C-?)
When setting up a thin-client to a SuSE machine (sieve), in June 2004 ceb
found that
she could get Backspace to be backwards-delete in emacs by interactively
using "M-x normal-erase-is-backspace".
However, putting "(normal-erase-is-backspace-mode 1)"
into ".emacs" had no effect.
Backspace could be set to be backwards delete in a shell in xterm on
SuSE linux (but not Redhat Linux where it is also mapped to forwards
delete!), by adding "XTerm*deleteIsDEL: True" to Xresources.