<chapter id='Key_Event_Processing_in_the_Server'>
<title>Key Event Processing in the Server</title>

<para>
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.
</para>

<sect1 id='Applying_Global_Controls'>
<title>Applying Global Controls</title>

<para>
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:
</para>

<itemizedlist>
<listitem>
  <para>If a key is pressed while the <emphasis>
BounceKeys</emphasis>
 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
<emphasis>
bounce keys timer</emphasis>
 with an interval specified by the debounce delay.
  </para>
  <para>
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.</para>
</listitem>
<listitem>
  <para>If the <emphasis>
SlowKeys</emphasis>
 control is enabled, the extension sets a <emphasis>
slow keys timer</emphasis>
 with an interval specified by the slow keys delay, but does not process the
key event immediately. The corresponding key release deactivates this timer.
  </para>
  <para>
If the slow keys timer expires, the server generates a key press for the
corresponding key, sends an <emphasis>
XkbAccessXNotify</emphasis>
 and deactivates the timer.
   </para>
</listitem>
<listitem>
  <para>The extension processes key press events normally whether or not the
<emphasis>
RepeatKeys</emphasis>
 control is active, but if <emphasis>
RepeatKeys</emphasis>
 are enabled and per-key autorepeat is enabled for the event key, the extension
processes key press events normally, but it also initiates an <emphasis>
autorepeat timer</emphasis>
 with an interval specified by the autorepeat delay. The corresponding key
release deactivates the timer.
  </para>
  <para>
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.
  </para>
</listitem>
</itemizedlist>

<para>
Key events are processed by each global control in turn: if the <emphasis>
BounceKeys</emphasis>
 control accepts a key event, <emphasis>
SlowKeys</emphasis>
 considers it. Once <emphasis>
SlowKeys</emphasis>
 allows or synthesizes an event, the <emphasis>
RepeatKeys</emphasis>
 control acts on it.
</para>


</sect1>
<sect1 id='Key_Behavior'>
<title>Key Behavior</title>

<para>
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:
</para>

<informaltable frame='topbot'>
<?dbfo keep-together="always" ?>
<tgroup cols='2' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<colspec colname='c2' colwidth='3.0*'/>
<thead>
  <row rowsep='1'>
    <entry>Behavior</entry>
    <entry>Effect</entry>
  </row>
</thead>
<tbody>
  <row>
    <entry><emphasis>
KB_Default</emphasis>
 </entry>
    <entry>Press and release events are processed normally.</entry>
  </row>
  <row>
    <entry><emphasis>
KB_Lock</emphasis>
 </entry>
    <entry>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.
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
KB_RadioGroup
</emphasis>
    </para>
    <para>
      flags: CARD8
    </para>
    <para>
      index: CARD8
    </para>
    </entry>
    <entry><para>If another member of the radio group specified by <emphasis>
index</emphasis>
 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. </para>
<para>
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 <emphasis>
RGAllowNone</emphasis>
 bit in <emphasis>
flags</emphasis>
. If it is set, the key release is processed normally; otherwise the key
release is also ignored.
</para>
<para>
All other key release events are ignored.</para>
  </entry>
  </row>
  <row>
    <entry>
   <para>
    <emphasis>
KB_Overlay1
</emphasis>
   </para>
   <para>
      key: KEYCODE
   </para>
      </entry>
    <entry>If the <emphasis>
Overlay1</emphasis>
 control is enabled, events from this key are reported as if they came from the
key specified in <emphasis>
key</emphasis>
. Otherwise, press and release events are processed normally.</entry>
  </row>
  <row>
    <entry>
   <para>
    <emphasis>
KB_Overlay2
</emphasis>
   </para>
   <para>
      key: KEYCODE
   </para>
      </entry>
    <entry>If the <emphasis>
Overlay2</emphasis>
 control is enabled, events from this key are reported as if they came from the
key specified in <emphasis>
key</emphasis>
. Otherwise, press and release events are processed normally.</entry>
  </row>
</tbody>
</tgroup>
</informaltable>

<para>
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.
</para>

<para>
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 <emphasis>
permanent</emphasis>
 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 <emphasis>
XkbSetMap</emphasis>
 request. The <emphasis>
permanent</emphasis>
 flag indicates a characteristic of the underlying system that XKB cannot
affect, so XKB treats all permanent behaviors as if they were <emphasis>
KB_Default</emphasis>
 and does not filter key events described in the table above.
</para>


</sect1>
<sect1 id='Key_Actions'>
<title>Key Actions</title>

<para>
Once the server has applied the global controls and per-key behavior and has
decided to process a key event, it applies <emphasis>
key actions</emphasis>
 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:
</para>

<itemizedlist>
<listitem>
  <para>change base, latched or locked modifiers or group
  </para>
</listitem>
<listitem>
  <para>move the core pointer or simulate core pointer button events
  </para>
</listitem>
<listitem>
  <para>change most aspects of keyboard behavior
  </para>
</listitem>
<listitem>
  <para>terminate or suspend the server
  </para>
</listitem>
<listitem>
  <para>send a message to interested clients
  </para>
</listitem>
<listitem>
  <para>simulate events on other keys
  </para>
</listitem>
</itemizedlist>

<para>
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 <link
linkend='Determining_the_KeySym_Associated_with_a_Key_Event'>Determining the KeySym Associated with a
Key Event</link>; if the event key does not have any actions, the server uses
the <emphasis>
SA_NoAction</emphasis>
 event for that key regardless of modifier or group state.
</para>


<para>
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.
</para>


<para>
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.
</para>


<para>
Most actions which affect keyboard modifier state accept a modifier definition
(see <link linkend='Virtual_Modifiers'>Virtual Modifiers</link>)
named <emphasis>
mods</emphasis>
 and a boolean flag name <emphasis>
useModMap</emphasis>
 among their arguments. These two fields combine to specify the modifiers
affected by the action as follows: If <emphasis>
useModMap</emphasis>
 is <emphasis>
True</emphasis>
, 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
<emphasis>
mods</emphasis>
. For brevity in the text of the following definitions, we refer to this
combination of <emphasis>
useModMap</emphasis>
 and <emphasis>
mods</emphasis>
 as the "action modifiers."
</para>


<para>
The X Keyboard Extension supports the following actions:
</para>

<informaltable frame='topbot'>
<?dbfo keep-together="auto" ?>
<tgroup cols='2' align='left' colsep='0' rowsep='0'>
<colspec colname='c1' colwidth='1.0*'/>
<colspec colname='c2' colwidth='3.0*'/>
<thead>
  <row rowsep='1'>
    <entry>Action</entry>
    <entry>Effect</entry>
  </row>
</thead>
<tbody>
  <row>
    <entry><emphasis>SA_NoAction</emphasis></entry>
    <entry>
      <itemizedlist>
        <listitem>
          <para>
No direct effect, though <emphasis>SA_NoAction</emphasis>
 events may change the effect of other server actions (see below).
          </para>
        </listitem>
      </itemizedlist>
    </entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>SA_SetMods</emphasis>
    </para>
    <para>
      mods: MOD_DEF
    </para>
    <para>
      useModMap: BOOL
    </para>
    <para>
      clearLocks: BOOL
    </para>
    </entry>
    <entry>
      <itemizedlist>
      <listitem>
        <para>
Key press adds any action modifiers to the keyboard’s base modifiers<emphasis>.</emphasis>
        </para>
      </listitem>
      <listitem>
        <para>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.
        </para>
      </listitem>
      <listitem>
        <para>If no keys were operated simultaneously with this key and <emphasis>
clearLocks</emphasis>
 is set, release unlocks any action modifiers.
        </para>
      </listitem>
      </itemizedlist>
    </entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_LatchMods
</emphasis>
    </para>
    <para>
      mods: MOD_DEF
    </para>
    <para>
      useModMap: BOOL
    </para>
    <para>
      clearLocks: BOOL
    </para>
    <para>
      latchToLock: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>Key press and release events have the same effect as for <emphasis>
SA_SetMods</emphasis>
; if no keys were operated simultaneously with the latching modifier key, key
release events have the following additional effects:
  </para>
</listitem>
<listitem>
  <para>Modifiers that were unlocked due to <emphasis>
clearLocks</emphasis>
 have no further effect.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
latchToLock</emphasis>
 is set, key release locks and then unlatches any remaining action modifiers
that are already latched.
  </para>
</listitem>
<listitem>
  <para>Finally, key release latches any action modifiers that were not used by
the <emphasis>
clearLocks</emphasis>
 or <emphasis>
latchToLock</emphasis>
 flags.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_LockMods
    </emphasis>
    </para>
    <para>
      mods: MOD_DEF
    </para>
    <para>
      useModMap: BOOL
    </para>
    <para>
      noLock: BOOL
    </para>
    <para>
      noUnlock: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>Key press sets the base and possibly the locked state of any action
modifiers. If <emphasis>
noLock</emphasis>
 is <emphasis>
True</emphasis>
, only the base state is changed.
  </para>
</listitem>
<listitem>
  <para>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 <emphasis>
noUnlock</emphasis>
 is <emphasis>
False</emphasis>
 and any of the action modifiers were locked before the corresponding key press
occurred, key release unlocks them.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_SetGroup
</emphasis>
    </para>
    <para>
      group: INT8
    </para>
    <para>
      groupAbsolute: BOOL
    </para>
    <para>
      clearLocks: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
groupAbsolute</emphasis>
 is set, key press events change the base keyboard group to <emphasis>
group</emphasis>
; otherwise, they add <emphasis>
group</emphasis>
 to the base keyboard group. In either case, the resulting effective keyboard
group is brought back into range depending on the value of the <emphasis>
GroupsWrap</emphasis>
 control for the keyboard.
  </para>
</listitem>
<listitem>
  <para>If an <emphasis>
SA_ISOLock</emphasis>
 key is pressed while this key is held down, key release has no effect,
otherwise it cancels the effects of the press.
  </para>
</listitem>
<listitem>
  <para>If no keys were operated simultaneously with this key and <emphasis>
clearLocks</emphasis>
 is set, key release also sets the locked keyboard group to <emphasis>
Group1</emphasis>
.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_LatchGroup
    </emphasis>
    </para>
    <para>
      group: INT8
    </para>
    <para>
      groupAbsolute: BOOL
    </para>
    <para>
      clearLocks: BOOL
    </para>
    <para>
      latchToLock: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>Key press and release events have the same effect as an <emphasis>
SA_SetGroup</emphasis>
 action; if no keys were operated simultaneously with the latching group key
and the <emphasis>
clearLocks</emphasis>
 flag was not set or had no effect, key release has the following additional
effects:
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
latchToLock</emphasis>
 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
<emphasis>
GroupsWrap</emphasis>
 control for the keyboard.
  </para>
</listitem>
<listitem>
  <para>Otherwise, key release adds the key press delta to the latched keyboard
group.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_LockGroup
    </emphasis>
    </para>
    <para>
      group: INT8
    </para>
    <para>
      groupAbsolute: BOOL
    </para>
    </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
groupAbsolute</emphasis>
 is set, key press sets the locked keyboard group to <emphasis>
group</emphasis>
. Otherwise, key press adds <emphasis>
group</emphasis>
 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
<emphasis>
GroupsWrap</emphasis>
 control for the keyboard.
  </para>
</listitem>
<listitem>
  <para>Key release has no effect.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_MovePtr
</emphasis>
    </para>
    <para>
      x, y: INT16
    </para>
    <para>
      noAccel: BOOL
    </para>
    <para>
      absoluteX: BOOL
    </para>
    <para>
      absoluteY: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
MouseKeys</emphasis>
 are not enabled, this action behaves like <emphasis>
SA_NoAction</emphasis>
, otherwise this action cancels any pending repeat key timers for this key and
has the following additional effects.
  </para>
</listitem>
<listitem>
  <para>Key press generates a core pointer <emphasis>
MotionNotify</emphasis>
 event instead of the usual <emphasis>
KeyPress</emphasis>
. If <emphasis>
absoluteX</emphasis>
 is <emphasis>
True</emphasis>
, <emphasis>
x</emphasis>
 specifies the new pointer X coordinate, otherwise <emphasis>
x</emphasis>
 is added to the current pointer X coordinate; <emphasis>
absoluteY</emphasis>
 and <emphasis>
y</emphasis>
 specify the new Y coordinate in the same way.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
noAccel</emphasis>
 is <emphasis>
False</emphasis>
, and the <emphasis>
MouseKeysAccel</emphasis>
 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 <link linkend='The_MouseKeysAccel_Control'>The
MouseKeysAccel Control</link>.
  </para>
</listitem>
<listitem>
  <para>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).
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_PtrBtn
   </emphasis>
    </para>
    <para>
      button: CARD8
    </para>
    <para>
      count: CARD8
    </para>
    <para>
      useDfltBtn: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
MouseKeys</emphasis>
 are not enabled, this action behaves like <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
useDfltBtn</emphasis>
 is set, the event is generated for the current default core button. Otherwise,
the event is generated for the button specified by <emphasis>
button</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>If the mouse button specified for this action is logically down, the
key press and corresponding release are ignored and have no effect.
  </para>
</listitem>
<listitem>
  <para>Otherwise, key press causes one or more core pointer button events
instead of the usual key press. If <emphasis>
count</emphasis>
 is <emphasis>
0</emphasis>
, key press generates a single <emphasis>
ButtonPress</emphasis>
 event; if <emphasis>
count</emphasis>
 is greater than <emphasis>
0</emphasis>
, key press generates <emphasis>
count</emphasis>
 pairs of <emphasis>
ButtonPress</emphasis>
 and <emphasis>
ButtonRelease</emphasis>
 events.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
count</emphasis>
 is <emphasis>
0</emphasis>
, key release generates a core pointer <emphasis>
ButtonRelease</emphasis>
 which matches the event generated by the corresponding key press; if count is
non-zero, key release does not cause a <emphasis>
ButtonRelease</emphasis>
 event. Key release never causes a key release event.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_LockPtrBtn
</emphasis>
    </para>
    <para>
      button: BUTTON
    </para>
    <para>
      noLock: BOOL
    </para>
    <para>
      noUnlock: BOOL
    </para>
    <para>
      useDfltBtn: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
MouseKeys</emphasis>
 are not enabled, this action behaves like <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>Otherwise, if the button specified by <emphasis>
useDfltBtn</emphasis>
 and <emphasis>
button</emphasis>
 is not locked, key press causes a <emphasis>
ButtonPress</emphasis>
 instead of a key press and locks the button. If the button is already locked
or if <emphasis>
noLock</emphasis>
 is <emphasis>
True</emphasis>
, key press is ignored and has no effect.
  </para>
</listitem>
<listitem>
  <para>If the corresponding key press was ignored, and if <emphasis>
noUnlock</emphasis>
 is <emphasis>
False</emphasis>
, key release generates a <emphasis>
ButtonRelease</emphasis>
 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.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_SetPtrDflt
</emphasis>
    </para>
    <para>
      affect: CARD8
    </para>
    <para>
      value: CARD8
    </para>
    <para>
      dfltBtnAbs: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
MouseKeys</emphasis>
 are not enabled, this action behaves like <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>Otherwise, both key press and key release are ignored, but key press
changes the pointer value specified by <emphasis>
affect </emphasis>
to <emphasis>
value</emphasis>
, as follows:
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
which</emphasis>
 is <emphasis>
SA_AffectDfltBtn</emphasis>
, <emphasis>
value</emphasis>
 and <emphasis>
dfltBtnAbs</emphasis>
 specify the default pointer button used by the various pointer actions as
follow: If <emphasis>
dfltBtnAbs </emphasis>
is True, value specifies the button to be used, otherwise, <emphasis>
value</emphasis>
 specifies the amount to be added to the current default button. In either
case, illegal button choices are wrapped back into range.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
      <para>
    <emphasis>
SA_ISOLock
</emphasis>
      </para>
      <para>
      dfltIsGroup: <emphasis>
False
</emphasis>
      </para>
      <para>
      mods: MOD_DEF
      </para>
      <para>
      useModMap: BOOL
      </para>
      <para>
      noLock: BOOL
      </para>
      <para>
      noUnlock: BOOL
      </para>
      <para>
      noAffectMods: BOOL
      </para>
      <para>
      noAffectGrp: BOOL
      </para>
      <para>
      noAffectPtr: BOOL
      </para>
      <para>
      noAffectCtrls: BOOL
      </para>
      <para>
or
      </para>
      <para>
      dfltIsGroup: <emphasis>
True
</emphasis>
      </para>
      <para>
      group: INT8
      </para>
      <para>
      groupAbsolute: BOOL
      </para>
      <para>
      noAffectMods: BOOL
      </para>
      <para>
      noAffectGrp: BOOL
      </para>
      <para>
      noAffectPtr: BOOL
      </para>
      <para>
      noAffectCtrls: BOOL
      </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
dfltIsGroup</emphasis>
 is <emphasis>
True</emphasis>
, key press sets the base group specified by <emphasis>
groupAbsolute</emphasis>
 and <emphasis>
group</emphasis>
. Otherwise, key press sets the action modifiers in the keyboard’s base
modifiers.
  </para>
</listitem>
<listitem>
  <para>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 <emphasis>
SA_ISOLock</emphasis>
 operation.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
noAffectMods</emphasis>
 is <emphasis>
False</emphasis>
, any <emphasis>
SA_SetMods</emphasis>
 or <emphasis>
SA_LatchMods</emphasis>
 actions that occur simultaneously with the <emphasis>
ISOLock</emphasis>
 action are treated as <emphasis>
SA_LockMods</emphasis>
 instead.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
noAffectGrp</emphasis>
 is <emphasis>
False</emphasis>
, any <emphasis>
SA_SetGroup</emphasis>
 or <emphasis>
SA_LatchGroup</emphasis>
 actions that occur simultaneously with this action are treated as <emphasis>
SA_LockGroup</emphasis>
 actions instead.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
noAffectPtr</emphasis>
 is <emphasis>
False</emphasis>
, <emphasis>
SA_PtrBtn</emphasis>
 actions that occur simultaneously with the <emphasis>
SA_ISOLock</emphasis>
 action are treated as <emphasis>
SA_LockPtrBtn</emphasis>
 actions instead.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
noAffectCtrls</emphasis>
 is <emphasis>
False</emphasis>
, any <emphasis>
SA_SetControls</emphasis>
 actions that occur simultaneously with the <emphasis>
SA_ISOLock</emphasis>
 action are treated as <emphasis>
SA_LockControls</emphasis>
 actions instead.
  </para>
</listitem>
<listitem>
  <para>If no other actions were transformed by the <emphasis>
SA_ISOLock</emphasis>
 action, key release locks the group or modifiers specified by the action
arguments.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry><emphasis>
SA_TerminateServer</emphasis>
 </entry>
<entry>
<itemizedlist>
<listitem>
  <para>Key press terminates the server. Key release is ignored.
  </para>
</listitem>
<listitem>
  <para>This action is optional; servers are free to ignore it. If ignored, it
behaves like <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_SwitchScreen
</emphasis>
      </para>
      <para>
      num: INT8
      </para>
      <para>
      switchApp: BOOL
      </para>
      <para>
      screenAbs: BOOL
      </para>
</entry>
<entry>
<itemizedlist>
<listitem>
  <para>If the server supports this action and multiple screens or displays
(either virtual or real), this action changes to the active screen indicated by
<emphasis>
num</emphasis>
 and <emphasis>
screenAbs</emphasis>
. If <emphasis>
screenAbs</emphasis>
 is <emphasis>
True</emphasis>
, num specifies the index of the new screen; otherwise, num specifies an offset
from the current screen to the new screen.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
switchApp</emphasis>
 is <emphasis>
False</emphasis>
, 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.
  </para>
</listitem>
<listitem>
  <para>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 <emphasis>
SA_NoAction</emphasis>
, otherwise neither key press nor release generate an event.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
      <para><emphasis>SA_SetControls</emphasis></para>
      <para>controls: KB_BOOLCTRLMASK</para>
    </entry>
    <entry>
      <itemizedlist>
        <listitem>
          <para>
Key press enables any boolean controls that are specified in <emphasis>
controls</emphasis>
 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 <emphasis>
XkbControlsNotify</emphasis>
 events.
          </para>
	</listitem>
	</itemizedlist>
     </entry>
  </row>
  <row>
    <entry>
      <para><emphasis>SA_LockControls</emphasis></para>
      <para>
      controls: KB_BOOLCTRLMASK
      </para>
      <para>
      noLock: BOOL
      </para>
      <para>
      noUnlock: BOOL
      </para>
    </entry>
    <entry>
<itemizedlist>
<listitem>
  <para>If <emphasis>
noLock</emphasis>
 is <emphasis>
False</emphasis>
, key press locks and enables any controls that are specified in <emphasis>
controls</emphasis>
 and not already locked at the time of the key press.
</para>
<para>
If <emphasis>
noUnlock</emphasis>
 is <emphasis>
False</emphasis>
, key release unlocks and disables any controls that are specified in <emphasis>
controls</emphasis>
 and were not enabled at the time of the corresponding key press.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
      <para>
    <emphasis>
SA_ActionMessage</emphasis>
:
      pressMsg: BOOL
      </para>
      <para>
      releaseMsg: BOOL
      </para>
      <para>
      genEvent: BOOL
      </para>
      <para>
      message: STRING
      </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>if <emphasis>
pressMsg</emphasis>
 is <emphasis>
True</emphasis>
, key press generates an <emphasis>
XkbActionMessage</emphasis>
 event which reports the keycode, event type and the contents of <emphasis>
message</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
releaseMsg</emphasis>
 is <emphasis>
True</emphasis>
, key release generates an <emphasis>
XkbActionMessage</emphasis>
 event which reports the keycode, event type and contents of <emphasis>
message</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
genEvent</emphasis>
 is <emphasis>
True</emphasis>
, both press and release generate key press and key release events, regardless
of whether they also cause an <emphasis>
XkbActionMessage</emphasis>
.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_RedirectKey
</emphasis>
    </para>
    <para>
      newKey: KEYCODE
    </para>
    <para>
      modsMask: KEYMASK
    </para>
    <para>
      mods: KEYMASK
    </para>
    <para>
      vmodsMask: CARD16
    </para>
    <para>
      vmods: CARD16
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>Key press causes a key press event for the key specified by <emphasis>
newKey</emphasis>
 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
<emphasis>
modsMask</emphasis>
 are set to corresponding values from <emphasis>
mods</emphasis>
. Any real modifiers bound to the virtual modifiers specified in <emphasis>
vmodsMask</emphasis>
 are either set or cleared, depending on the corresponding value in <emphasis>
vmods</emphasis>
. If the real and virtual modifier definitions specify conflicting values for a
single modifier, the real modifier definition has priority.
  </para>
</listitem>
<listitem>
  <para>Key release causes a key release event for the key specified by
<emphasis>
newKey</emphasis>
; the state field for this event consists of the effective keyboard modifiers
at the time of the release, changed as described above.
  </para>
</listitem>
<listitem>
  <para>The <emphasis>
SA_RedirectKey</emphasis>
 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.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_DeviceBtn
</emphasis>
    </para>
    <para>
      count: CARD8
    </para>
    <para>
      button: BUTTON
    </para>
    <para>
      device: CARD8
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>The <emphasis>
device</emphasis>
 field specifies the ID of an extension device; the <emphasis>
button</emphasis>
 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 <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>Otherwise, key press causes one or more input extension device button
events instead of the usual key press event. If <emphasis>
count</emphasis>
 is <emphasis>
0</emphasis>
, key press generates a single <emphasis>
DeviceButtonPress</emphasis>
 event; if <emphasis>
count</emphasis>
 is greater than <emphasis>
0</emphasis>
, key press generates <emphasis>
count</emphasis>
 pairs of <emphasis>
DeviceButtonPress</emphasis>
 and <emphasis>
DeviceButtonRelease</emphasis>
 events.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
count</emphasis>
 is <emphasis>
0</emphasis>
, key release generates an input extension <emphasis>
DeviceButtonRelease</emphasis>
 which matches the event generated by the corresponding key press; if count is
non-zero, key release does not cause a <emphasis>
DeviceButtonRelease</emphasis>
 event. Key release never causes a key release event.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
    <para>
    <emphasis>
SA_LockDeviceBtn
</emphasis>
    </para>
    <para>
      button: BUTTON
    </para>
    <para>
      device: CARD8
    </para>
    <para>
      noLock: BOOL
    </para>
    <para>
      noUnlock: BOOL
    </para>
      </entry>
<entry>
<itemizedlist>
<listitem>
  <para>The <emphasis>
device</emphasis>
 field specifies the ID of an extension device; the <emphasis>
button</emphasis>
 field specifies the index of a button on that device. If the device or button
specified by this action are illegal, it behaves like <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>Otherwise, if the specified button is not locked and if <emphasis>
noLock</emphasis>
 is <emphasis>
False</emphasis>
, key press causes an input extension <emphasis>
DeviceButtonPress</emphasis>
 event instead of a key press event and locks the button. If the button is
already locked or if <emphasis>
noLock</emphasis>
 is <emphasis>
True</emphasis>
, key press is ignored and has no effect.
  </para>
</listitem>
<listitem>
  <para>If the corresponding key press was ignored, and if <emphasis>
noUnlock</emphasis>
 is <emphasis>
False</emphasis>
, key release generates an input extension <emphasis>
DeviceButtonRelease</emphasis>
 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.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
  <row>
    <entry>
<para>
    <emphasis>
SA_DeviceValuator
</emphasis>
</para>
<para>
      <emphasis>
device</emphasis>
: CARD8
</para>
<para>
      <emphasis>
val1What</emphasis>
: SA_DVOP
</para>
<para>
      <emphasis>
val1</emphasis>
: CARD8
</para>
<para>
      <emphasis>
val1Value</emphasis>
: INT8
</para>
<para>
      <emphasis>
val1Scale</emphasis>
: 0...7
</para>
<para>
      <emphasis>
val2What</emphasis>
: BOOL
</para>
<para>
      <emphasis>
val2</emphasis>
: CARD8
</para>
<para>
      <emphasis>
val2Value</emphasis>
: INT8
</para>
<para>
      <emphasis>
val2Scale</emphasis>
: 0...7
</para>
</entry>
<entry>
<itemizedlist>
<listitem>
  <para>The <emphasis>
device</emphasis>
 field specifies the ID of an extension device; <emphasis>
val1</emphasis>
 and <emphasis>
val2</emphasis>
 specify valuators on that device. If <emphasis>
device</emphasis>
 is illegal or if neither <emphasis>
val1</emphasis>
 nor <emphasis>
val2</emphasis>
 specifies a legal valuator, this action behaves like <emphasis>
SA_NoAction</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
valn</emphasis>
 specifies a legal valuator and <emphasis>
valnWhat</emphasis>
 is not <emphasis>
SA_IgnoreVal</emphasis>
, the specified value is adjusted as specified by <emphasis>
valnWhat</emphasis>
:
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
valnWhat</emphasis>
 is <emphasis>
SA_SetValMin</emphasis>
, <emphasis>
valn</emphasis>
 is set to its minimum legal value.
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
valnWhat</emphasis>
 is <emphasis>
SA_SetValCenter</emphasis>
, <emphasis>
valn</emphasis>
 is centered (to (max-min)/2).
  </para>
</listitem>
<listitem>
  <para>If <emphasis>
valnWhat</emphasis>
 is <emphasis>
SA_SetValMax</emphasis>
, <emphasis>
valn</emphasis>
 is set to its maximum legal value.
  </para>
</listitem>
<listitem>
  <para>if <emphasis>
valnWhat</emphasis>
 is <emphasis>
SA_SetValRelative</emphasis>
, <mediaobject>
 <imageobject> <imagedata format="SVG" fileref="XKBproto-4.svg"/>
 </imageobject>
 </mediaobject>

 is added to <emphasis>
valn</emphasis>
.
  </para>
</listitem>
<listitem>
  <para>if <emphasis>
valnWhat</emphasis>
 is <emphasis>
SA_SetValAbsolute</emphasis>
, <emphasis>
valn</emphasis>
 is set to <mediaobject>
 <imageobject> <imagedata format="SVG" fileref="XKBproto-5.svg"/>
 </imageobject>
 </mediaobject>

.
  </para>
</listitem>
<listitem>
  <para>Illegal values for <emphasis>
SA_SetValRelative</emphasis>
 or <emphasis>
SA_SetValAbsolute</emphasis>
 are clamped into range.
  </para>
</listitem>
</itemizedlist>
</entry>
  </row>
</tbody>
</tgroup>
</informaltable>

<para>
If <emphasis>
StickyKeys</emphasis>
 are enabled, all <emphasis>
SA_SetMods</emphasis>
 and <emphasis>
SA_SetGroup</emphasis>
 actions act like <emphasis>
SA_LatchMods</emphasis>
 and <emphasis>
SA_LatchGroup</emphasis>
 respectively. If the <emphasis>
LatchToLock</emphasis>
 AccessX option is set, either action behaves as if both the <emphasis>
SA_ClearLocks</emphasis>
 and <emphasis>
SA_LatchToLock</emphasis>
 flags are set.
</para>


<para>
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.
</para>


<para>
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.
</para>


<para>
Events sent to clients that have not issued an <emphasis>
XkbUseExtension</emphasis>
 request contain a compatibility state in place of the actual XKB keyboard
state. See <link linkend='Effects_of_XKB_on_Core_Protocol_Events'>Effects of XKB on Core
Protocol Events</link> for a description of this compatibility mapping.
</para>


</sect1>
<sect1 id='Delivering_a_Key_or_Button_Event_to_a_Client'>
<title>Delivering a Key or Button Event to a Client</title>

<para>
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:
</para>

<itemizedlist>
<listitem>
  <para>A passive grab triggers if the modifier state specified in the grab
matches the grab compatibility state (described in <link
linkend='Compatibility_Components_of_Keyboard_State'>Compatibility Components of Keyboard
State</link>). Clients can choose to use the XKB grab state instead by setting
the <emphasis>
GrabsUseXKBState</emphasis>
 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.
  </para>
</listitem>
<listitem>
  <para>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.
  </para>
</listitem>
<listitem>
  <para>If the <emphasis>
LookupStateWhenGrabbed</emphasis>
 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 <emphasis>
GrabsUseXKBState</emphasis>
 per-client flag. If <emphasis>
LookupStateWhenGrabbed</emphasis>
 is not set, they include the XKB or compatibility grab state, instead.
  </para>
</listitem>
<listitem>
  <para>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
<link linkend='Computing_A_State_Field_from_an_XKB_State'>Computing A State Field from an
XKB State</link>.
  </para>
</listitem>
<listitem>
  <para>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 <link linkend='Detectable_Autorepeat'>
Detectable Autorepeat</link>), the event is not delivered to the client.
  </para>
</listitem>
</itemizedlist>

<para>
The following section explains the intent of the XKB interactions with core
protocol grabs and the reason that the per-client flags are needed.
</para>


<sect2 id='XKB_Interactions_With_Core_Protocol_Grabs'>
<title>XKB Interactions With Core Protocol Grabs</title>

<para>
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.
</para>


<para>
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.
</para>

<itemizedlist>
<listitem>
  <para>The largest problems arise from the fact that an XKB state field
encodes an explicit keyboard group in bits 13-14 (as described in <link
linkend='Computing_A_State_Field_from_an_XKB_State'>Computing A State Field from an XKB
State</link>), 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 <emphasis>
GrabsUseXKBState</emphasis>
 per-client flag to indicate that they are specifying passive grabs using an
XKB state.
  </para>
</listitem>
<listitem>
  <para>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 <emphasis>
LookupStateWhenGrabbed</emphasis>
 per-client flag in order to receive the same state component whether or not a
grab is active.
  </para>
<para>
The <emphasis>
GrabsUseXKBState</emphasis>
 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.</para>
</listitem>
</itemizedlist>

<para>
The state used to trigger a passive grab is controlled by the setting of the
<emphasis>
GrabsUseXKBState</emphasis>
 per-client flag at the time the grab is registered. Changing this flag does
not affect existing passive grabs.
</para>
</sect2>
</sect1>
</chapter>
