Key Event Processing in the Server
This section describes the steps involved in processing a key event within the
server when XKB is present. Key events can be generated due to keyboard
activity and passed to XKB by the DDX layer, or they can be synthesized by
another extension, such as XTEST.
Applying Global Controls
When the X Keyboard Extension receives a key event, it first checks the global
key controls to decide whether to process the event immediately or at all. The
global key controls which might affect the event, in descending order of
priority, are:
If a key is pressed while the
BounceKeys
control is enabled, the extension generates the event only if the key is
active. When a key is released, the server deactivates the key and starts a
bounce keys timer
with an interval specified by the debounce delay.
If the bounce keys timer expires or if some other key is pressed before the
timer expires, the server reactivates the corresponding key and deactivates the
timer. Neither expiration nor deactivation of a bounce keys timer causes an
event.
If the
SlowKeys
control is enabled, the extension sets a
slow keys timer
with an interval specified by the slow keys delay, but does not process the
key event immediately. The corresponding key release deactivates this timer.
If the slow keys timer expires, the server generates a key press for the
corresponding key, sends an
XkbAccessXNotify
and deactivates the timer.
The extension processes key press events normally whether or not the
RepeatKeys
control is active, but if
RepeatKeys
are enabled and per-key autorepeat is enabled for the event key, the extension
processes key press events normally, but it also initiates an
autorepeat timer
with an interval specified by the autorepeat delay. The corresponding key
release deactivates the timer.
If the autorepeat timer expires, the server generates a key release and a key
press for the corresponding key and reschedules the timer according to the
autorepeat interval.
Key events are processed by each global control in turn: if the
BounceKeys
control accepts a key event,
SlowKeys
considers it. Once
SlowKeys
allows or synthesizes an event, the
RepeatKeys
control acts on it.
Key Behavior
Once an event is accepted by all of the controls or generated by a timer, the
server checks the per-key behavior of the corresponding key. This extension
currently defines the following key behaviors:
Behavior
Effect
KB_Default
Press and release events are processed normally.
KB_Lock
If a key is logically up (i.e. the corresponding bit of the core key
map is cleared) when it is pressed, the key press is processed normally and the
corresponding release is ignored. If the key is logically down when pressed,
the key press is ignored but the corresponding release is processed normally.
KB_RadioGroup
flags: CARD8
index: CARD8
If another member of the radio group specified by
index
is logically down when a key is pressed, the server synthesizes a key release
for the member that is logically down and then processes the new key press
event normally.
If the key itself is logically down when pressed, the key press event is
ignored, but the processing of the corresponding key release depends on the
value of the
RGAllowNone
bit in
flags
. If it is set, the key release is processed normally; otherwise the key
release is also ignored.
All other key release events are ignored.
KB_Overlay1
key: KEYCODE
If the
Overlay1
control is enabled, events from this key are reported as if they came from the
key specified in
key
. Otherwise, press and release events are processed normally.
KB_Overlay2
key: KEYCODE
If the
Overlay2
control is enabled, events from this key are reported as if they came from the
key specified in
key
. Otherwise, press and release events are processed normally.
The X server uses key behavior to determine whether to process or filter out
any given key event; key behavior is independent of keyboard modifier or group
state (each key has exactly one behavior.
Key behaviors can be used to simulate any of these types of keys or to indicate
an unmodifiable physical, electrical or software driver characteristic of a
key. An optional
permanent
flag can modify any of the supported behaviors and indicates that behavior
describes an unalterable physical, electrical or software aspect of the
keyboard. Permanent behaviors cannot be changed or set by the
XkbSetMap
request. The
permanent
flag indicates a characteristic of the underlying system that XKB cannot
affect, so XKB treats all permanent behaviors as if they were
KB_Default
and does not filter key events described in the table above.
Key Actions
Once the server has applied the global controls and per-key behavior and has
decided to process a key event, it applies
key actions
to determine the effects of the key on the internal state of the server. A key
action consists of an operator and some optional data. XKB supports actions
which:
change base, latched or locked modifiers or group
move the core pointer or simulate core pointer button events
change most aspects of keyboard behavior
terminate or suspend the server
send a message to interested clients
simulate events on other keys
Each key has an optional list of actions. If present, this list parallels the
list of symbols associated with the key (i.e. it has one action per symbol
associated with the key). For key press events, the server looks up the action
to be applied from this list using the key symbol mapping associated with the
event key, just as a client looks up symbols as described in See Determining the KeySym Associated with a
Key Event; if the event key does not have any actions, the server uses
the
SA_NoAction
event for that key regardless of modifier or group state.
Key actions have essentially two halves; the effects on the server when the key
is pressed and the effects when the key is released. The action applied for a
key press event determines the further actions, if any, that are applied to the
corresponding release event or to events that occur while the key is held down.
Clients can change the actions associated with a key while the key is down
without changing the action applied next time the key is released; subsequent
press-release pairs will use the newly bound key action.
Most actions directly change the state of the keyboard or server; some actions
also modify other actions that occur simultaneously with them. Two actions
occur simultaneously if the keys which invoke the actions are both logically
down at the same time, regardless of the order in which they are pressed or
delay between the activation of one and the other.
Most actions which affect keyboard modifier state accept a modifier definition
(see See Virtual Modifiers)
named
mods
and a boolean flag name
useModMap
among their arguments. These two fields combine to specify the modifiers
affected by the action as follows: If
useModMap
is
True
, the action sets any modifiers bound by the modifier mapping to the key that
initiated the action; otherwise, the action sets the modifiers specified by
mods
. For brevity in the text of the following definitions, we refer to this
combination of
useModMap
and
mods
as the "action modifiers."
The X Keyboard Extension supports the following actions:
Action
Effect
SA_NoAction
No direct effect, though SA_NoAction
events may change the effect of other server actions (see below).
SA_SetMods
mods: MOD_DEF
useModMap: BOOL
clearLocks: BOOL
Key press adds any action modifiers to the keyboard’s base modifiers.
Key release clears any action modifiers in the keyboard’s base
modifiers, provided that no other key which affects the same modifiers is
logically down.
If no keys were operated simultaneously with this key and
clearLocks
is set, release unlocks any action modifiers.
SA_LatchMods
mods: MOD_DEF
useModMap: BOOL
clearLocks: BOOL
latchToLock: BOOL
Key press and release events have the same effect as for
SA_SetMods
; if no keys were operated simultaneously with the latching modifier key, key
release events have the following additional effects:
Modifiers that were unlocked due to
clearLocks
have no further effect.
If
latchToLock
is set, key release locks and then unlatches any remaining action modifiers
that are already latched.
Finally, key release latches any action modifiers that were not used by
the
clearLocks
or
latchToLock
flags.
SA_LockMods
mods: MOD_DEF
useModMap: BOOL
noLock: BOOL
noUnlock: BOOL
Key press sets the base and possibly the locked state of any action
modifiers. If
noLock
is
True
, only the base state is changed.
For key release events, clears any action modifiers in the keyboard’s
base modifiers, provided that no other key which affects the same modifiers is
down. If
noUnlock
is
False
and any of the action modifiers were locked before the corresponding key press
occurred, key release unlocks them.
SA_SetGroup
group: INT8
groupAbsolute: BOOL
clearLocks: BOOL
If
groupAbsolute
is set, key press events change the base keyboard group to
group
; otherwise, they add
group
to the base keyboard group. In either case, the resulting effective keyboard
group is brought back into range depending on the value of the
GroupsWrap
control for the keyboard.
If an
SA_ISOLock
key is pressed while this key is held down, key release has no effect,
otherwise it cancels the effects of the press.
If no keys were operated simultaneously with this key and
clearLocks
is set, key release also sets the locked keyboard group to
Group1
.
SA_LatchGroup
group: INT8
groupAbsolute: BOOL
clearLocks: BOOL
latchToLock: BOOL
Key press and release events have the same effect as an
SA_SetGroup
action; if no keys were operated simultaneously with the latching group key
and the
clearLocks
flag was not set or had no effect, key release has the following additional
effects:
If
latchToLock
is set and the latched keyboard group is non-zero, the key release adds the
delta applied by the corresponding key press to the locked keyboard group and
subtracts it from the latched keyboard group. The locked and effective keyboard
group are brought back into range according to the value of the global
GroupsWrap
control for the keyboard.
Otherwise, key release adds the key press delta to the latched keyboard
group.
SA_LockGroup
group: INT8
groupAbsolute: BOOL
If
groupAbsolute
is set, key press sets the locked keyboard group to
group
. Otherwise, key press adds
group
to the locked keyboard group. In either case, the resulting locked and
effective group is brought back into range depending on the value of the
GroupsWrap
control for the keyboard.
Key release has no effect.
SA_MovePtr
x, y: INT16
noAccel: BOOL
absoluteX: BOOL
absoluteY: BOOL
If
MouseKeys
are not enabled, this action behaves like
SA_NoAction
, otherwise this action cancels any pending repeat key timers for this key and
has the following additional effects.
Key press generates a core pointer
MotionNotify
event instead of the usual
KeyPress
. If
absoluteX
is
True
,
x
specifies the new pointer X coordinate, otherwise
x
is added to the current pointer X coordinate;
absoluteY
and
y
specify the new Y coordinate in the same way.
If
noAccel
is
False
, and the
MouseKeysAccel
keyboard control is enabled, key press also initiates the mouse keys timer for
this key; every time this timer expires, the cursor moves again. The distance
the cursor moves in these subsequent events is determined by the mouse keys
acceleration as described in See The
MouseKeysAccel Control.
Key release disables the mouse keys timer (if it was initiated by the
corresponding key press) but has no other effect and is ignored (does not
generate an event of any type).
SA_PtrBtn
button: CARD8
count: CARD8
useDfltBtn: BOOL
If
MouseKeys
are not enabled, this action behaves like
SA_NoAction
.
If
useDfltBtn
is set, the event is generated for the current default core button. Otherwise,
the event is generated for the button specified by
button
.
If the mouse button specified for this action is logically down, the
key press and corresponding release are ignored and have no effect.
Otherwise, key press causes one or more core pointer button events
instead of the usual key press. If
count
is
0
, key press generates a single
ButtonPress
event; if
count
is greater than
0
, key press generates
count
pairs of
ButtonPress
and
ButtonRelease
events.
If
count
is
0
, key release generates a core pointer
ButtonRelease
which matches the event generated by the corresponding key press; if count is
non-zero, key release does not cause a
ButtonRelease
event. Key release never causes a key release event.
SA_LockPtrBtn
button: BUTTON
noLock: BOOL
noUnlock: BOOL
useDfltBtn: BOOL
If
MouseKeys
are not enabled, this action behaves like
SA_NoAction
.
Otherwise, if the button specified by
useDfltBtn
and
button
is not locked, key press causes a
ButtonPress
instead of a key press and locks the button. If the button is already locked
or if
noLock
is
True
, key press is ignored and has no effect.
If the corresponding key press was ignored, and if
noUnlock
is
False
, key release generates a
ButtonRelease
event instead of a key release event and unlocks the specified button. If the
corresponding key press locked a button, key release is ignored and has no
effect.
SA_SetPtrDflt
affect: CARD8
value: CARD8
dfltBtnAbs: BOOL
If
MouseKeys
are not enabled, this action behaves like
SA_NoAction
.
Otherwise, both key press and key release are ignored, but key press
changes the pointer value specified by
affect
to
value
, as follows:
If
which
is
SA_AffectDfltBtn
,
value
and
dfltBtnAbs
specify the default pointer button used by the various pointer actions as
follow: If
dfltBtnAbs
is True, value specifies the button to be used, otherwise,
value
specifies the amount to be added to the current default button. In either
case, illegal button choices are wrapped back into range.
SA_ISOLock
dfltIsGroup:
False
mods: MOD_DEF
useModMap: BOOL
noLock: BOOL
noUnlock: BOOL
noAffectMods: BOOL
noAffectGrp: BOOL
noAffectPtr: BOOL
noAffectCtrls: BOOL
or
dfltIsGroup:
True
group: INT8
groupAbsolute: BOOL
noAffectMods: BOOL
noAffectGrp: BOOL
noAffectPtr: BOOL
noAffectCtrls: BOOL
If
dfltIsGroup
is
True
, key press sets the base group specified by
groupAbsolute
and
group
. Otherwise, key press sets the action modifiers in the keyboard’s base
modifiers.
Key release clears the base modifiers or group that were set by the key
press; it may have additional effects if no other appropriate actions occur
simultaneously with the
SA_ISOLock
operation.
If
noAffectMods
is
False
, any
SA_SetMods
or
SA_LatchMods
actions that occur simultaneously with the
ISOLock
action are treated as
SA_LockMods
instead.
If
noAffectGrp
is
False
, any
SA_SetGroup
or
SA_LatchGroup
actions that occur simultaneously with this action are treated as
SA_LockGroup
actions instead.
If
noAffectPtr
is
False
,
SA_PtrBtn
actions that occur simultaneously with the
SA_ISOLock
action are treated as
SA_LockPtrBtn
actions instead.
If
noAffectCtrls
is
False
, any
SA_SetControls
actions that occur simultaneously with the
SA_ISOLock
action are treated as
SA_LockControls
actions instead.
If no other actions were transformed by the
SA_ISOLock
action, key release locks the group or modifiers specified by the action
arguments.
SA_TerminateServer
Key press terminates the server. Key release is ignored.
This action is optional; servers are free to ignore it. If ignored, it
behaves like
SA_NoAction
.
SA_SwitchScreen
num: INT8
switchApp: BOOL
screenAbs: BOOL
If the server supports this action and multiple screens or displays
(either virtual or real), this action changes to the active screen indicated by
num
and
screenAbs
. If
screenAbs
is
True
, num specifies the index of the new screen; otherwise, num specifies an offset
from the current screen to the new screen.
If
switchApp
is
False
, it should switch to another screen on the same server. Otherwise it should
switch to another X server or application which shares the same physical
display.
This action is optional; servers are free to ignore the action or any
of its flags if they do not support the requested behavior. If the action is
ignored, it behaves like
SA_NoAction
, otherwise neither key press nor release generate an event.
SA_SetControls
controls: KB_BOOLCTRLMASK
Key press enables any boolean controls that are specified in
controls
and not already enabled at the time of the key press. Key release disables any
controls that were enabled by the corresponding key press. This action can
cause
XkbControlsNotify
events.
SA_LockControls
controls: KB_BOOLCTRLMASK
noLock: BOOL
noUnlock: BOOL
If
noLock
is
False
, key press locks and enables any controls that are specified in
controls
and not already locked at the time of the key press.
If
noUnlock
is
False
, key release unlocks and disables any controls that are specified in
controls
and were not enabled at the time of the corresponding key press.
SA_ActionMessage
:
pressMsg: BOOL
releaseMsg: BOOL
genEvent: BOOL
message: STRING
if
pressMsg
is
True
, key press generates an
XkbActionMessage
event which reports the keycode, event type and the contents of
message
.
If
releaseMsg
is
True
, key release generates an
XkbActionMessage
event which reports the keycode, event type and contents of
message
.
If
genEvent
is
True
, both press and release generate key press and key release events, regardless
of whether they also cause an
XkbActionMessage
.
SA_RedirectKey
newKey: KEYCODE
modsMask: KEYMASK
mods: KEYMASK
vmodsMask: CARD16
vmods: CARD16
Key press causes a key press event for the key specified by
newKey
instead of for the actual key. The state reported in this event reports of the
current effective modifiers changed as follow: Any real modifiers specified in
modsMask
are set to corresponding values from
mods
. Any real modifiers bound to the virtual modifiers specified in
vmodsMask
are either set or cleared, depending on the corresponding value in
vmods
. If the real and virtual modifier definitions specify conflicting values for a
single modifier, the real modifier definition has priority.
Key release causes a key release event for the key specified by
newKey
; the state field for this event consists of the effective keyboard modifiers
at the time of the release, changed as described above.
The
SA_RedirectKey
action normally redirects to another key on the same device as the key or
button which caused the event, unless that device does not belong to the input
extension KEYCLASS, in which case this action causes an event on the core
keyboard device.
SA_DeviceBtn
count: CARD8
button: BUTTON
device: CARD8
The
device
field specifies the ID of an extension device; the
button
field specifies the index of a button on that device. If the button specified
by this action is logically down, the key press and corresponding release are
ignored and have no effect. If the device or button specified by this action
are illegal, this action behaves like
SA_NoAction
.
Otherwise, key press causes one or more input extension device button
events instead of the usual key press event. If
count
is
0
, key press generates a single
DeviceButtonPress
event; if
count
is greater than
0
, key press generates
count
pairs of
DeviceButtonPress
and
DeviceButtonRelease
events.
If
count
is
0
, key release generates an input extension
DeviceButtonRelease
which matches the event generated by the corresponding key press; if count is
non-zero, key release does not cause a
DeviceButtonRelease
event. Key release never causes a key release event.
SA_LockDeviceBtn
button: BUTTON
device: CARD8
noLock: BOOL
noUnlock: BOOL
The
device
field specifies the ID of an extension device; the
button
field specifies the index of a button on that device. If the device or button
specified by this action are illegal, it behaves like
SA_NoAction
.
Otherwise, if the specified button is not locked and if
noLock
is
False
, key press causes an input extension
DeviceButtonPress
event instead of a key press event and locks the button. If the button is
already locked or if
noLock
is
True
, key press is ignored and has no effect.
If the corresponding key press was ignored, and if
noUnlock
is
False
, key release generates an input extension
DeviceButtonRelease
event instead of a core protocol or input extension key release event and
unlocks the specified button. If the corresponding key press locked a button,
key release is ignored and has no effect.
SA_DeviceValuator
device
: CARD8
val1What
: SA_DVOP
val1
: CARD8
val1Value
: INT8
val1Scale
: 0...7
val2What
: BOOL
val2
: CARD8
val2Value
: INT8
val2Scale
: 0...7
The
device
field specifies the ID of an extension device;
val1
and
val2
specify valuators on that device. If
device
is illegal or if neither
val1
nor
val2
specifies a legal valuator, this action behaves like
SA_NoAction
.
If
valn
specifies a legal valuator and
valnWhat
is not
SA_IgnoreVal
, the specified value is adjusted as specified by
valnWhat
:
If
valnWhat
is
SA_SetValMin
,
valn
is set to its minimum legal value.
If
valnWhat
is
SA_SetValCenter
,
valn
is centered (to (max-min)/2).
If
valnWhat
is
SA_SetValMax
,
valn
is set to its maximum legal value.
if
valnWhat
is
SA_SetValRelative
,
is added to
valn
.
if
valnWhat
is
SA_SetValAbsolute
,
valn
is set to
.
Illegal values for
SA_SetValRelative
or
SA_SetValAbsolute
are clamped into range.
If
StickyKeys
are enabled, all
SA_SetMods
and
SA_SetGroup
actions act like
SA_LatchMods
and
SA_LatchGroup
respectively. If the
LatchToLock
AccessX option is set, either action behaves as if both the
SA_ClearLocks
and
SA_LatchToLock
flags are set.
Actions which cause an event from another key or from a button on another
device immediately generate the specified event. These actions do not consider
the behavior or actions (if any) that are bound to the key or button to which
the event is redirected.
Core events generated by server actions contain the keyboard state that was in
effect at the time the key event occurred; the reported state does not reflect
any changes in state that occur as a result of the actions bound to the key
event that caused them.
Events sent to clients that have not issued an
XkbUseExtension
request contain a compatibility state in place of the actual XKB keyboard
state. See See Effects of XKB on Core
Protocol Events for a description of this compatibility mapping.
Delivering a Key or Button Event to a Client
The window and client that receive core protocol and input extension key or
button events are determined using the focus policy, window hierarchy and
passive grabs as specified by the core protocol and the input extension, with
the following changes:
A passive grab triggers if the modifier state specified in the grab
matches the grab compatibility state (described in See Compatibility Components of Keyboard
State). Clients can choose to use the XKB grab state instead by setting
the
GrabsUseXKBState
per-client flag. This flag affects all passive grabs that are requested by the
client which sets it but does not affect passive grabs that are set by any
other client.
The state field of events which trigger a passive grab reports the XKB
or compatibility grab state in effect at the time the grab is triggered; the
state field of the corresponding release event reports the corresponding grab
state in effect when the key or button is released.
If the
LookupStateWhenGrabbed
per-client flag is set, all key or button events that occur while a keyboard
or pointer grab is active contain the XKB or compatibility lookup state,
depending on the value of the
GrabsUseXKBState
per-client flag. If
LookupStateWhenGrabbed
is not set, they include the XKB or compatibility grab state, instead.
Otherwise, the state field of events that do not trigger a passive grab
report is derived from the XKB effective modifiers and group, as described in
See Computing A State Field from an
XKB State.
If a key release event is the result of an autorepeating key that is
being held down, and the client to which the event is reported has requested
detectable autorepeat (see See
Detectable Autorepeat), the event is not delivered to the client.
The following section explains the intent of the XKB interactions with core
protocol grabs and the reason that the per-client flags are needed.
XKB Interactions With Core Protocol Grabs
XKB provides the separate lookup and grab states to help work around some
difficulties with the way the core protocol specifies passive grabs.
Unfortunately, many clients work around those problems differently, and the way
that XKB handles grabs and reports keyboard state can sometimes interact with
those client workarounds in unexpected and unpleasant ways.
To provide more reasonable behavior for clients that are aware of XKB without
causing problems for clients that are unaware of XKB, this extension provides
two per-client flags that specify the way that XKB and the core protocol should
interact.
The largest problems arise from the fact that an XKB state field
encodes an explicit keyboard group in bits 13-14 (as described in See Computing A State Field from an XKB
State), while pre-XKB clients use one of the eight keyboard modifiers
to select an alternate keyboard group. To make existing clients behave
reasonably, XKB normally uses the compatibility grab state instead of the XKB
grab state to determine whether or not a passive grab is triggered. XKB-aware
clients can set the
GrabsUseXKBState
per-client flag to indicate that they are specifying passive grabs using an
XKB state.
Some toolkits start an active grab when a passive grab is triggered, in
order to have more control over the conditions under which the grab is
terminated. Unfortunately, the fact that XKB reports a different state in
events that trigger or terminate grabs means that this grab simulation can fail
to terminate the grab under some conditions. To work around this problem, XKB
normally reports the grab state in all events whenever a grab is active.
Clients which do not use active grabs like this can set the
LookupStateWhenGrabbed
per-client flag in order to receive the same state component whether or not a
grab is active.
The
GrabsUseXKBState
per-client flag also applies to the state of events sent while a grab is
active. If it is set, events during a grab contain the XKB lookup or grab
state; by default, events during a grab contain the compatibility lookup or
grab state.
The state used to trigger a passive grab is controlled by the setting of the
GrabsUseXKBState
per-client flag at the time the grab is registered. Changing this flag does
not affect existing passive grabs.