Symbolic Names
The core protocol does not provide any information to clients other than that
actually used to interpret events. This makes it difficult to write an
application that presents the keyboard to a user in an easy-to-understand way.
Such applications have to examine the vendor string and keycodes to determine
the type of keyboard connected to the server and then examine keysyms and
modifier mappings to determine the effects of most modifiers (the
Shift
,
Lock
and
Control
modifiers are defined by the core protocol but no semantics are implied for
any other modifiers).
To make it easier for applications to present a keyboard to the user, Xkb
supports symbolic names for most components of the keyboard extension. Most of
these symbolic names are grouped into the
names
component of the keyboard description.
The XkbNamesRec Structure
The names component of the keyboard description is defined as follows:
#define XkbKeyNameLength 4
#define XkbKeyNumVirtualMods 16
#define XkbKeyNumIndicators 32
#define XkbKeyNumKbdGroups 4
#define XkbMaxRadioGroups 32
typedef struct {
char name[XkbKeyNameLength]; /* symbolic key names */
} XkbKeyNameRec,*XkbKeyNamePtr;
typedef struct {
char real[XkbKeyNameLength];
/* this key name must be in the keys array */
char alias[XkbKeyNameLength];
/* symbolic key name as alias for the key */
} XkbKeyAliasRec,*XkbKeyAliasPtr;
typedef struct _XkbNamesRec {
Atom keycodes; /* identifies range and meaning of keycodes */
Atom geometry; /* identifies physical location, size, and shape of keys */
Atom symbols; /* identifies the symbols logically bound to the keys */
Atom types; /* identifies the set of key types */
Atom compat; /* identifies actions for keys using core protocol */
Atom vmods[XkbNumVirtualMods]; /* symbolic names for virtual modifiers */
Atom indicators[XkbNumIndicators]; /* symbolic names for indicators */
Atom groups[XkbNumKbdGroups]; /* symbolic names for keyboard groups */
XkbKeyNamePtr keys; /* symbolic key name array */
XkbKeyAliasPtr key_aliases; /* real/alias symbolic name pairs array */
Atom * radio_groups; /* radio group name array */
Atom phys_symbols; /* identifies the symbols engraved on the keyboard */
unsigned char num_keys; /* number of keys in the keys array */
unsigned char num_key_aliases; /* number of keys in the
key_aliases array */
unsigned short num_rg; /* number of radio groups */
} XkbNamesRec,*XkbNamesPtr; /*
The
keycodes
name identifies the range and meaning of the keycodes returned by the keyboard
in question. The
geometry
name, on the other hand, identifies the physical location, size and shape of
the various keys on the keyboard. As an example to distinguish between these
two names, consider function keys on PC-compatible keyboards. Function keys are
sometimes above the main keyboard and sometimes to the left of the main
keyboard, but the same keycode is used for the key that is logically F1
regardless of physical position. Thus, all PC-compatible keyboards share a
similar keycodes name but may have different geometry names.
The keycodes name is intended to be a very general description of
the keycodes returned by a keyboard; a single keycodes name might cover
keyboards with differing numbers of keys provided all keys have the same
semantics when present. For example, 101 and 102 key PC keyboards might use the
same name. In these cases, applications can use the keyboard
geometry
name to determine which subset of the named keycodes is in use.
The
symbols
name identifies the symbols logically bound to the keys. The symbols name is a
human or application-readable description of the intended locale or usage of
the keyboard with these symbols. The
phys_symbols
name, on the other hand, identifies the symbols actually engraved on the
keyboard. Given this, the
symbols
name and
phys_symbols
names might be different. For example, the description for a keyboard that has
English US engravings, but that is using Swiss German symbols might have a
phys_symbols
name of "en_US" and a
symbols
name of "de_CH."
The
types
name provides some information about the set of key types (see section 15.2)
that can be associated with the keyboard. In addition, each key type can have a
name, and each shift level of a type can have a name. Although these names are
stored in the map description with each of the types, they are accessed using
the same methods as the other symbolic names.
The
compat
name provides some information about the rules used to bind actions to keys
that are changed using core protocol requests.
Xkb provides symbolic names for each of the 4 keyboard groups, 16 virtual
modifiers, 32 keyboard indicators, and 4 keyboard groups. These names are held
in the
vmods
,
indicators
, and
groups
fixed-length arrays.
Each key has a four-byte symbolic name. All of the symbolic key names are held
in the
keys
array, and
num_keys
reports the number of entries that are in the keys array. For each key, the
key name links keys with similar functions or in similar positions on keyboards
that report different keycodes. For example, the
F1
key may emit keycode 23 on one keyboard and keycode 86 on another. By naming
this key "FK01" on both keyboards, the keyboard layout designer can reuse parts
of keyboard descriptions for different keyboards.
Key aliases allow the keyboard layout designer to assign multiple key names to
a single key. This allows the keyboard layout designer to refer to keys using
either their position or their "function." For example, a keyboard layout
designer may wish to refer to the left arrow key on a PC keyboard using the
ISO9995-5 positional specification of A31 or using the functional specification
of LEFT. The
key_aliases
field holds a variable-length array of real and alias key name pairs, and the
total number of entries in the
key_aliases
array is held in
num_key_aliases
. For each real and alias key name pair, the
real
field refers to the a name in the keys array, and the
alias
field refers to the alias for that key. Using the previous example, the
keyboard designer may use the name A31 in the keys array, but also define the
name LEFT as an alias for A31 in the
key_aliases
array.
Key aliases defined in the geometry component of a keyboard mapping
(see Chapter 13) override those defined in the keycodes component of the server
database, which are stored in the
XkbNamesRec
(
xkb->names
). Therefore, consider the key aliases defined by the geometry before
considering key aliases supplied by the
XkbNamesRec
.
A radio group is a set of keys whose behavior simulates a set of radio buttons.
Once a key in a radio group is pressed, it stays logically depressed until
another key in the group is pressed, at which point the previously depressed
key is logically released. Consequently, at most one key in a radio group can
be logically depressed at one time.
Each radio group in the keyboard description can have a name. These names are
held in the variable-length array
radio_groups
, and
num_rg
tells how many elements are in the
radio_groups
array.
Symbolic Names Masks
Xkb provides several functions that work with symbolic names. Each of these
functions uses a mask to specify individual fields of the structures described
above. These masks and their relationships to the fields in a keyboard
description are shown in Table 18.1.
Symbolic Names Masks
Mask Bit
Value
Keyboard Component
Field
XkbKeycodesNameMask
(1<<0)
Xkb->names
keycodes
XkbGeometryNameMask
(1<<1)
Xkb->names
geometry
XkbSymbolsNameMask
(1<<2)
Xkb->names
symbols
XkbPhysSymbolsNameMask
(1<<3)
Xkb->names
phys_symbols
XkbTypesNameMask
(1<<4)
Xkb->names
type
XkbCompatNameMask
(1<<5)
Xkb->names
compat
XkbKeyTypeNamesMask
(1<<6)
Xkb->map
type[*].name
XkbKTLevelNamesMask
(1<<7)
Xkb->map
type[*].lvl_names[*]
XkbIndicatorNamesMask
(1<<8)
Xkb->names
indicators[*]
XkbKeyNamesMask
(1<<9)
Xkb->names
keys[*], num_keys
XkbKeyAliasesMask
(1<<10)
Xkb->names
key_aliases[*], num_key_aliases
XkbVirtualModNamesMask
(1<<11)
Xkb->names
vmods[*]
XkbGroupNamesMask
(1<<12)
Xkb->names
groups[*]
XkbRGNamesMask
(1<<13)
Xkb->names
radio_groups[*], num_rg
XkbComponentNamesMask
(0x3f)
Xkb->names
keycodes,
geometry,
symbols,
physical symbols,
types, and
compatibility map
XkbAllNamesMask
(0x3fff)
Xkb->names
all name components
Getting Symbolic Names From the Server
To obtain symbolic names from the server, use
XkbGetNames
.
Status
XkbGetNames
(
dpy, which, Xkb
)
Display *
dpy
; /* connection to the X server */
unsigned int
which
; /* mask of names or map components to be updated */
XkbDescPtr
xkb
/* keyboard description to be updated */
XkbGetNames
retrieves symbolic names for the components of the keyboard extension from the
X server. The
which
parameter specifies the name components to be updated in the
xkb
parameter, and is the bitwise inclusive OR of the valid names mask bits
defined in Table 18.1.
If the
names
field of the keyboard description
xkb
is
NULL
,
XkbGetNames
allocates and initializes the
names
component of the keyboard description before obtaining the values specified by
which
. If the
names
field of
xkb
is not
NULL
,
XkbGetNames
obtains the values specified by
which
and copies them into the keyboard description
Xkb
.
If the
map
component of the
xkb
parameter is
NULL
,
XkbGetNames
does not retrieve type or shift level names, even if
XkbKeyTypeNamesMask
or
XkbKTLevelNamesMask
are set in
which
.
XkbGetNames
can return
Success
, or
BadAlloc
,
BadLength
,
BadMatch
, and
BadImplementation
errors.
To free symbolic names, use
XkbFreeNames
(see section 18.6)
Changing Symbolic Names on the Server
To change the symbolic names in the server, first modify a local copy of the
keyboard description and then use either
XkbSetNames,
or, to save network traffic, use a
XkbNameChangesRec
structure and call
XkbChangeNames
to download the changes to the server.
XkbSetNames
and
XkbChangeNames
can generate
BadAlloc
,
BadAtom
,
BadLength
,
BadMatch,
and
BadImplementation
errors.
Bool
XkbSetNames
(
dpy, which, first_type, num_types, xkb
)
Display *
dpy
; /* connection to the X server */
unsigned int
which
; /* mask of names or map components to be changed */
unsigned int
first_type
; /* first type whose name is to be changed */
unsigned int
num_types
; /* number of types for which names are to be changed */
XkbDescPtr
xkb
; /* keyboard description from which names are to be taken */
Use
XkbSetNames
to change many names at the same time. For each bit set in
which
,
XkbSetNames
takes the corresponding value (or values in the case of arrays) from the
keyboard description
xkb
and sends it to the server.
The
first_type
and
num_types
arguments are used only if
XkbKeyTypeNamesMask
or
XkbKTLevelNamesMask
is set in
which
and specify a subset of the types for which the corresponding names are to be
changed. If either or both of these mask bits are set but the specified types
are illegal,
XkbSetNames
returns
False
and does not update any of the names specified in
which
. The specified types are illegal if
xkb
does not include a map component or if
first_type
and
num_types
specify types that are not defined in the keyboard description.
The XkbNameChangesRec Structure
The
XkbNameChangesRec
allows applications to identify small modifications to the symbolic names and
effectively reduces the amount of traffic sent to the server:
typedef struct _XkbNameChanges {
unsigned int changed; /* name components that have
changed */
unsigned char first_type; /* first key type with a new
name */
unsigned char num_types; /* number of types with new
names */
unsigned char first_lvl; /* first key type with new level
names */
unsigned char num_lvls; /* number of key types with new
level names */
unsigned char num_aliases; /* if key aliases changed,
total number of key aliases */
unsigned char num_rg; /* if radio groups changed, total
number of radio groups */
unsigned char first_key; /* first key with a new name */
unsigned char num_keys; /* number of keys with new names
*/
unsigned short changed_vmods; /* mask of virtual
modifiers for which names have changed */
unsigned long changed_indicators; /* mask of indicators
for which names were changed */
unsigned char changed_groups; /* mask of groups for
which names were changed */
} XkbNameChangesRec, *XkbNameChangesPtr
The
changed
field specifies the name components that have changed and is the bitwise
inclusive OR of the valid names mask bits defined in Table 18.1. The rest of
the fields in the structure specify the ranges that have changed for the
various kinds of symbolic names, as shown in Table 18.2.
XkbNameChanges Fields
Mask
Fields
Component
Field
XkbKeyTypeNamesMask
first_type,
num_types
Xkb->map
type[*].name
XkbKTLevelNamesMask
first_lvl,
num_lvls
Xkb->map
type[*].lvl_names[*]
XkbKeyAliasesMask
num_aliases
Xkb->names
key_aliases[*]
XkbRGNamesMask
num_rg
Xkb->names
radio_groups[*]
XkbKeyNamesMask
first_key,
num_keys
Xkb->names
keys[*]
XkbVirtualModNamesMask
changed_vmods
Xkb->names
vmods[*]
XkbIndicatorNamesMask
changed_indicators
Xkb->names
indicators[*]
XkbGroupNamesMask
changed_groups
Xkb->names
groups[*]
XkbChangeNames
provides a more flexible method for changing symbolic names than
XkbSetNames
and requires the use of an
XkbNameChangesRec
structure.
Bool
XkbChangeNames
(
dpy, xkb, changes
)
Display *
dpy
; /* connection to the X server */
XkbDescPtr
xkb
; /* keyboard description from which names are to be taken */
XkbNameChangesPtr
changes
; /* names map components to be updated on the server */
XkbChangeNames
copies any names specified by
changes
from the keyboard description,
xkb
, to the X server specified by
dpy
.
XkbChangeNames
aborts and returns
False
if any illegal type names or type shift level names are specified by
changes
.
Tracking Name Changes
Whenever a symbolic name changes in the server’s keyboard description, the
server sends a
XkbNamesNotify
event to all interested clients. To receive name notify events, use
XkbSelectEvents
(see section 4.3) with
XkbNamesNotifyMask
in both the
bits_to_change
and
values_for_bits
parameters.
To receive events for only specific names, use
XkbSelectEventDetails
. Set the
event_type
parameter to
XkbNamesNotify
, and set both the
bits_to_change
and
values_for_bits
detail parameter to a mask composed of a bitwise OR of masks in Table 18.1.
The structure for the
XkbNamesNotify
event is defined as follows:
typedef struct {
int type; /* Xkb extension base event code */
unsigned long serial; /* X server serial number for
event */
Bool send_event; /* True
=> synthetically generated */
Display * display; /* server connection where event
generated */
Time time; /* server time when event generated */
int xkb_type; /* XkbNamesNotify */
int device; /* Xkb device ID, will not be
XkbUseCoreKbd */
unsigned int changed; /* mask of name components
that have changed */
int first_type; /* first key type with a new name */
int num_types; /* number of types with new names */
int first_lvl; /* first key type with new level names */
int num_lvls; /* number of key types with new level names */
int num_aliases; /* if key aliases changed, total number
of key aliases */
int num_radio_groups; /* if radio groups changed,
total number of radio groups */
unsigned int changed_vmods; /* mask of virtual modifiers for
which names have changed */
unsigned int changed_groups; /* mask of groups for
which names were changed */
unsigned int changed_indicators; /* mask of indicators for which
names were changed */
int first_key; /* first key with a new name */
int num_keys; /* number of keys with new names */
} XkbNamesNotifyEvent;
The
changed
field specifies the name components that have changed and is the bitwise
inclusive OR of the valid names mask bits defined in Table 18.1. The other
fields in this event are interpreted as the like-named fields in an
XkbNameChangesRec , as previously defined.
When your application receives a X
kbNamesNotify
event, you can note the changed names in a changes structure using
XkbNoteNameChanges
.
void
XkbNoteNameChanges
(
old
,
new
,
wanted
)
XkbNameChangesPtr
old
; /*
XkbNameChanges
structure to be updated */
XkbNamesNotifyEvent *
new
; /* event from which changes are to be copied */
unsigned int
wanted
; /* types of names for which changes are to be noted */
The
wanted
parameter is the bitwise inclusive OR of the valid names mask bits shown in
Table 18.1.
XkbNoteNameChanges
copies any changes that are reported in
new
and specified in
wanted
into the changes record specified by
old
.
To update the local copy of the keyboard description with the actual values,
pass to
XkbGetNameChanges
the results of one or more calls to
XkbNoteNameChanges
.
Status
XkbGetNameChanges
(
dpy
,
xkb
,
changes
)
Display *
dpy
; /* connection to the X server */
XkbDescPtr
xkb
; /* keyboard description to which names are copied */
XkbNameChangesPtr
changes
; /* names components to be obtained from the server */
XkbGetNameChanges
examines the
changes
parameter, retrieves the necessary information from the server, and places the
results into the
xkb
keyboard description.
XkbGetNamesChanges
can generate
BadAlloc
,
BadImplementation,
and
BadMatch
errors.
Allocating and Freeing Symbolic Names
Most applications do not need to directly allocate symbolic names structures.
Do not allocate a names structure directly using
malloc
or
Xmalloc
if your application changes the number of key aliases or radio groups or
constructs a symbolic names structure without loading the necessary components
from the X server. Instead use
XkbAllocNames
.
Status
XkbAllocNames
(
xkb, which, num_rg, num_key_aliases)
XkbDescPtr
xkb;
/* keyboard description for which names are to be allocated */
unsigned int
which;
/* mask of names to be allocated */
int
num_rg;
/* total number of radio group names needed */
int
num_key_aliases;
/* total number of key aliases needed */
XkbAllocNames
can return
BadAlloc
,
BadMatch,
and
BadValue
errors.
The
which
parameter is the bitwise inclusive OR of the valid names mask bits defined in
Table 18.1.
Do not free symbolic names structures directly using
free
or
XFree
. Use
XkbFreeNames
instead.
void
XkbFreeNames
(
xkb, which, free_map)
XkbDescPtr
xkb
; /* keyboard description for which names are to be freed */
unsigned int
which
; /* mask of names components to be freed */
Bool
free_map
; /*
True
=> XkbNamesRec structure itself should be freed */
The
which
parameter is the bitwise inclusive OR of the valid names mask bits defined in
Table 18.1.