Selkies
Developer Referencex11_xkb

XkbLink

One connection's XKEYBOARD session: keysym placement and group control.

Opened through open_xkb_link; every method talks to the server on the connection the link was opened on, so a group lock and the XTEST key that follows it are processed in order without a round trip between them.

Attributes

attribute_d
= xdisplay
attribute_opcode
= major_opcode
attributeevent_base
= event_base

First event code of the extension on this connection.

attributecore_device
= core_device

XKB device id of the core keyboard, which the replacement notify (sent once per device) is filtered on.

attribute_placement
= None

Keysym to (keycode, group, level) at the lowest group, then level, then keycode carrying it; None until a lookup needs it.

Functions

func__init__(self, xdisplay, major_opcode, event_base, core_device) -> None
Source Code
def __init__(self, xdisplay: Any, major_opcode: int, event_base: int,
             core_device: int) -> None:
    self._d = xdisplay
    self._opcode = major_opcode
    self.event_base = event_base
    self.core_device = core_device
    self._placement = None
paramself
paramxdisplayAny
parammajor_opcodeint
paramevent_baseint
paramcore_deviceint

Returns

None
funcinvalidate(self) -> None

Forget the map; the next lookup refetches it from the server.

Source Code
def invalidate(self) -> None:
    """Forget the map; the next lookup refetches it from the server."""
    self._placement = None
paramself

Returns

None
funclocate(self, keysym) -> Optional[Tuple[int, int, int]]

Where the server's keymap puts a keysym.

Source Code
def locate(self, keysym: int) -> Optional[Tuple[int, int, int]]:
    """Where the server's keymap puts a keysym.

    Returns:
        `(keycode, group, level)` for the lowest group, then level, then
        keycode carrying the keysym at an injectable level, or None when
        the keymap does not carry it.
    """
    if self._placement is None:
        self._placement = self._fetch_placement()
    return self._placement.get(keysym)
paramself
paramkeysymint

Returns

typing.Optional

(keycode, group, level) for the lowest group, then level, then

func_fetch_placement(self) -> Dict[int, Tuple[int, int, int]]

Fetch the XKB symbol map and index it by keysym.

Only the key symbol maps are requested: each is the key's group count and width followed by width keysyms per group, which is all the placement needs; the levels Shift and AltGr cannot reach are skipped.

Source Code
def _fetch_placement(self) -> Dict[int, Tuple[int, int, int]]:
    """Fetch the XKB symbol map and index it by keysym.

    Only the key symbol maps are requested: each is the key's group count
    and width followed by `width` keysyms per group, which is all the
    placement needs; the levels Shift and AltGr cannot reach are skipped.
    """
    info = self._d.display.info
    lo, hi = info.min_keycode, info.max_keycode
    reply = _XkbGetMap(
        display=self._d.display, opcode=self._opcode, device_spec=XKB_USE_CORE_KBD,
        full=0, partial=XKB_KEY_SYMS_MASK, first_type=0, n_types=0,
        first_key_sym=lo, n_key_syms=hi - lo + 1, first_key_action=0,
        n_key_actions=0, first_key_behavior=0, n_key_behaviors=0, virtual_mods=0,
        first_key_explicit=0, n_key_explicit=0, first_mod_map_key=0,
        n_mod_map_keys=0, first_vmod_map_key=0, n_vmod_map_keys=0)
    blob = bytes(reply.map)
    placement = {}
    offset = 0
    for keycode in range(reply.first_key_sym, reply.first_key_sym + reply.n_key_syms):
        group_info, width, nsyms = struct.unpack_from('=xxxxBBH', blob, offset)
        offset += 8
        syms = struct.unpack_from('=%dI' % nsyms, blob, offset)
        offset += 4 * nsyms
        ngroups = group_info & 0x0F
        for group in range(ngroups):
            for level in range(min(width, XKB_INJECTABLE_LEVELS)):
                index = group * width + level
                sym = syms[index] if index < nsyms else 0
                if not sym:
                    continue
                have = placement.get(sym)
                if have is None or (group, level, keycode) < (have[1], have[2], have[0]):
                    placement[sym] = (keycode, group, level)
    return placement
paramself

Returns

typing.Dict[int, typing.Tuple[int, int, int]]
funclocked_group(self) -> int

The group the server currently has locked for the core keyboard.

Source Code
def locked_group(self) -> int:
    """The group the server currently has locked for the core keyboard."""
    reply = _XkbGetState(display=self._d.display, opcode=self._opcode,
                         device_spec=XKB_USE_CORE_KBD)
    return int(reply.locked_group)
paramself

Returns

int
funclock_group(self, group) -> None

Lock the core keyboard's group; queued, not flushed, so the caller's next XTEST key follows it in the same write.

Source Code
def lock_group(self, group: int) -> None:
    """Lock the core keyboard's group; queued, not flushed, so the caller's
    next XTEST key follows it in the same write."""
    _XkbLatchLockState(
        display=self._d.display, onerror=_log_x_error, opcode=self._opcode,
        device_spec=XKB_USE_CORE_KBD, affect_mod_locks=0, mod_locks=0,
        lock_group=1, group_lock=group, affect_mod_latches=0, mod_latches=0,
        latch_group=0, group_latch=0)
paramself
paramgroupint

Returns

None
funcreplaced_keyboard(self, event) -> Optional[Tuple[int, int]]

Recognise the XkbNewKeyboardNotify a whole-keyboard replacement sends.

The server emits one per device; only the core keyboard's counts, so a layout switch is handled once.

Source Code
def replaced_keyboard(self, event: Any) -> Optional[Tuple[int, int]]:
    """Recognise the XkbNewKeyboardNotify a whole-keyboard replacement sends.

    The server emits one per device; only the core keyboard's counts, so a
    layout switch is handled once.

    Returns:
        `(min_keycode, max_keycode)` of the new keyboard, or None when the
        event is something else.
    """
    if event.type != self.event_base or getattr(event, 'detail', None) != XKB_NEW_KEYBOARD_NOTIFY:
        return None
    data = bytes(event.data)
    if len(data) < 8:
        return None
    _time, device, _old_device, lo, hi = struct.unpack_from('=IBBBB', data, 0)
    if device != self.core_device:
        return None
    return lo, hi
paramself
parameventAny

Returns

typing.Optional

(min_keycode, max_keycode) of the new keyboard, or None when the

On this page

Edit on GitHub