Replacing a Keyboard On the Fly
Some operating system and X server implementations allow
hot plugging of
input devices. When using these implementations, input devices can be unplugged
and new ones plugged in without restarting the software that is using those
devices. There is no provision in the standard X server for notification of
client programs if input devices are unplugged and/or new ones plugged in. In
the case of the X keyboard, this could result in the X server having a keymap
that does not match the new keyboard.
If the X server implementation supports the X input device extension, a client
program may also change the X keyboard programmatically. The
XChangeKeyboardDevice input extension request allows a client to designate an
input extension keyboard device as the X keyboard, in which case the old X
keyboard device becomes inaccessible except via the input device extension. In
this case, core protocol
MappingNotify
and input extension
XChangeDeviceNotify
events are generated to notify all clients that a new keyboard with a new
keymap has been designated.
When a client opens a connection to the X server, the server reports the
minimum and maximum keycodes. The server keeps track of the minimum and maximum
keycodes last reported to each client. When delivering events to a particular
client, the server filters out any events that fall outside of the valid range
for the client.
Xkb provides an
XkbNewKeyboardNotify
event that reports a change in keyboard geometry and/or the range of supported
keycodes. The server can generate an
XkbNewKeyboardNotify
event when it detects a new keyboard or in response to an
XkbGetKeyboardByName
request that loads a new keyboard description. Selecting for
XkbNewKeyboardNotify
events allows Xkb-aware clients to be notified whenever a keyboard change
occurs that may affect the keymap.
When a client requests
XkbNewKeyboardNotify
events, the server compares the range of keycodes for the current keyboard to
the range of keycodes that are valid for the client. If they are not the same,
the server immediately sends the client an
XkbNewKeyboardNotify
event. Even if the new keyboard is not new to the server,
it is new to this particular client.
When the server sends an
XkbNewKeyboardNotify
event to a client to inform it of a new keycode range, it resets the stored
range of legal keycodes for the client to the keycode range reported in the
event; it does not reset this range for the client if it does not sent an
XkbNewKeyboardNotify
event to a client. Because Xkb-unaware clients and Xkb-aware clients that do
not request
XkbNewKeyboardNotify
events are never sent these events, the server’s notion of the legal keycode
range never changes, and these clients never receive events from keys that fall
outside of their notion of the legal keycode range.
Clients that have not selected to receive
XkbNewKeyboardNotify
events do, however, receive the
XkbNewKeyboardNotify
event when a keyboard change occurs. Clients that have not selected to receive
this event also receive numerous other events detailing the individual changes
that occur when a keyboard change occurs.
Clients wishing to track changes in
min_key_code
and
max_key_code
must watch for both
XkbNewKeyboardNotify
and
XkbMapNotify
events, because a simple mapping change causes an
XkbMapNotify
event and may change the range of valid keycodes, but does not cause an
XkbNewKeyboardNotify
event. If a client does not select for
XkbNewKeyboardNotify
events, the server restricts the range of keycodes reported to the client.
In addition to filtering out-of-range key events, Xkb:
Adjusts core protocol
MappingNotify
events to refer only to keys that match the stored legal range.
Reports keyboard mappings for keys that match the stored legal range to clients
that issue a core protocol
GetKeyboardMapping
request.
Reports modifier mappings only for keys that match the stored legal range to
clients that issue a core protocol
GetModifierMapping
request.
Restricts the core protocol
ChangeKeyboardMapping
and
SetModifierMapping
requests to keys that fall inside the stored legal range.
In short, Xkb does everything possible to hide from Xkb-unaware clients the
fact that the range of legal keycodes has changed, because such clients cannot
be expected to deal with them. Xkb events and requests are not modified in this
manner; all Xkb events report the full range of legal keycodes. No requested
Xkb events are discarded, and no Xkb requests have their keycode range clamped.
eventsXkbNewKeyboardNotifyXkbNewKeyboardNotifyEvent
The structure for the
XkbNewKeyboardNotify
event is defined as follows:
typedef struct _XkbNewKeyboardNotify {
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; /* XkbNewKeyboardNotify */
int device; /* device ID of new keyboard */
int old_device; /* device ID of old keyboard */
int min_key_code; /* min keycode of new keyboard */
int max_key_code; /* max keycode of new keyboard */
int old_min_key_code; /* min keycode of old keyboard */
int old_max_key_code; /* max keycode of old keyboard */
unsigned int changed; /* changed aspects - see masks below */
char req_major; /* major request that caused change */
char req_minor; /* minor request that caused change */
} XkbNewKeyboardNotifyEvent;
To receive name notify events, use
XkbSelectEvents
(see section 4.3) with
XkbNewKeyboardNotifyMask
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
XkbNewKeyboardNotify,
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 19.1.
XkbNewKeyboardNotifyEvent DetailsXkbNewKeyboardNotify Event DetailsValueCircumstancesXkbNKN_KeycodesMask(1L<<0)Notification of keycode range changes wantedXkbNKN_GeometryMask(1L<<1)Notification of geometry changes wantedXkbNKN_DeviceIDMask(1L<<2)Notification of device ID changes wantedXkbAllNewKeyboardEventsMask(0x7)Includes all of the above masks
The
req_major
and
req_minor
fields indicate what type of keyboard change has occurred.
If
req_major
and
req_minor
are zero, the device change was not caused by a software request to the server
— a spontaneous change has occurred, such as hot-plugging a new device. In
this case,
device
is the device identifier for the new, current X keyboard device, but no
implementation-independent guarantee can be made about
old_device.
old_device
may be identical to
device
(an implementor is permitted to reuse the device specifier when the device
changes); or it may be different. Note that
req_major
and
req_minor
being zero do not necessarily mean that the physical keyboard device has
changed; rather, they only imply a spontaneous change outside of software
control (some systems have keyboards that can change personality at the press
of a key).
If the keyboard change is the result of an X Input Extension
ChangeKeyboardDevice
request,
req_major
contains the input extension major opcode, and
req_minor
contains the input extension request number for
X_ChangeKeyboardDevice.
In this case,
device
and
old_device
are different, with
device
being the identifier for the new, current X keyboard device, and
old_device
being the identifier for the former device.
If the keyboard change is the result of an
XkbGetKeyboardByName
function call, which generates an
X_kbGetKbdByName
request,
req_major
contains the Xkb extension base event code (see section 2.4), and
req_minor
contains the event code for the Xkb extension request
X_kbGetKbdByName.
device
contains the device identifier for the new device, but nothing definitive can
be said for
old_device;
it may be identical to
device,
or it may be different, depending on the implementation.