]> Pileus Git - ~andy/gtk/blob - gdk/gdkkeys.c
bd3f7dd7a906fbe7a7962b81bd626b01dcdf623d
[~andy/gtk] / gdk / gdkkeys.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27 #include "config.h"
28
29 #include "gdkkeysyms.h"
30 #include "gdkkeysprivate.h"
31 #include "gdkdisplay.h"
32 #include "gdkdisplaymanagerprivate.h"
33
34
35 /**
36  * SECTION:keys
37  * @Short_description: Functions for manipulating keyboard codes
38  * @Title: Key Values
39  *
40  * Key values are the codes which are sent whenever a key is pressed or released.
41  * They appear in the #GdkEventKey.keyval field of the
42  * #GdkEventKey structure, which is passed to signal handlers for the
43  * #GtkWidget::key-press-event and #GtkWidget::key-release-event signals.
44  * The complete list of key values can be found in the
45  * <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file.
46  *
47  * Key values are regularly updated from the upstream X.org X11 implementation,
48  * so new values are added regularly. They will be prefixed with GDK_KEY_ rather
49  * than XF86XK_ or XK_ (for older symbols).
50  *
51  * Key values can be converted into a string representation using
52  * gdk_keyval_name(). The reverse function, converting a string to a key value,
53  * is provided by gdk_keyval_from_name().
54  *
55  * The case of key values can be determined using gdk_keyval_is_upper() and
56  * gdk_keyval_is_lower(). Key values can be converted to upper or lower case
57  * using gdk_keyval_to_upper() and gdk_keyval_to_lower().
58  *
59  * When it makes sense, key values can be converted to and from
60  * Unicode characters with gdk_keyval_to_unicode() and gdk_unicode_to_keyval().
61  *
62  * <para id="key-group-explanation">
63  * One #GdkKeymap object exists for each user display. gdk_keymap_get_default()
64  * returns the #GdkKeymap for the default display; to obtain keymaps for other
65  * displays, use gdk_keymap_get_for_display(). A keymap
66  * is a mapping from #GdkKeymapKey to key values. You can think of a #GdkKeymapKey
67  * as a representation of a symbol printed on a physical keyboard key. That is, it
68  * contains three pieces of information. First, it contains the hardware keycode;
69  * this is an identifying number for a physical key. Second, it contains the
70  * <firstterm>level</firstterm> of the key. The level indicates which symbol on the
71  * key will be used, in a vertical direction. So on a standard US keyboard, the key
72  * with the number "1" on it also has the exclamation point ("!") character on
73  * it. The level indicates whether to use the "1" or the "!" symbol.  The letter
74  * keys are considered to have a lowercase letter at level 0, and an uppercase
75  * letter at level 1, though only the uppercase letter is printed.  Third, the
76  * #GdkKeymapKey contains a group; groups are not used on standard US keyboards,
77  * but are used in many other countries. On a keyboard with groups, there can be 3
78  * or 4 symbols printed on a single key. The group indicates movement in a
79  * horizontal direction. Usually groups are used for two different languages.  In
80  * group 0, a key might have two English characters, and in group 1 it might have
81  * two Hebrew characters. The Hebrew characters will be printed on the key next to
82  * the English characters.
83  * </para>
84  *
85  * In order to use a keymap to interpret a key event, it's necessary to first
86  * convert the keyboard state into an effective group and level. This is done via a
87  * set of rules that varies widely according to type of keyboard and user
88  * configuration. The function gdk_keymap_translate_keyboard_state() accepts a
89  * keyboard state -- consisting of hardware keycode pressed, active modifiers, and
90  * active group -- applies the appropriate rules, and returns the group/level to be
91  * used to index the keymap, along with the modifiers which did not affect the
92  * group and level. i.e. it returns "unconsumed modifiers." The keyboard group may
93  * differ from the effective group used for keymap lookups because some keys don't
94  * have multiple groups - e.g. the Enter key is always in group 0 regardless of
95  * keyboard state.
96  *
97  * Note that gdk_keymap_translate_keyboard_state() also returns the keyval, i.e. it
98  * goes ahead and performs the keymap lookup in addition to telling you which
99  * effective group/level values were used for the lookup. #GdkEventKey already
100  * contains this keyval, however, so you don't normally need to call
101  * gdk_keymap_translate_keyboard_state() just to get the keyval.
102  */
103
104
105 enum {
106   DIRECTION_CHANGED,
107   KEYS_CHANGED,
108   STATE_CHANGED,
109   LAST_SIGNAL
110 };
111
112
113 static GdkModifierType gdk_keymap_real_get_modifier_mask (GdkKeymap         *keymap,
114                                                           GdkModifierIntent  intent);
115
116
117 static guint signals[LAST_SIGNAL] = { 0 };
118
119 G_DEFINE_TYPE (GdkKeymap, gdk_keymap, G_TYPE_OBJECT)
120
121 static void
122 gdk_keymap_class_init (GdkKeymapClass *klass)
123 {
124   GObjectClass *object_class = G_OBJECT_CLASS (klass);
125
126   klass->get_modifier_mask = gdk_keymap_real_get_modifier_mask;
127
128   /**
129    * GdkKeymap::direction-changed:
130    * @keymap: the object on which the signal is emitted
131    *
132    * The ::direction-changed signal gets emitted when the direction of
133    * the keymap changes.
134    *
135    * Since: 2.0
136    */
137   signals[DIRECTION_CHANGED] =
138     g_signal_new ("direction-changed",
139                   G_OBJECT_CLASS_TYPE (object_class),
140                   G_SIGNAL_RUN_LAST,
141                   G_STRUCT_OFFSET (GdkKeymapClass, direction_changed),
142                   NULL, NULL,
143                   g_cclosure_marshal_VOID__VOID,
144                   G_TYPE_NONE,
145                   0);
146   /**
147    * GdkKeymap::keys-changed:
148    * @keymap: the object on which the signal is emitted
149    *
150    * The ::keys-changed signal is emitted when the mapping represented by
151    * @keymap changes.
152    *
153    * Since: 2.2
154    */
155   signals[KEYS_CHANGED] =
156     g_signal_new ("keys-changed",
157                   G_OBJECT_CLASS_TYPE (object_class),
158                   G_SIGNAL_RUN_LAST,
159                   G_STRUCT_OFFSET (GdkKeymapClass, keys_changed),
160                   NULL, NULL,
161                   g_cclosure_marshal_VOID__VOID,
162                   G_TYPE_NONE,
163                   0);
164
165   /**
166    * GdkKeymap::state-changed:
167    * @keymap: the object on which the signal is emitted
168    *
169    * The ::state-changed signal is emitted when the state of the
170    * keyboard changes, e.g when Caps Lock is turned on or off.
171    * See gdk_keymap_get_caps_lock_state().
172    *
173    * Since: 2.16
174    */
175   signals[STATE_CHANGED] =
176     g_signal_new ("state_changed",
177                   G_OBJECT_CLASS_TYPE (object_class),
178                   G_SIGNAL_RUN_LAST,
179                   G_STRUCT_OFFSET (GdkKeymapClass, state_changed),
180                   NULL, NULL,
181                   g_cclosure_marshal_VOID__VOID,
182                   G_TYPE_NONE,
183                   0);
184 }
185
186 static void
187 gdk_keymap_init (GdkKeymap *keymap)
188 {
189 }
190
191 /* Other key-handling stuff
192  */
193
194 /**
195  * gdk_keyval_convert_case:
196  * @symbol: a keyval
197  * @lower: (out): return location for lowercase version of @symbol
198  * @upper: (out): return location for uppercase version of @symbol
199  *
200  * Obtains the upper- and lower-case versions of the keyval @symbol.
201  * Examples of keyvals are #GDK_KEY_a, #GDK_KEY_Enter, #GDK_KEY_F1, etc.
202  */
203 void
204 gdk_keyval_convert_case (guint symbol,
205                          guint *lower,
206                          guint *upper)
207 {
208   GdkDisplayManager *manager = gdk_display_manager_get ();
209
210   GDK_DISPLAY_MANAGER_GET_CLASS (manager)->keyval_convert_case (manager, symbol, lower, upper);
211 }
212
213 /**
214  * gdk_keyval_to_upper:
215  * @keyval: a key value.
216  *
217  * Converts a key value to upper case, if applicable.
218  *
219  * Returns: the upper case form of @keyval, or @keyval itself if it is already
220  *   in upper case or it is not subject to case conversion.
221  */
222 guint
223 gdk_keyval_to_upper (guint keyval)
224 {
225   guint result;
226
227   gdk_keyval_convert_case (keyval, NULL, &result);
228
229   return result;
230 }
231
232 /**
233  * gdk_keyval_to_lower:
234  * @keyval: a key value.
235  *
236  * Converts a key value to lower case, if applicable.
237  *
238  * Returns: the lower case form of @keyval, or @keyval itself if it is already
239  *  in lower case or it is not subject to case conversion.
240  */
241 guint
242 gdk_keyval_to_lower (guint keyval)
243 {
244   guint result;
245
246   gdk_keyval_convert_case (keyval, &result, NULL);
247
248   return result;
249 }
250
251 /**
252  * gdk_keyval_is_upper:
253  * @keyval: a key value.
254  *
255  * Returns %TRUE if the given key value is in upper case.
256  *
257  * Returns: %TRUE if @keyval is in upper case, or if @keyval is not subject to
258  *  case conversion.
259  */
260 gboolean
261 gdk_keyval_is_upper (guint keyval)
262 {
263   if (keyval)
264     {
265       guint upper_val = 0;
266
267       gdk_keyval_convert_case (keyval, NULL, &upper_val);
268       return upper_val == keyval;
269     }
270   return FALSE;
271 }
272
273 /**
274  * gdk_keyval_is_lower:
275  * @keyval: a key value.
276  *
277  * Returns %TRUE if the given key value is in lower case.
278  *
279  * Returns: %TRUE if @keyval is in lower case, or if @keyval is not
280  *   subject to case conversion.
281  */
282 gboolean
283 gdk_keyval_is_lower (guint keyval)
284 {
285   if (keyval)
286     {
287       guint lower_val = 0;
288
289       gdk_keyval_convert_case (keyval, &lower_val, NULL);
290       return lower_val == keyval;
291     }
292   return FALSE;
293 }
294
295 /**
296  * gdk_keymap_get_default:
297  *
298  * Returns the #GdkKeymap attached to the default display.
299  *
300  * Returns: (transfer none): the #GdkKeymap attached to the default display.
301  */
302 GdkKeymap*
303 gdk_keymap_get_default (void)
304 {
305   return gdk_keymap_get_for_display (gdk_display_get_default ());
306 }
307
308 /**
309  * gdk_keymap_get_direction:
310  * @keymap: a #GdkKeymap
311  *
312  * Returns the direction of effective layout of the keymap.
313  *
314  * Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL
315  *   if it can determine the direction. %PANGO_DIRECTION_NEUTRAL
316  *   otherwise.
317  **/
318 PangoDirection
319 gdk_keymap_get_direction (GdkKeymap *keymap)
320 {
321   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), PANGO_DIRECTION_LTR);
322
323   return GDK_KEYMAP_GET_CLASS (keymap)->get_direction (keymap);
324 }
325
326 /**
327  * gdk_keymap_have_bidi_layouts:
328  * @keymap: a #GdkKeymap
329  *
330  * Determines if keyboard layouts for both right-to-left and left-to-right
331  * languages are in use.
332  *
333  * Returns: %TRUE if there are layouts in both directions, %FALSE otherwise
334  *
335  * Since: 2.12
336  **/
337 gboolean
338 gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
339 {
340   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
341
342   return GDK_KEYMAP_GET_CLASS (keymap)->have_bidi_layouts (keymap);
343 }
344
345 /**
346  * gdk_keymap_get_caps_lock_state:
347  * @keymap: a #GdkKeymap
348  *
349  * Returns whether the Caps Lock modifer is locked.
350  *
351  * Returns: %TRUE if Caps Lock is on
352  *
353  * Since: 2.16
354  */
355 gboolean
356 gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
357 {
358   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
359
360   return GDK_KEYMAP_GET_CLASS (keymap)->get_caps_lock_state (keymap);
361 }
362
363 /**
364  * gdk_keymap_get_num_lock_state:
365  * @keymap: a #GdkKeymap
366  *
367  * Returns whether the Num Lock modifer is locked.
368  *
369  * Returns: %TRUE if Num Lock is on
370  *
371  * Since: 3.0
372  */
373 gboolean
374 gdk_keymap_get_num_lock_state (GdkKeymap *keymap)
375 {
376   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
377
378   return GDK_KEYMAP_GET_CLASS (keymap)->get_num_lock_state (keymap);
379 }
380
381 /**
382  * gdk_keymap_get_entries_for_keyval:
383  * @keymap: a #GdkKeymap
384  * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
385  * @keys: (out) (array length=n_keys) (transfer full): return location
386  *     for an array of #GdkKeymapKey
387  * @n_keys: return location for number of elements in returned array
388  *
389  * Obtains a list of keycode/group/level combinations that will
390  * generate @keyval. Groups and levels are two kinds of keyboard mode;
391  * in general, the level determines whether the top or bottom symbol
392  * on a key is used, and the group determines whether the left or
393  * right symbol is used. On US keyboards, the shift key changes the
394  * keyboard level, and there are no groups. A group switch key might
395  * convert a keyboard between Hebrew to English modes, for example.
396  * #GdkEventKey contains a %group field that indicates the active
397  * keyboard group. The level is computed from the modifier mask.
398  * The returned array should be freed
399  * with g_free().
400  *
401  * Return value: %TRUE if keys were found and returned
402  **/
403 gboolean
404 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
405                                    guint          keyval,
406                                    GdkKeymapKey **keys,
407                                    gint          *n_keys)
408 {
409   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
410
411   return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keyval (keymap, keyval,
412                                                                 keys, n_keys);
413 }
414
415 /**
416  * gdk_keymap_get_entries_for_keycode:
417  * @keymap: a #GdkKeymap
418  * @hardware_keycode: a keycode
419  * @keys: (out) (array length=n_entries) (transfer full): return
420  *     location for array of #GdkKeymapKey, or %NULL
421  * @keyvals: (out) (array length=n_entries) (transfer full): return
422  *     location for array of keyvals, or %NULL
423  * @n_entries: length of @keys and @keyvals
424  *
425  * Returns the keyvals bound to @hardware_keycode.
426  * The Nth #GdkKeymapKey in @keys is bound to the Nth
427  * keyval in @keyvals. Free the returned arrays with g_free().
428  * When a keycode is pressed by the user, the keyval from
429  * this list of entries is selected by considering the effective
430  * keyboard group and level. See gdk_keymap_translate_keyboard_state().
431  *
432  * Returns: %TRUE if there were any entries
433  **/
434 gboolean
435 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
436                                     guint          hardware_keycode,
437                                     GdkKeymapKey **keys,
438                                     guint        **keyvals,
439                                     gint          *n_entries)
440 {
441   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
442
443   return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keycode (keymap, hardware_keycode,
444                                                                  keys, keyvals, n_entries);
445 }
446
447 /**
448  * gdk_keymap_lookup_key:
449  * @keymap: a #GdkKeymap
450  * @key: a #GdkKeymapKey with keycode, group, and level initialized
451  *
452  * Looks up the keyval mapped to a keycode/group/level triplet.
453  * If no keyval is bound to @key, returns 0. For normal user input,
454  * you want to use gdk_keymap_translate_keyboard_state() instead of
455  * this function, since the effective group/level may not be
456  * the same as the current keyboard state.
457  *
458  * Return value: a keyval, or 0 if none was mapped to the given @key
459  **/
460 guint
461 gdk_keymap_lookup_key (GdkKeymap          *keymap,
462                        const GdkKeymapKey *key)
463 {
464   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
465
466   return GDK_KEYMAP_GET_CLASS (keymap)->lookup_key (keymap, key);
467 }
468
469 /**
470  * gdk_keymap_translate_keyboard_state:
471  * @keymap: a #GdkKeymap
472  * @hardware_keycode: a keycode
473  * @state: a modifier state
474  * @group: active keyboard group
475  * @keyval: (out) (allow-none): return location for keyval, or %NULL
476  * @effective_group: (out) (allow-none): return location for effective
477  *     group, or %NULL
478  * @level: (out) (allow-none): return location for level, or %NULL
479  * @consumed_modifiers: (out) (allow-none): return location for modifiers
480  *     that were used to determine the group or level, or %NULL
481  *
482  * Translates the contents of a #GdkEventKey into a keyval, effective
483  * group, and level. Modifiers that affected the translation and
484  * are thus unavailable for application use are returned in
485  * @consumed_modifiers.
486  * See <xref linkend="key-group-explanation"/> for an explanation of
487  * groups and levels. The @effective_group is the group that was
488  * actually used for the translation; some keys such as Enter are not
489  * affected by the active keyboard group. The @level is derived from
490  * @state. For convenience, #GdkEventKey already contains the translated
491  * keyval, so this function isn't as useful as you might think.
492  *
493  * <note><para>
494  * @consumed_modifiers gives modifiers that should be masked out
495  * from @state when comparing this key press to a hot key. For
496  * instance, on a US keyboard, the <literal>plus</literal>
497  * symbol is shifted, so when comparing a key press to a
498  * <literal>&lt;Control&gt;plus</literal> accelerator &lt;Shift&gt; should
499  * be masked out.
500  * </para>
501  * <informalexample><programlisting>
502  * &sol;* We want to ignore irrelevant modifiers like ScrollLock *&sol;
503  * &num;define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)
504  * gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
505  *                                      event->state, event->group,
506  *                                      &amp;keyval, NULL, NULL, &amp;consumed);
507  * if (keyval == GDK_PLUS &&
508  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
509  *   &sol;* Control was pressed *&sol;
510  * </programlisting></informalexample>
511  * <para>
512  * An older interpretation @consumed_modifiers was that it contained
513  * all modifiers that might affect the translation of the key;
514  * this allowed accelerators to be stored with irrelevant consumed
515  * modifiers, by doing:</para>
516  * <informalexample><programlisting>
517  * &sol;* XXX Don't do this XXX *&sol;
518  * if (keyval == accel_keyval &&
519  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == (accel_mods &amp; ~consumed))
520  *   &sol;* Accelerator was pressed *&sol;
521  * </programlisting></informalexample>
522  * <para>
523  * However, this did not work if multi-modifier combinations were
524  * used in the keymap, since, for instance, <literal>&lt;Control&gt;</literal>
525  * would be masked out even if only <literal>&lt;Control&gt;&lt;Alt&gt;</literal>
526  * was used in the keymap. To support this usage as well as well as
527  * possible, all <emphasis>single modifier</emphasis> combinations
528  * that could affect the key for any combination of modifiers will
529  * be returned in @consumed_modifiers; multi-modifier combinations
530  * are returned only when actually found in @state. When you store
531  * accelerators, you should always store them with consumed modifiers
532  * removed. Store <literal>&lt;Control&gt;plus</literal>,
533  * not <literal>&lt;Control&gt;&lt;Shift&gt;plus</literal>,
534  * </para></note>
535  *
536  * Return value: %TRUE if there was a keyval bound to the keycode/state/group
537  **/
538 gboolean
539 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
540                                      guint            hardware_keycode,
541                                      GdkModifierType  state,
542                                      gint             group,
543                                      guint           *keyval,
544                                      gint            *effective_group,
545                                      gint            *level,
546                                      GdkModifierType *consumed_modifiers)
547 {
548   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
549
550   return GDK_KEYMAP_GET_CLASS (keymap)->translate_keyboard_state (keymap,
551                                                                   hardware_keycode,
552                                                                   state,
553                                                                   group,
554                                                                   keyval,
555                                                                   effective_group,
556                                                                   level,
557                                                                   consumed_modifiers);
558 }
559
560 /**
561  * gdk_keymap_add_virtual_modifiers:
562  * @keymap: a #GdkKeymap
563  * @state: (out): pointer to the modifier mask to change
564  *
565  * Adds virtual modifiers (i.e. Super, Hyper and Meta) which correspond
566  * to the real modifiers (i.e Mod2, Mod3, ...) in @modifiers.
567  * are set in @state to their non-virtual counterparts (i.e. Mod2,
568  * Mod3,...) and set the corresponding bits in @state.
569  *
570  * GDK already does this before delivering key events, but for
571  * compatibility reasons, it only sets the first virtual modifier
572  * it finds, whereas this function sets all matching virtual modifiers.
573  *
574  * This function is useful when matching key events against
575  * accelerators.
576  *
577  * Since: 2.20
578  */
579 void
580 gdk_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
581                                   GdkModifierType *state)
582 {
583   g_return_if_fail (GDK_IS_KEYMAP (keymap));
584
585   GDK_KEYMAP_GET_CLASS (keymap)->add_virtual_modifiers (keymap, state);
586 }
587
588 /**
589  * gdk_keymap_map_virtual_modifiers:
590  * @keymap: a #GdkKeymap
591  * @state: (out): pointer to the modifier state to map
592  *
593  * Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
594  * are set in @state to their non-virtual counterparts (i.e. Mod2,
595  * Mod3,...) and set the corresponding bits in @state.
596  *
597  * This function is useful when matching key events against
598  * accelerators.
599  *
600  * Returns: %TRUE if no virtual modifiers were mapped to the
601  *     same non-virtual modifier. Note that %FALSE is also returned
602  *     if a virtual modifier is mapped to a non-virtual modifier that
603  *     was already set in @state.
604  *
605  * Since: 2.20
606  */
607 gboolean
608 gdk_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
609                                   GdkModifierType *state)
610 {
611   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
612
613   return GDK_KEYMAP_GET_CLASS(keymap)->map_virtual_modifiers (keymap, state);
614 }
615
616 static GdkModifierType
617 gdk_keymap_real_get_modifier_mask (GdkKeymap         *keymap,
618                                    GdkModifierIntent  intent)
619 {
620   switch (intent)
621     {
622     case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
623       return GDK_CONTROL_MASK;
624
625     case GDK_MODIFIER_INTENT_CONTEXT_MENU:
626       return 0;
627
628     case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
629       return GDK_SHIFT_MASK;
630
631     case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
632       return GDK_CONTROL_MASK;
633
634     case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
635       return GDK_MOD1_MASK | GDK_CONTROL_MASK;
636
637     case GDK_MODIFIER_INTENT_SHIFT_GROUP:
638       return 0;
639
640     default:
641       g_return_val_if_reached (0);
642     }
643 }
644
645 /**
646  * gdk_keymap_get_modifier_mask:
647  * @keymap: a #GdkKeymap
648  * @intent: the use case for the modifier mask
649  *
650  * Returns the modifier mask the @keymap's windowing system backend
651  * uses for a particular purpose.
652  *
653  * Note that this function always returns real hardware modifiers, not
654  * virtual ones (e.g. it will return #GDK_MOD1_MASK rather than
655  * #GDK_META_MASK if the backend maps MOD1 to META), so there are use
656  * cases where the return value of this function has to be transformed
657  * by gdk_keymap_add_virtual_modifiers() in order to contain the
658  * expected result.
659  *
660  * Returns: the modifier mask used for @intent.
661  *
662  * Since: 3.4
663  **/
664 GdkModifierType
665 gdk_keymap_get_modifier_mask (GdkKeymap         *keymap,
666                               GdkModifierIntent  intent)
667 {
668   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
669
670   return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_mask (keymap, intent);
671 }
672
673
674 /**
675  * gdk_keyval_name:
676  * @keyval: a key value
677  *
678  * Converts a key value into a symbolic name.
679  *
680  * The names are the same as those in the
681  * <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file
682  * but without the leading "GDK_KEY_".
683  *
684  * Return value: (transfer none): a string containing the name of the key,
685  *     or %NULL if @keyval is not a valid key. The string should not be
686  *     modified.
687  */
688 gchar *
689 gdk_keyval_name (guint keyval)
690 {
691   GdkDisplayManager *manager = gdk_display_manager_get ();
692
693   return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->get_keyval_name (manager,
694                                                                    keyval);
695 }
696
697 /**
698  * gdk_keyval_from_name:
699  * @keyval_name: a key name
700  *
701  * Converts a key name to a key value.
702  *
703  * The names are the same as those in the
704  * <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file
705  * but without the leading "GDK_KEY_".
706  *
707  * Returns: the corresponding key value, or %GDK_KEY_VoidSymbol
708  *     if the key name is not a valid key
709  */
710 guint
711 gdk_keyval_from_name (const gchar *keyval_name)
712 {
713   GdkDisplayManager *manager = gdk_display_manager_get ();
714
715   return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->lookup_keyval (manager,
716                                                                  keyval_name);
717 }
718
719 void
720 _gdk_display_manager_real_keyval_convert_case (GdkDisplayManager *manager,
721                                                guint              symbol,
722                                                guint             *lower,
723                                                guint             *upper)
724 {
725   guint xlower = symbol;
726   guint xupper = symbol;
727
728   /* Check for directly encoded 24-bit UCS characters: */
729   if ((symbol & 0xff000000) == 0x01000000)
730     {
731       if (lower)
732         *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
733       if (upper)
734         *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
735       return;
736     }
737
738   switch (symbol >> 8)
739     {
740     case 0: /* Latin 1 */
741       if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z))
742         xlower += (GDK_KEY_a - GDK_KEY_A);
743       else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z))
744         xupper -= (GDK_KEY_a - GDK_KEY_A);
745       else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis))
746         xlower += (GDK_KEY_agrave - GDK_KEY_Agrave);
747       else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis))
748         xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave);
749       else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn))
750         xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique);
751       else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn))
752         xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique);
753       break;
754
755     case 1: /* Latin 2 */
756       /* Assume the KeySym is a legal value (ignore discontinuities) */
757       if (symbol == GDK_KEY_Aogonek)
758         xlower = GDK_KEY_aogonek;
759       else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute)
760         xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke);
761       else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute)
762         xlower += (GDK_KEY_scaron - GDK_KEY_Scaron);
763       else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot)
764         xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron);
765       else if (symbol == GDK_KEY_aogonek)
766         xupper = GDK_KEY_Aogonek;
767       else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute)
768         xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke);
769       else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute)
770         xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron);
771       else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot)
772         xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron);
773       else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla)
774         xlower += (GDK_KEY_racute - GDK_KEY_Racute);
775       else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla)
776         xupper -= (GDK_KEY_racute - GDK_KEY_Racute);
777       break;
778
779     case 2: /* Latin 3 */
780       /* Assume the KeySym is a legal value (ignore discontinuities) */
781       if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex)
782         xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke);
783       else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex)
784         xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve);
785       else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex)
786         xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke);
787       else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex)
788         xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve);
789       else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex)
790         xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
791       else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex)
792         xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
793       break;
794
795     case 3: /* Latin 4 */
796       /* Assume the KeySym is a legal value (ignore discontinuities) */
797       if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash)
798         xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
799       else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash)
800         xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
801       else if (symbol == GDK_KEY_ENG)
802         xlower = GDK_KEY_eng;
803       else if (symbol == GDK_KEY_eng)
804         xupper = GDK_KEY_ENG;
805       else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron)
806         xlower += (GDK_KEY_amacron - GDK_KEY_Amacron);
807       else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron)
808         xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron);
809       break;
810
811     case 6: /* Cyrillic */
812       /* Assume the KeySym is a legal value (ignore discontinuities) */
813       if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE)
814         xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
815       else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze)
816         xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
817       else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN)
818         xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
819       else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign)
820         xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
821       break;
822
823     case 7: /* Greek */
824       /* Assume the KeySym is a legal value (ignore discontinuities) */
825       if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent)
826         xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
827       else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent &&
828                symbol != GDK_KEY_Greek_iotaaccentdieresis &&
829                symbol != GDK_KEY_Greek_upsilonaccentdieresis)
830         xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
831       else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA)
832         xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
833       else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega &&
834                symbol != GDK_KEY_Greek_finalsmallsigma)
835         xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
836       break;
837     }
838
839   if (lower)
840     *lower = xlower;
841   if (upper)
842     *upper = xupper;
843 }