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