Subject: Bug#674: Acknowledgement (keycode -> keycode translation harmful (makes configuration complex))

From: Robert Siemer <[email-masked]>
Date: Sun, 07 Dec 2014 05:07:14 +0100

> I really think we should get evdev support into NX. What do you think?

No, for keyboard configuration no special evdev support is needed.

 > But for now... so that I get a deeper feeling for this... Could you
 > provide a recipe for setting the correct / transparent keyboard
 > setup in the X2Go Session?

For the commands see below. – At the moment I remove _XKB_RULES_NAMES 
from the root window property before starting/resuming x2go.

 > Wouldn't [running xkbcomp on the client] bypass all this setxkbmap
 > names and files altogether?

I do already run xkbcomp on the client (and local as well) already, but 
it has no influence on keycode translation. – I’m not sure why you 
mentioned it...

I believe I know the reasoning behind this keycode translation: in a 
heterogeneous environment, where you resume an x2go session from 
different workstations, there exists only one way to represent the 
different keyboards as an unchanging virtual keyboard. Yes: with keycode 
translation.

The alternative would be to reconfigure XKB on each session resume, 
which I believe is perfectly reasonable. – This is what I (would) do.

Allow me to draw a little ascii diagram here (look at it with fixed 
width font):

local Xserver    local Xclients    x2go Xserv    x2go Xclients

[1]
|==================xterm
|==================chromium
|==================xlsclients [3]
|==================setxkbmap
|==================xkbcomp [7]
|                                   [2]
|------------------------------------|==============xterm
|------------------------------------|==============gnome-do [6]
|------------------------------------|==============xlsclients [4]
|------------------------------------|==============setxkbmap
|------------------------------------|==============xkbcomp [8]

This is about the X11 protocol level view of an x2go setup. There are 
two Xservers running: the local one [1] and that x2go Xserver (that is 
called nxagent?) [2]. Both are drawn as lines made of |

The x2go Xserver [2] represents its clients to the real local Xserver 
[1] as X11 clients, but draws them in a different way (still X11 
protocol, though).

An xlsclients [4] executed on the x2go server will be run against [2] 
and show only the x2go Xclients. On the local Xserver [1] an execution 
of xlsclients [3] lists all Xclients: the local ones and the remote ones.

Unfortunately the x2go Xserver [2] does not relay all and everything to 
the local Xserver [1]. Examples: the X properties of the root window 
(some kind of “global” storage for X clients) exist twice (in [1] and 
[2]) and can differ. Also global hotkeys (“passive keygrabs”) of the 
x2go Xclients will be stored in [2] and have no influence on [1]. The 
launcher gnome-do [5] registers a hotkey: it will only be delivered to 
[5] if the local Xserver [1] has no local Xclient waiting for it _and_ 
any of the x2go client windows is in focus. Otherwise [2] will not
even see the key event.

Back to XKB. As far as I could observe, the XKB setup consists of an XKB 
configuration (which can be read and written with xkbcomp [7][8]) and 
the root window property _XKB_RULES_NAMES (can be read with xprop and 
setxkbmap and is written as a side effect of setxkbmap). Note that both 
things exist twice, stored in [1] and [2].

Command line examples:

# dump current XKB configuration into one file
$ xkbcomp $DISPLAY full.xkb

# load full single-file XKB configuration
$ xkbcomp full.xkb $DISPLAY

# load from multiple files (xkbcomp will read more than one file):
# main keymap file triggers inclusion of files from system X11 files
$ xkbcomp keymap.xkb $DISPLAY

# example keymap.xkb file
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete+my"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+inet(evdev)+eurosign(e)"	};
	xkb_geometry  { include "pc(pc104)"	};
};

# load from multiple files and have those searched for in your own tree
# otherwise they will be looked for in XKB root /usr/share/X11/xkb
$ xkbcomp -I/home/blabla/xkb mykeymap.xkb $DISPLAY

# read _XKB_RULES_NAMES
$ xprop -root _XKB_RULES_NAMES
_XKB_RULES_NAMES(STRING) = "evdev", "pc104", "us,us", "altgr-intl,", 
"eurosign:e,caps:backspace,compose:rctrl"

# interpreted version of the above
$ setxkbmap -query
rules:      evdev
model:      pc104
layout:     us,us
variant:    altgr-intl,
options:    eurosign:e,caps:backspace,compose:rctrl

# delete _XKB_RULES_NAMES property (and then read it)
$ xprop -root -remove _XKB_RULES_NAMES
$ xprop -root _XKB_RULES_NAMES
_XKB_RULES_NAMES:  not found.
$ setxkbmap -query
Couldn't interpret _XKB_RULES_NAMES property
Use defaults: rules - 'base' model - 'pc105' layout - 'us'
rules:      base
model:      pc105
layout:     us

# set _XKB_RULES_NAMES only(!)
# I wrote a tool for that (xprop can’t set STRING arrays)
# https://github.com/siemer/xproperty
$ ./xproperty.py _XKB_RULES_NAMES evdev pc104 us altgr-intl
<class 'Xlib.protocol.request.QueryExtension'>
_XKB_RULES_NAMES evdev pc104 us altgr-intl

# let setxkbmap read this property, override a part of it
# and ask which keymap it would load
$ setxkbmap -layout de -print
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwertz)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+de+inet(evdev)"	};
	xkb_geometry  { include "pc(pc104)"	};
};

# without “-print” setxkbmap will write the updated property _and_
# instruct the X11 server to load the resulting configuration
# with the help of xkbcomp
# → setxkbmap can’t just update the property alone

On x2go session startup, the x2go Xserver [2] does a superficial 
investigation of what keyboard is used on the local Xserver [1] and sets 
up an incomplete keycode translation to a keyboard known as “xfree86”. 
It further creates an imperfect copy of the XKB configuration from [1] 
to [2]. The _XKB_RULES_NAMES property on [2] is set to rules=xfree86, 
model = pc???, layout = us(?) [I forgot the details].

Why is it a superficial investigation? – It takes the rules name from 
_XKB_RULES_NAMES and deducts the resulting keycodes directly from that 
(I believe). Even though in a common setup rules name “evdev” results in 
one specific set of keycodes and rules name “xfree86” in another 
specific set of keycodes, this is not a must.

Why is the keycode translation incomplete? – As far as I observed it, 
“unusual” or unknown keycodes are not translated and passed as-is.

Why is the XKB configuration copy imperfect? – I did a XKB dump on the 
local Xserver [1] and the x2go Xserver [2] after starting a new session. 
Keys with four levels of symbols turned into two-level-keysyms. – 
_Loading_ (i.e. xkbcomp/setxkbmap) a four-level configuration is no 
problem, though.

Note: the imperfect copy of the XKB configuration is almost always 
useless, because the copied configuration does not match the new 
(translated) keycodes!

Resuming an x2go session triggers the same superficial keyboard 
investigation, the translation kicks in again, but the XKB configuration 
is not touched (i.e. is not copied from [1] to [2]).

Deleting the _XKB_RULES_NAMES property before session startup/resume or 
setting the first part (that is the “rules” part) to some unknown string 
results in untranslated keycodes.

Please pardon me for repeating myself in some instances.

Robert