NAME

X11::Xlib::Keymap - Object Oriented access to the X11 keymap

DESCRIPTION

For better or for worse, (hah, who am I kidding; worse) the X11 protocol gives applications the direct keyboard scan codes from the input device, and provides two tables to let applications do their own interpretation of the codes. The first table ("keymap") maps the scan codes (single byte) to one or more symbolic constants describing the glyph on the key. Choosing which of the several symbols to use depends on which "modifiers" are in effect. The second table is the "modifier map", which lists keys (scan codes, again) that are part of each of the eight modifier groups. Two modifier groups (Shift and Control) have constant meaning, but the rest require some creative logic to interpret.

The keymap can't be used without the modifier map, but the modifier map can't be interpreted without the keymap, so both tables are rolled together into this object.

While there are always less than 255 hardware scan codes, the set of device- independent KeySym codes is huge (including Unicode as a subset). Since the KeySym constants can't be practically exported by a Perl module, this API mostly tries to let you use the symbolic names of keys, or Unicode characters. Translating KeySym names and characters to/from KeySym values is a client-side operation.

ATTRIBUTES

display

Holds a weak-ref to the Display, used for the loading and saving operations.

keymap

Arrayref that maps from a key code (byte) to an arrayref of KeySyms.

[
  ...
  [ $normal_key, $key_with_shift, $mode2_normal_key, $mode2_key_with_shift, ... ]
  ...
]

Each KeyCode (up to 255 of them) is used as an index into the outer array, and the inner array's elements correspond to different shift/mode states, where "mode2" indicates a dynamic switch of key layout of some sort. Each key's array can contain additional vendor-specific elements.

This table is stored exactly as loaded from the X11 server.

rkeymap

A hashref mapping from the symbolic name of a key to its scan code.

modmap

An arrayref of eight modifier groups, each element being the list of key codes that are part of that modifier.

modmap_ident

A hashref of logical modifier group names to array index within the modmap. On a modern US-English Linux desktop you will likely find:

shift    => 0,
lock     => 1, capslock => 1,
control  => 2,
alt      => 3, meta => 3,
numlock  => 4,
win      => 6, super => 6
mode     => 7,

but the numbers 3..7 can be re-purposed by your particular key layout. Note that X11 has a concept of "mode switching" where a modifier completely changes the meaning of every key. I think this is used by multi-lingual setups, but I have not tested/confirmed this.

METHODS

new

my $keymap= X11::Xlib::Keymap->new(display => $dpy, %attrs);

Initialize a keymap with the list of parameters. "display" is required for any load/save operations. You can use most of the class with just the "keymap" and "modmap" attributes.

find_keycode

my $keycode= $display->find_keycode( $key_sym_or_char );

Return a keycode for the parameter, which is either a KeySym name (XStringToKeysym) or a string holding a Unicode character (char_to_keysym). If more than one key code can map to the KeySym, this returns an arbitrary one of them. Returns undef if no matches were found.

find_keysym

my $sym_name= $display->find_keysym( $key_code, $modifier_bits );
my $sym_name= $display->find_keysym( $XKeyEvent );

Returns the symbolic name of a key, given its scan code and current modifier bits.

For convenience, you can pass an XKeyEvent object.

If you don't have modifier bits, pass 0.

keymap_reload

$keymap->keymap_reload();        # reload all keys
$keymap->keymap_reload(@codes);  # reload range from min to max

Reload all or a portion of the keymap. If @codes are given, then only load from min(@codes) to max(@codes). (The cost of loading the extra codes not in the list is assumed to be less than the cost of multiple round trips to the server to pick only the specific codes)

keymap_save

$keymap->keymap_save(@codes);    # Save changes to keymap (not modmap)

Save any changes to "keymap" back to the server. If @codes are given, then only save from min(@codes) to max(@codes).

See "save" to save both the "keymap" and "modmap".

modmap_sym_list

my @keysym_names= $display->modmap_sym_list( $modifier );

Get the default keysym names for all the keys bound to the $modifier. Modifier is one of 'shift','lock','control','mod1','mod2','mod3','mod4','mod5', 'alt','meta','capslock','shiftlock','win','super','numlock','hyper'.

Any modifier after mod5 in that list might not be defined for your keymap (and return an empty list, rather than an error).

modmap_add_codes

my $n_added= $keymap->modmap_add_codes( $modifier, @key_codes );

Adds key codes (and remove duplicates) to one of the eight modifier groups. $modifier is one of the values listed above.

Throws an exception if $modifier does not exist. Returns the number of key codes added.

modmap_add_syms

my $n_added= $keymap->modmap_add_syms( $modifier, @keysym_names );

Convert keysym names to key codes and then call "modmap_add_codes".

Warns if any keysym is not part of the current keyboard layout. Returns the number of key codes added.

modmap_del_codes

my $n_removed= $keymap->modmap_del_syms( $modifier, @key_codes );

Removes the listed key codes from the named modifier, or from all modifiers if $modifier is undef.

Warns if $modifier does not exist. Silently ignores key codes that don't exist in the modifiers. Returns number of key codes removed.

modmap_del_syms

my $n_removed= $display->modmap_del_syms( $modifier, @keysym_names );

Convert keysym names to key codes and then call "modmap_del_codes".

Warns if any keysym is not part of the current keyboard layout. Returns number of key codes removed.

modmap_save

$keymap->modmap_save;

Call "XSetModifierMapping" in X11::Xlib for the current "modmap".

save

$keymap->save

Save the full "keymap" and "modmap".

EXAMPLES

Press a Key

Suppose you have an old DOS game that you are playing in Dosbox, and you find a neat trick to level up your character by pressing 'R' repeatedly. You might bang out a quick perl one-liner like this:

perl -e 'use X11::Xlib; $d= X11::Xlib->new;
   $r= $d->keymap->find_keycode("R") or die "No R key?";
   while (1) { $d->fake_key($r, 1); $d->fake_key($r, 0);
    $d->flush; sleep 1; }'

AUTHOR

Olivier Thauvin, <nanardon@nanardon.zarb.org>

Michael Conrad, <mike@nrdvana.net>

COPYRIGHT AND LICENSE

Copyright (C) 2009-2010 by Olivier Thauvin

Copyright (C) 2017-2023 by Michael Conrad

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.