# 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.

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 Details

XkbNewKeyboardNotify Event Details | Value | Circumstances
XkbNKN_KeycodesMask | (1L<<0) | Notification of keycode range changes wanted
XkbNKN_GeometryMask | (1L<<1) | Notification of geometry changes wanted
XkbNKN_DeviceIDMask | (1L<<2) | Notification of device ID changes wanted
XkbAllNewKeyboardEventsMask | (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.