X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gdk%2Fgdkkeys.c;h=5b7ea78e5fb2ee404f1970a9aa1e1c5b8beeda1d;hb=4b92625fe0cad34aa9bec11963f678f88214f442;hp=6953b4642683971f3f6448bb49fc7b84fb796ac4;hpb=18dc96caf883cad9226cb6e783dd930a7fe62c2e;p=~andy%2Fgtk diff --git a/gdk/gdkkeys.c b/gdk/gdkkeys.c index 6953b4642..5b7ea78e5 100644 --- a/gdk/gdkkeys.c +++ b/gdk/gdkkeys.c @@ -26,9 +26,80 @@ #include "config.h" +#include "gdkkeysprivate.h" #include "gdkdisplay.h" -#include "gdkkeys.h" -#include "gdkalias.h" +#include "gdkdisplaymanagerprivate.h" + + +/** + * SECTION:keys + * @Short_description: Functions for manipulating keyboard codes + * @Title: Key Values + * + * Key values are the codes which are sent whenever a key is pressed or released. + * They appear in the #GdkEventKey.keyval field of the + * #GdkEventKey structure, which is passed to signal handlers for the + * #GtkWidget::key-press-event and #GtkWidget::key-release-event signals. + * The complete list of key values can be found in the + * <gdk/gdkkeysyms.h> header file. + * + * Key values are regularly updated from the upstream X.org X11 implementation, + * so new values are added regularly. They will be prefixed with GDK_KEY_ rather + * than XF86XK_ or XK_ (for older symbols). + * + * Key values can be converted into a string representation using + * gdk_keyval_name(). The reverse function, converting a string to a key value, + * is provided by gdk_keyval_from_name(). + * + * The case of key values can be determined using gdk_keyval_is_upper() and + * gdk_keyval_is_lower(). Key values can be converted to upper or lower case + * using gdk_keyval_to_upper() and gdk_keyval_to_lower(). + * + * When it makes sense, key values can be converted to and from + * Unicode characters with gdk_keyval_to_unicode() and gdk_unicode_to_keyval(). + * + * + * One #GdkKeymap object exists for each user display. gdk_keymap_get_default() + * returns the #GdkKeymap for the default display; to obtain keymaps for other + * displays, use gdk_keymap_get_for_display(). A keymap + * is a mapping from #GdkKeymapKey to key values. You can think of a #GdkKeymapKey + * as a representation of a symbol printed on a physical keyboard key. That is, it + * contains three pieces of information. First, it contains the hardware keycode; + * this is an identifying number for a physical key. Second, it contains the + * level of the key. The level indicates which symbol on the + * key will be used, in a vertical direction. So on a standard US keyboard, the key + * with the number "1" on it also has the exclamation point ("!") character on + * it. The level indicates whether to use the "1" or the "!" symbol. The letter + * keys are considered to have a lowercase letter at level 0, and an uppercase + * letter at level 1, though only the uppercase letter is printed. Third, the + * #GdkKeymapKey contains a group; groups are not used on standard US keyboards, + * but are used in many other countries. On a keyboard with groups, there can be 3 + * or 4 symbols printed on a single key. The group indicates movement in a + * horizontal direction. Usually groups are used for two different languages. In + * group 0, a key might have two English characters, and in group 1 it might have + * two Hebrew characters. The Hebrew characters will be printed on the key next to + * the English characters. + * + * + * In order to use a keymap to interpret a key event, it's necessary to first + * convert the keyboard state into an effective group and level. This is done via a + * set of rules that varies widely according to type of keyboard and user + * configuration. The function gdk_keymap_translate_keyboard_state() accepts a + * keyboard state -- consisting of hardware keycode pressed, active modifiers, and + * active group -- applies the appropriate rules, and returns the group/level to be + * used to index the keymap, along with the modifiers which did not affect the + * group and level. i.e. it returns "unconsumed modifiers." The keyboard group may + * differ from the effective group used for keymap lookups because some keys don't + * have multiple groups - e.g. the Enter key is always in group 0 regardless of + * keyboard state. + * + * Note that gdk_keymap_translate_keyboard_state() also returns the keyval, i.e. it + * goes ahead and performs the keymap lookup in addition to telling you which + * effective group/level values were used for the lookup. #GdkEventKey already + * contains this keyval, however, so you don't normally need to call + * gdk_keymap_translate_keyboard_state() just to get the keyval. + */ + enum { DIRECTION_CHANGED, @@ -112,12 +183,6 @@ gdk_keymap_init (GdkKeymap *keymap) /* Other key-handling stuff */ -#ifndef HAVE_XCONVERTCASE -#include "gdkkeysyms.h" - -/* compatibility function from X11R6.3, since XConvertCase is not - * supplied by X11R5. - */ /** * gdk_keyval_convert_case: * @symbol: a keyval @@ -125,135 +190,27 @@ gdk_keymap_init (GdkKeymap *keymap) * @upper: (out): return location for uppercase version of @symbol * * Obtains the upper- and lower-case versions of the keyval @symbol. - * Examples of keyvals are #GDK_a, #GDK_Enter, #GDK_F1, etc. - * - **/ + * Examples of keyvals are #GDK_KEY_a, #GDK_KEY_Enter, #GDK_KEY_F1, etc. + */ void gdk_keyval_convert_case (guint symbol, - guint *lower, - guint *upper) + guint *lower, + guint *upper) { - guint xlower = symbol; - guint xupper = symbol; + GdkDisplayManager *manager = gdk_display_manager_get (); - /* Check for directly encoded 24-bit UCS characters: */ - if ((symbol & 0xff000000) == 0x01000000) - { - if (lower) - *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff)); - if (upper) - *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff)); - return; - } - - switch (symbol >> 8) - { - case 0: /* Latin 1 */ - if ((symbol >= GDK_A) && (symbol <= GDK_Z)) - xlower += (GDK_a - GDK_A); - else if ((symbol >= GDK_a) && (symbol <= GDK_z)) - xupper -= (GDK_a - GDK_A); - else if ((symbol >= GDK_Agrave) && (symbol <= GDK_Odiaeresis)) - xlower += (GDK_agrave - GDK_Agrave); - else if ((symbol >= GDK_agrave) && (symbol <= GDK_odiaeresis)) - xupper -= (GDK_agrave - GDK_Agrave); - else if ((symbol >= GDK_Ooblique) && (symbol <= GDK_Thorn)) - xlower += (GDK_oslash - GDK_Ooblique); - else if ((symbol >= GDK_oslash) && (symbol <= GDK_thorn)) - xupper -= (GDK_oslash - GDK_Ooblique); - break; - - case 1: /* Latin 2 */ - /* Assume the KeySym is a legal value (ignore discontinuities) */ - if (symbol == GDK_Aogonek) - xlower = GDK_aogonek; - else if (symbol >= GDK_Lstroke && symbol <= GDK_Sacute) - xlower += (GDK_lstroke - GDK_Lstroke); - else if (symbol >= GDK_Scaron && symbol <= GDK_Zacute) - xlower += (GDK_scaron - GDK_Scaron); - else if (symbol >= GDK_Zcaron && symbol <= GDK_Zabovedot) - xlower += (GDK_zcaron - GDK_Zcaron); - else if (symbol == GDK_aogonek) - xupper = GDK_Aogonek; - else if (symbol >= GDK_lstroke && symbol <= GDK_sacute) - xupper -= (GDK_lstroke - GDK_Lstroke); - else if (symbol >= GDK_scaron && symbol <= GDK_zacute) - xupper -= (GDK_scaron - GDK_Scaron); - else if (symbol >= GDK_zcaron && symbol <= GDK_zabovedot) - xupper -= (GDK_zcaron - GDK_Zcaron); - else if (symbol >= GDK_Racute && symbol <= GDK_Tcedilla) - xlower += (GDK_racute - GDK_Racute); - else if (symbol >= GDK_racute && symbol <= GDK_tcedilla) - xupper -= (GDK_racute - GDK_Racute); - break; - - case 2: /* Latin 3 */ - /* Assume the KeySym is a legal value (ignore discontinuities) */ - if (symbol >= GDK_Hstroke && symbol <= GDK_Hcircumflex) - xlower += (GDK_hstroke - GDK_Hstroke); - else if (symbol >= GDK_Gbreve && symbol <= GDK_Jcircumflex) - xlower += (GDK_gbreve - GDK_Gbreve); - else if (symbol >= GDK_hstroke && symbol <= GDK_hcircumflex) - xupper -= (GDK_hstroke - GDK_Hstroke); - else if (symbol >= GDK_gbreve && symbol <= GDK_jcircumflex) - xupper -= (GDK_gbreve - GDK_Gbreve); - else if (symbol >= GDK_Cabovedot && symbol <= GDK_Scircumflex) - xlower += (GDK_cabovedot - GDK_Cabovedot); - else if (symbol >= GDK_cabovedot && symbol <= GDK_scircumflex) - xupper -= (GDK_cabovedot - GDK_Cabovedot); - break; - - case 3: /* Latin 4 */ - /* Assume the KeySym is a legal value (ignore discontinuities) */ - if (symbol >= GDK_Rcedilla && symbol <= GDK_Tslash) - xlower += (GDK_rcedilla - GDK_Rcedilla); - else if (symbol >= GDK_rcedilla && symbol <= GDK_tslash) - xupper -= (GDK_rcedilla - GDK_Rcedilla); - else if (symbol == GDK_ENG) - xlower = GDK_eng; - else if (symbol == GDK_eng) - xupper = GDK_ENG; - else if (symbol >= GDK_Amacron && symbol <= GDK_Umacron) - xlower += (GDK_amacron - GDK_Amacron); - else if (symbol >= GDK_amacron && symbol <= GDK_umacron) - xupper -= (GDK_amacron - GDK_Amacron); - break; - - case 6: /* Cyrillic */ - /* Assume the KeySym is a legal value (ignore discontinuities) */ - if (symbol >= GDK_Serbian_DJE && symbol <= GDK_Serbian_DZE) - xlower -= (GDK_Serbian_DJE - GDK_Serbian_dje); - else if (symbol >= GDK_Serbian_dje && symbol <= GDK_Serbian_dze) - xupper += (GDK_Serbian_DJE - GDK_Serbian_dje); - else if (symbol >= GDK_Cyrillic_YU && symbol <= GDK_Cyrillic_HARDSIGN) - xlower -= (GDK_Cyrillic_YU - GDK_Cyrillic_yu); - else if (symbol >= GDK_Cyrillic_yu && symbol <= GDK_Cyrillic_hardsign) - xupper += (GDK_Cyrillic_YU - GDK_Cyrillic_yu); - break; - - case 7: /* Greek */ - /* Assume the KeySym is a legal value (ignore discontinuities) */ - if (symbol >= GDK_Greek_ALPHAaccent && symbol <= GDK_Greek_OMEGAaccent) - xlower += (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent); - else if (symbol >= GDK_Greek_alphaaccent && symbol <= GDK_Greek_omegaaccent && - symbol != GDK_Greek_iotaaccentdieresis && - symbol != GDK_Greek_upsilonaccentdieresis) - xupper -= (GDK_Greek_alphaaccent - GDK_Greek_ALPHAaccent); - else if (symbol >= GDK_Greek_ALPHA && symbol <= GDK_Greek_OMEGA) - xlower += (GDK_Greek_alpha - GDK_Greek_ALPHA); - else if (symbol >= GDK_Greek_alpha && symbol <= GDK_Greek_omega && - symbol != GDK_Greek_finalsmallsigma) - xupper -= (GDK_Greek_alpha - GDK_Greek_ALPHA); - break; - } - - if (lower) - *lower = xlower; - if (upper) - *upper = xupper; + GDK_DISPLAY_MANAGER_GET_CLASS (manager)->keyval_convert_case (manager, symbol, lower, upper); } -#endif +/** + * gdk_keyval_to_upper: + * @keyval: a key value. + * + * Converts a key value to upper case, if applicable. + * + * Returns: the upper case form of @keyval, or @keyval itself if it is already + * in upper case or it is not subject to case conversion. + */ guint gdk_keyval_to_upper (guint keyval) { @@ -264,6 +221,15 @@ gdk_keyval_to_upper (guint keyval) return result; } +/** + * gdk_keyval_to_lower: + * @keyval: a key value. + * + * Converts a key value to lower case, if applicable. + * + * Returns: the lower case form of @keyval, or @keyval itself if it is already + * in lower case or it is not subject to case conversion. + */ guint gdk_keyval_to_lower (guint keyval) { @@ -274,6 +240,15 @@ gdk_keyval_to_lower (guint keyval) return result; } +/** + * gdk_keyval_is_upper: + * @keyval: a key value. + * + * Returns %TRUE if the given key value is in upper case. + * + * Returns: %TRUE if @keyval is in upper case, or if @keyval is not subject to + * case conversion. + */ gboolean gdk_keyval_is_upper (guint keyval) { @@ -287,6 +262,15 @@ gdk_keyval_is_upper (guint keyval) return FALSE; } +/** + * gdk_keyval_is_lower: + * @keyval: a key value. + * + * Returns %TRUE if the given key value is in lower case. + * + * Returns: %TRUE if @keyval is in lower case, or if @keyval is not + * subject to case conversion. + */ gboolean gdk_keyval_is_lower (guint keyval) { @@ -302,15 +286,323 @@ gdk_keyval_is_lower (guint keyval) /** * gdk_keymap_get_default: - * @returns: the #GdkKeymap attached to the default display. * * Returns the #GdkKeymap attached to the default display. - **/ + * + * Returns: (transfer none): the #GdkKeymap attached to the default display. + */ GdkKeymap* gdk_keymap_get_default (void) { return gdk_keymap_get_for_display (gdk_display_get_default ()); } -#define __GDK_KEYS_C__ -#include "gdkaliasdef.c" +/** + * gdk_keymap_get_direction: + * @keymap: a #GdkKeymap or %NULL to use the default keymap + * + * Returns the direction of effective layout of the keymap. + * + * Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL + * if it can determine the direction. %PANGO_DIRECTION_NEUTRAL + * otherwise. + **/ +PangoDirection +gdk_keymap_get_direction (GdkKeymap *keymap) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->get_direction (keymap); +} + +/** + * gdk_keymap_have_bidi_layouts: + * @keymap: a #GdkKeymap or %NULL to use the default keymap + * + * Determines if keyboard layouts for both right-to-left and left-to-right + * languages are in use. + * + * Returns: %TRUE if there are layouts in both directions, %FALSE otherwise + * + * Since: 2.12 + **/ +gboolean +gdk_keymap_have_bidi_layouts (GdkKeymap *keymap) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->have_bidi_layouts (keymap); +} + +/** + * gdk_keymap_get_caps_lock_state: + * @keymap: a #GdkKeymap + * + * Returns whether the Caps Lock modifer is locked. + * + * Returns: %TRUE if Caps Lock is on + * + * Since: 2.16 + */ +gboolean +gdk_keymap_get_caps_lock_state (GdkKeymap *keymap) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->get_caps_lock_state (keymap); +} + +/** + * gdk_keymap_get_num_lock_state: + * @keymap: a #GdkKeymap + * + * Returns whether the Num Lock modifer is locked. + * + * Returns: %TRUE if Num Lock is on + * + * Since: 3.0 + */ +gboolean +gdk_keymap_get_num_lock_state (GdkKeymap *keymap) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->get_num_lock_state (keymap); +} + +/** + * gdk_keymap_get_entries_for_keyval: + * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default keymap + * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc. + * @keys: (out): return location for an array of #GdkKeymapKey + * @n_keys: (out): return location for number of elements in returned array + * + * Obtains a list of keycode/group/level combinations that will + * generate @keyval. Groups and levels are two kinds of keyboard mode; + * in general, the level determines whether the top or bottom symbol + * on a key is used, and the group determines whether the left or + * right symbol is used. On US keyboards, the shift key changes the + * keyboard level, and there are no groups. A group switch key might + * convert a keyboard between Hebrew to English modes, for example. + * #GdkEventKey contains a %group field that indicates the active + * keyboard group. The level is computed from the modifier mask. + * The returned array should be freed + * with g_free(). + * + * Return value: %TRUE if keys were found and returned + **/ +gboolean +gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap, + guint keyval, + GdkKeymapKey **keys, + gint *n_keys) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->get_entries_for_keyval (keymap, keyval, keys, n_keys); +} + +/** + * gdk_keymap_get_entries_for_keycode: + * @keymap: (allow-none): a #GdkKeymap or %NULL to use the default keymap + * @hardware_keycode: a keycode + * @keys: (out): return location for array of #GdkKeymapKey, or %NULL + * @keyvals: (out): return location for array of keyvals, or %NULL + * @n_entries: length of @keys and @keyvals + * + * Returns the keyvals bound to @hardware_keycode. + * The Nth #GdkKeymapKey in @keys is bound to the Nth + * keyval in @keyvals. Free the returned arrays with g_free(). + * When a keycode is pressed by the user, the keyval from + * this list of entries is selected by considering the effective + * keyboard group and level. See gdk_keymap_translate_keyboard_state(). + * + * Returns: %TRUE if there were any entries + **/ +gboolean +gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap, + guint hardware_keycode, + GdkKeymapKey **keys, + guint **keyvals, + gint *n_entries) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->get_entries_for_keycode (keymap, hardware_keycode, keys, keyvals, n_entries); +} + +/** + * gdk_keymap_lookup_key: + * @keymap: a #GdkKeymap or %NULL to use the default keymap + * @key: a #GdkKeymapKey with keycode, group, and level initialized + * + * Looks up the keyval mapped to a keycode/group/level triplet. + * If no keyval is bound to @key, returns 0. For normal user input, + * you want to use gdk_keymap_translate_keyboard_state() instead of + * this function, since the effective group/level may not be + * the same as the current keyboard state. + * + * Return value: a keyval, or 0 if none was mapped to the given @key + **/ +guint +gdk_keymap_lookup_key (GdkKeymap *keymap, + const GdkKeymapKey *key) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->lookup_key (keymap, key); +} + +/** + * gdk_keymap_translate_keyboard_state: + * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default + * @hardware_keycode: a keycode + * @state: a modifier state + * @group: active keyboard group + * @keyval: (out) (allow-none): return location for keyval, or %NULL + * @effective_group: (out) (allow-none): return location for effective group, or %NULL + * @level: (out) (allow-none): return location for level, or %NULL + * @consumed_modifiers: (out) (allow-none): return location for modifiers that were used to + * determine the group or level, or %NULL + * + * Translates the contents of a #GdkEventKey into a keyval, effective + * group, and level. Modifiers that affected the translation and + * are thus unavailable for application use are returned in + * @consumed_modifiers. See for an explanation of + * groups and levels. The @effective_group is the group that was + * actually used for the translation; some keys such as Enter are not + * affected by the active keyboard group. The @level is derived from + * @state. For convenience, #GdkEventKey already contains the translated + * keyval, so this function isn't as useful as you might think. + * + * + * @consumed_modifiers gives modifiers that should be masked out + * from @state when comparing this key press to a hot key. For + * instance, on a US keyboard, the plus + * symbol is shifted, so when comparing a key press to a + * <Control>plus accelerator <Shift> should + * be masked out. + * + * + * /* We want to ignore irrelevant modifiers like ScrollLock */ + * #define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK) + * gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode, + * event->state, event->group, + * &keyval, NULL, NULL, &consumed); + * if (keyval == GDK_PLUS && + * (event->state & ~consumed & ALL_ACCELS_MASK) == GDK_CONTROL_MASK) + * /* Control was pressed */ + * + * + * An older interpretation @consumed_modifiers was that it contained + * all modifiers that might affect the translation of the key; + * this allowed accelerators to be stored with irrelevant consumed + * modifiers, by doing: + * + * /* XXX Don't do this XXX */ + * if (keyval == accel_keyval && + * (event->state & ~consumed & ALL_ACCELS_MASK) == (accel_mods & ~consumed)) + * /* Accelerator was pressed */ + * + * + * However, this did not work if multi-modifier combinations were + * used in the keymap, since, for instance, <Control> + * would be masked out even if only <Control><Alt> + * was used in the keymap. To support this usage as well as well as + * possible, all single modifier combinations + * that could affect the key for any combination of modifiers will + * be returned in @consumed_modifiers; multi-modifier combinations + * are returned only when actually found in @state. When you store + * accelerators, you should always store them with consumed modifiers + * removed. Store <Control>plus, + * not <Control><Shift>plus, + * + * + * Return value: %TRUE if there was a keyval bound to the keycode/state/group + **/ +gboolean +gdk_keymap_translate_keyboard_state (GdkKeymap *keymap, + guint hardware_keycode, + GdkModifierType state, + gint group, + guint *keyval, + gint *effective_group, + gint *level, + GdkModifierType *consumed_modifiers) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->translate_keyboard_state (keymap, + hardware_keycode, + state, + group, + keyval, + effective_group, + level, + consumed_modifiers); +} + +/** + * gdk_keymap_add_virtual_modifiers: + * @keymap: a #GdkKeymap + * @state: pointer to the modifier mask to change + * + * Adds virtual modifiers (i.e. Super, Hyper and Meta) which correspond + * to the real modifiers (i.e Mod2, Mod3, ...) in @modifiers. + * are set in @state to their non-virtual counterparts (i.e. Mod2, + * Mod3,...) and set the corresponding bits in @state. + * + * GDK already does this before delivering key events, but for + * compatibility reasons, it only sets the first virtual modifier + * it finds, whereas this function sets all matching virtual modifiers. + * + * This function is useful when matching key events against + * accelerators. + * + * Since: 2.20 + */ +void +gdk_keymap_add_virtual_modifiers (GdkKeymap *keymap, + GdkModifierType *state) +{ + GDK_KEYMAP_GET_CLASS(keymap)->add_virtual_modifiers (keymap, state); +} + +/** + * gdk_keymap_map_virtual_modifiers: + * @keymap: a #GdkKeymap + * @state: pointer to the modifier state to map + * + * Maps the virtual modifiers (i.e. Super, Hyper and Meta) which + * are set in @state to their non-virtual counterparts (i.e. Mod2, + * Mod3,...) and set the corresponding bits in @state. + * + * This function is useful when matching key events against + * accelerators. + * + * Returns: %TRUE if no virtual modifiers were mapped to the + * same non-virtual modifier. Note that %FALSE is also returned + * if a virtual modifier is mapped to a non-virtual modifier that + * was already set in @state. + * + * Since: 2.20 + */ +gboolean +gdk_keymap_map_virtual_modifiers (GdkKeymap *keymap, + GdkModifierType *state) +{ + return GDK_KEYMAP_GET_CLASS(keymap)->map_virtual_modifiers (keymap, state); +} + +/** + * gdk_keyval_name: + * @keyval: a key value. + * + * Converts a key value into a symbolic name. + * The names are the same as those in the + * <gdk/gdkkeysyms.h> header file + * but without the leading "GDK_KEY_". + * + * Return value: (transfer none): a string containing the name of the key, + * or %NULL if @keyval is not a valid key. The string should not be + * modified. + */ +gchar* +gdk_keyval_name (guint keyval) +{ + GdkDisplayManager *manager = gdk_display_manager_get (); + + return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->get_keyval_name (manager, keyval); +} + +guint +gdk_keyval_from_name (const gchar *keyval_name) +{ + GdkDisplayManager *manager = gdk_display_manager_get (); + + return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->lookup_keyval (manager, keyval_name); +}