1Title: Key Values
2
3## Functions for manipulating keyboard codes
4
5Key values are the codes which are sent whenever a key is pressed or released.
6They are included in the data contained in a key press or release `GdkEvent`.
7The complete list of key values can be found in the `gdk/gdkkeysyms.h` header
8file.
9
10Key values are regularly updated from the upstream X.org X11 implementation,
11so new values are added regularly. They will be prefixed with GDK_KEY_ rather
12than XF86XK_ or XK_ (for older symbols).
13
14Key values can be converted into a string representation using
15gdk_keyval_name(). The reverse function, converting a string to a key value,
16is provided by gdk_keyval_from_name().
17
18The case of key values can be determined using gdk_keyval_is_upper() and
19gdk_keyval_is_lower(). Key values can be converted to upper or lower case
20using gdk_keyval_to_upper() and gdk_keyval_to_lower().
21
22When it makes sense, key values can be converted to and from
23Unicode characters with gdk_keyval_to_unicode() and gdk_unicode_to_keyval().
24
25## Key groups
26
27At the lowest level, physical keys on the keyboard are represented by
28numeric keycodes, and GDK knows how to translate these keycodes into
29key values according to the configured keyboard layout and the current
30state of the keyboard. In the GDK api, the mapping from keycodes to key
31values is available via [method@Gdk.Display.map_keycode], and the reverse
32mapping is available via [method@Gdk.Display.map_keyval]. The results of
33these functions are returned in [struct@Gdk.KeymapKey] structures.
34
35You can think of a [struct@Gdk.KeymapKey] as a representation of a symbol
36printed on a physical keyboard key. That is, it contains three pieces of
37information:
38
39  1. first, it contains the hardware keycode; this is an identifying number
40    for a physical key
41  1. second, it contains the “level” of the key. The level indicates which
42    symbol on the key will be used, in a vertical direction. So on a standard
43    US keyboard, the key with the number “1“ on it also has the exclamation
44    point (”!”) character on it. The level indicates whether to use the “1”
45    or the “!” symbol. The letter keys are considered to have a lowercase
46    letter at level 0, and an uppercase letter at level 1, though normally
47    only the uppercase letter is printed on the key
48  1. third, the [struct@Gdk.KeymapKey] contains a group; groups are not used on
49     standard US keyboards, but are used in many other countries. On a
50     keyboard with groups, there can be 3 or 4 symbols printed on a single
51     key. The group indicates movement in a horizontal direction. Usually
52     groups are used for two different languages. In group 0, a key might
53     have two English characters, and in group 1 it might have two Hebrew
54     characters. The Hebrew characters will be printed on the key next to
55     the English characters.
56
57When GDK creates a key event in order to deliver a key press or release,
58it first converts the current keyboard state into an effective group and
59level. This is done via a set of rules that varies widely according to
60type of keyboard and user configuration. The input to this translation
61consists of the hardware keycode pressed, the active modifiers, and the
62active group. It then applies the appropriate rules, and returns the
63group/level to be used to index the keymap, along with the modifiers
64which did not affect the group and level. i.e. it returns “unconsumed
65modifiers.” The keyboard group may differ from the effective group used
66for lookups because some keys don't have multiple groups - e.g. the
67<kbd>Enter</kbd> key is always in group 0 regardless of keyboard state.
68
69The results of the translation, including the keyval, are all included
70in the key event and can be obtained via [class@Gdk.KeyEvent] getters.
71
72### Consumed modifiers
73
74The `consumed_modifiers` in a key event are modifiers that should be masked
75out from @state when comparing this key press to a hot key. For instance,
76on a US keyboard, the `plus` symbol is shifted, so when comparing a key
77press to a `<Control>plus` accelerator `<Shift>` should be masked out.
78
79```c
80// We want to ignore irrelevant modifiers like ScrollLock
81#define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_ALT_MASK)
82state = gdk_event_get_modifier_state (event);
83gdk_keymap_translate_keyboard_state (keymap,
84                                     gdk_key_event_get_keycode (event),
85                                     state,
86                                     gdk_key_event_get_group (event),
87                                     &keyval, NULL, NULL, &consumed);
88if (keyval == GDK_PLUS &&
89    (state & ~consumed & ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
90  // Control was pressed
91```
92
93An older interpretation of `consumed_modifiers` was that it contained
94all modifiers that might affect the translation of the key;
95this allowed accelerators to be stored with irrelevant consumed
96modifiers, by doing:
97
98```c
99// XXX Don’t do this XXX
100if (keyval == accel_keyval &&
101    (state & ~consumed & ALL_ACCELS_MASK) == (accel_mods & ~consumed))
102  // Accelerator was pressed
103```
104
105However, this did not work if multi-modifier combinations were
106used in the keymap, since, for instance, `<Control>` would be
107masked out even if only `<Control><Alt>` was used in
108the keymap. To support this usage as well as well as possible, all single
109modifier combinations that could affect the key for any combination
110of modifiers will be returned in `consumed_modifiers`; multi-modifier
111combinations are returned only when actually found in `state`. When
112you store accelerators, you should always store them with consumed
113modifiers removed. Store `<Control>plus`, not `<Control><Shift>plus`.
114