]> Pileus Git - ~andy/gtk/blob - gdk/gdkkeys.c
921493a6edd8ec2550fbb9258137894fd8464936
[~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_modifier_state:
383  * @keymap: a #GdkKeymap
384  *
385  * Returns the current modifier state.
386  *
387  * Returns: the current modifier state.
388  *
389  * Since: 3.4
390  */
391 guint
392 gdk_keymap_get_modifier_state (GdkKeymap *keymap)
393 {
394   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
395
396   if (GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_state)
397     return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_state (keymap);
398
399   return 0;
400 }
401
402 /**
403  * gdk_keymap_get_entries_for_keyval:
404  * @keymap: a #GdkKeymap
405  * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
406  * @keys: (out) (array length=n_keys) (transfer full): return location
407  *     for an array of #GdkKeymapKey
408  * @n_keys: return location for number of elements in returned array
409  *
410  * Obtains a list of keycode/group/level combinations that will
411  * generate @keyval. Groups and levels are two kinds of keyboard mode;
412  * in general, the level determines whether the top or bottom symbol
413  * on a key is used, and the group determines whether the left or
414  * right symbol is used. On US keyboards, the shift key changes the
415  * keyboard level, and there are no groups. A group switch key might
416  * convert a keyboard between Hebrew to English modes, for example.
417  * #GdkEventKey contains a %group field that indicates the active
418  * keyboard group. The level is computed from the modifier mask.
419  * The returned array should be freed
420  * with g_free().
421  *
422  * Return value: %TRUE if keys were found and returned
423  **/
424 gboolean
425 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
426                                    guint          keyval,
427                                    GdkKeymapKey **keys,
428                                    gint          *n_keys)
429 {
430   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
431   g_return_val_if_fail (keys != NULL, FALSE);
432   g_return_val_if_fail (n_keys != NULL, FALSE);
433   g_return_val_if_fail (keyval != 0, FALSE);
434
435   return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keyval (keymap, keyval,
436                                                                 keys, n_keys);
437 }
438
439 /**
440  * gdk_keymap_get_entries_for_keycode:
441  * @keymap: a #GdkKeymap
442  * @hardware_keycode: a keycode
443  * @keys: (out) (array length=n_entries) (transfer full): return
444  *     location for array of #GdkKeymapKey, or %NULL
445  * @keyvals: (out) (array length=n_entries) (transfer full): return
446  *     location for array of keyvals, or %NULL
447  * @n_entries: length of @keys and @keyvals
448  *
449  * Returns the keyvals bound to @hardware_keycode.
450  * The Nth #GdkKeymapKey in @keys is bound to the Nth
451  * keyval in @keyvals. Free the returned arrays with g_free().
452  * When a keycode is pressed by the user, the keyval from
453  * this list of entries is selected by considering the effective
454  * keyboard group and level. See gdk_keymap_translate_keyboard_state().
455  *
456  * Returns: %TRUE if there were any entries
457  **/
458 gboolean
459 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
460                                     guint          hardware_keycode,
461                                     GdkKeymapKey **keys,
462                                     guint        **keyvals,
463                                     gint          *n_entries)
464 {
465   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
466   g_return_val_if_fail (n_entries != NULL, FALSE);
467
468   return GDK_KEYMAP_GET_CLASS (keymap)->get_entries_for_keycode (keymap, hardware_keycode,
469                                                                  keys, keyvals, n_entries);
470 }
471
472 /**
473  * gdk_keymap_lookup_key:
474  * @keymap: a #GdkKeymap
475  * @key: a #GdkKeymapKey with keycode, group, and level initialized
476  *
477  * Looks up the keyval mapped to a keycode/group/level triplet.
478  * If no keyval is bound to @key, returns 0. For normal user input,
479  * you want to use gdk_keymap_translate_keyboard_state() instead of
480  * this function, since the effective group/level may not be
481  * the same as the current keyboard state.
482  *
483  * Return value: a keyval, or 0 if none was mapped to the given @key
484  **/
485 guint
486 gdk_keymap_lookup_key (GdkKeymap          *keymap,
487                        const GdkKeymapKey *key)
488 {
489   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
490   g_return_val_if_fail (key != NULL, 0);
491
492   return GDK_KEYMAP_GET_CLASS (keymap)->lookup_key (keymap, key);
493 }
494
495 /**
496  * gdk_keymap_translate_keyboard_state:
497  * @keymap: a #GdkKeymap
498  * @hardware_keycode: a keycode
499  * @state: a modifier state
500  * @group: active keyboard group
501  * @keyval: (out) (allow-none): return location for keyval, or %NULL
502  * @effective_group: (out) (allow-none): return location for effective
503  *     group, or %NULL
504  * @level: (out) (allow-none): return location for level, or %NULL
505  * @consumed_modifiers: (out) (allow-none): return location for modifiers
506  *     that were used to determine the group or level, or %NULL
507  *
508  * Translates the contents of a #GdkEventKey into a keyval, effective
509  * group, and level. Modifiers that affected the translation and
510  * are thus unavailable for application use are returned in
511  * @consumed_modifiers.
512  * See <xref linkend="key-group-explanation"/> for an explanation of
513  * groups and levels. The @effective_group is the group that was
514  * actually used for the translation; some keys such as Enter are not
515  * affected by the active keyboard group. The @level is derived from
516  * @state. For convenience, #GdkEventKey already contains the translated
517  * keyval, so this function isn't as useful as you might think.
518  *
519  * <note><para>
520  * @consumed_modifiers gives modifiers that should be masked out
521  * from @state when comparing this key press to a hot key. For
522  * instance, on a US keyboard, the <literal>plus</literal>
523  * symbol is shifted, so when comparing a key press to a
524  * <literal>&lt;Control&gt;plus</literal> accelerator &lt;Shift&gt; should
525  * be masked out.
526  * </para>
527  * <informalexample><programlisting>
528  * &sol;* We want to ignore irrelevant modifiers like ScrollLock *&sol;
529  * &num;define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)
530  * gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
531  *                                      event->state, event->group,
532  *                                      &amp;keyval, NULL, NULL, &amp;consumed);
533  * if (keyval == GDK_PLUS &&
534  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
535  *   &sol;* Control was pressed *&sol;
536  * </programlisting></informalexample>
537  * <para>
538  * An older interpretation @consumed_modifiers was that it contained
539  * all modifiers that might affect the translation of the key;
540  * this allowed accelerators to be stored with irrelevant consumed
541  * modifiers, by doing:</para>
542  * <informalexample><programlisting>
543  * &sol;* XXX Don't do this XXX *&sol;
544  * if (keyval == accel_keyval &&
545  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == (accel_mods &amp; ~consumed))
546  *   &sol;* Accelerator was pressed *&sol;
547  * </programlisting></informalexample>
548  * <para>
549  * However, this did not work if multi-modifier combinations were
550  * used in the keymap, since, for instance, <literal>&lt;Control&gt;</literal>
551  * would be masked out even if only <literal>&lt;Control&gt;&lt;Alt&gt;</literal>
552  * was used in the keymap. To support this usage as well as well as
553  * possible, all <emphasis>single modifier</emphasis> combinations
554  * that could affect the key for any combination of modifiers will
555  * be returned in @consumed_modifiers; multi-modifier combinations
556  * are returned only when actually found in @state. When you store
557  * accelerators, you should always store them with consumed modifiers
558  * removed. Store <literal>&lt;Control&gt;plus</literal>,
559  * not <literal>&lt;Control&gt;&lt;Shift&gt;plus</literal>,
560  * </para></note>
561  *
562  * Return value: %TRUE if there was a keyval bound to the keycode/state/group
563  **/
564 gboolean
565 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
566                                      guint            hardware_keycode,
567                                      GdkModifierType  state,
568                                      gint             group,
569                                      guint           *keyval,
570                                      gint            *effective_group,
571                                      gint            *level,
572                                      GdkModifierType *consumed_modifiers)
573 {
574   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
575
576   return GDK_KEYMAP_GET_CLASS (keymap)->translate_keyboard_state (keymap,
577                                                                   hardware_keycode,
578                                                                   state,
579                                                                   group,
580                                                                   keyval,
581                                                                   effective_group,
582                                                                   level,
583                                                                   consumed_modifiers);
584 }
585
586 /**
587  * gdk_keymap_add_virtual_modifiers:
588  * @keymap: a #GdkKeymap
589  * @state: (out): pointer to the modifier mask to change
590  *
591  * Adds virtual modifiers (i.e. Super, Hyper and Meta) which correspond
592  * to the real modifiers (i.e Mod2, Mod3, ...) in @modifiers.
593  * are set in @state to their non-virtual counterparts (i.e. Mod2,
594  * Mod3,...) and set the corresponding bits in @state.
595  *
596  * GDK already does this before delivering key events, but for
597  * compatibility reasons, it only sets the first virtual modifier
598  * it finds, whereas this function sets all matching virtual modifiers.
599  *
600  * This function is useful when matching key events against
601  * accelerators.
602  *
603  * Since: 2.20
604  */
605 void
606 gdk_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
607                                   GdkModifierType *state)
608 {
609   g_return_if_fail (GDK_IS_KEYMAP (keymap));
610
611   GDK_KEYMAP_GET_CLASS (keymap)->add_virtual_modifiers (keymap, state);
612 }
613
614 /**
615  * gdk_keymap_map_virtual_modifiers:
616  * @keymap: a #GdkKeymap
617  * @state: (out): pointer to the modifier state to map
618  *
619  * Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
620  * are set in @state to their non-virtual counterparts (i.e. Mod2,
621  * Mod3,...) and set the corresponding bits in @state.
622  *
623  * This function is useful when matching key events against
624  * accelerators.
625  *
626  * Returns: %TRUE if no virtual modifiers were mapped to the
627  *     same non-virtual modifier. Note that %FALSE is also returned
628  *     if a virtual modifier is mapped to a non-virtual modifier that
629  *     was already set in @state.
630  *
631  * Since: 2.20
632  */
633 gboolean
634 gdk_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
635                                   GdkModifierType *state)
636 {
637   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), FALSE);
638
639   return GDK_KEYMAP_GET_CLASS(keymap)->map_virtual_modifiers (keymap, state);
640 }
641
642 static GdkModifierType
643 gdk_keymap_real_get_modifier_mask (GdkKeymap         *keymap,
644                                    GdkModifierIntent  intent)
645 {
646   switch (intent)
647     {
648     case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
649       return GDK_CONTROL_MASK;
650
651     case GDK_MODIFIER_INTENT_CONTEXT_MENU:
652       return 0;
653
654     case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
655       return GDK_SHIFT_MASK;
656
657     case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
658       return GDK_CONTROL_MASK;
659
660     case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
661       return GDK_MOD1_MASK | GDK_CONTROL_MASK;
662
663     case GDK_MODIFIER_INTENT_SHIFT_GROUP:
664       return 0;
665
666     default:
667       g_return_val_if_reached (0);
668     }
669 }
670
671 /**
672  * gdk_keymap_get_modifier_mask:
673  * @keymap: a #GdkKeymap
674  * @intent: the use case for the modifier mask
675  *
676  * Returns the modifier mask the @keymap's windowing system backend
677  * uses for a particular purpose.
678  *
679  * Note that this function always returns real hardware modifiers, not
680  * virtual ones (e.g. it will return #GDK_MOD1_MASK rather than
681  * #GDK_META_MASK if the backend maps MOD1 to META), so there are use
682  * cases where the return value of this function has to be transformed
683  * by gdk_keymap_add_virtual_modifiers() in order to contain the
684  * expected result.
685  *
686  * Returns: the modifier mask used for @intent.
687  *
688  * Since: 3.4
689  **/
690 GdkModifierType
691 gdk_keymap_get_modifier_mask (GdkKeymap         *keymap,
692                               GdkModifierIntent  intent)
693 {
694   g_return_val_if_fail (GDK_IS_KEYMAP (keymap), 0);
695
696   return GDK_KEYMAP_GET_CLASS (keymap)->get_modifier_mask (keymap, intent);
697 }
698
699
700 /**
701  * gdk_keyval_name:
702  * @keyval: a key value
703  *
704  * Converts a key value into a symbolic name.
705  *
706  * The names are the same as those in the
707  * <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file
708  * but without the leading "GDK_KEY_".
709  *
710  * Return value: (transfer none): a string containing the name of the key,
711  *     or %NULL if @keyval is not a valid key. The string should not be
712  *     modified.
713  */
714 gchar *
715 gdk_keyval_name (guint keyval)
716 {
717   GdkDisplayManager *manager = gdk_display_manager_get ();
718
719   return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->get_keyval_name (manager,
720                                                                    keyval);
721 }
722
723 /**
724  * gdk_keyval_from_name:
725  * @keyval_name: a key name
726  *
727  * Converts a key name to a key value.
728  *
729  * The names are the same as those in the
730  * <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file
731  * but without the leading "GDK_KEY_".
732  *
733  * Returns: the corresponding key value, or %GDK_KEY_VoidSymbol
734  *     if the key name is not a valid key
735  */
736 guint
737 gdk_keyval_from_name (const gchar *keyval_name)
738 {
739   GdkDisplayManager *manager = gdk_display_manager_get ();
740
741   return GDK_DISPLAY_MANAGER_GET_CLASS (manager)->lookup_keyval (manager,
742                                                                  keyval_name);
743 }
744
745 void
746 _gdk_display_manager_real_keyval_convert_case (GdkDisplayManager *manager,
747                                                guint              symbol,
748                                                guint             *lower,
749                                                guint             *upper)
750 {
751   guint xlower = symbol;
752   guint xupper = symbol;
753
754   /* Check for directly encoded 24-bit UCS characters: */
755   if ((symbol & 0xff000000) == 0x01000000)
756     {
757       if (lower)
758         *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
759       if (upper)
760         *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
761       return;
762     }
763
764   switch (symbol >> 8)
765     {
766     case 0: /* Latin 1 */
767       if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z))
768         xlower += (GDK_KEY_a - GDK_KEY_A);
769       else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z))
770         xupper -= (GDK_KEY_a - GDK_KEY_A);
771       else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis))
772         xlower += (GDK_KEY_agrave - GDK_KEY_Agrave);
773       else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis))
774         xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave);
775       else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn))
776         xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique);
777       else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn))
778         xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique);
779       break;
780
781     case 1: /* Latin 2 */
782       /* Assume the KeySym is a legal value (ignore discontinuities) */
783       if (symbol == GDK_KEY_Aogonek)
784         xlower = GDK_KEY_aogonek;
785       else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute)
786         xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke);
787       else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute)
788         xlower += (GDK_KEY_scaron - GDK_KEY_Scaron);
789       else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot)
790         xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron);
791       else if (symbol == GDK_KEY_aogonek)
792         xupper = GDK_KEY_Aogonek;
793       else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute)
794         xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke);
795       else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute)
796         xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron);
797       else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot)
798         xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron);
799       else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla)
800         xlower += (GDK_KEY_racute - GDK_KEY_Racute);
801       else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla)
802         xupper -= (GDK_KEY_racute - GDK_KEY_Racute);
803       break;
804
805     case 2: /* Latin 3 */
806       /* Assume the KeySym is a legal value (ignore discontinuities) */
807       if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex)
808         xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke);
809       else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex)
810         xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve);
811       else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex)
812         xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke);
813       else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex)
814         xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve);
815       else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex)
816         xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
817       else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex)
818         xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
819       break;
820
821     case 3: /* Latin 4 */
822       /* Assume the KeySym is a legal value (ignore discontinuities) */
823       if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash)
824         xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
825       else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash)
826         xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
827       else if (symbol == GDK_KEY_ENG)
828         xlower = GDK_KEY_eng;
829       else if (symbol == GDK_KEY_eng)
830         xupper = GDK_KEY_ENG;
831       else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron)
832         xlower += (GDK_KEY_amacron - GDK_KEY_Amacron);
833       else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron)
834         xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron);
835       break;
836
837     case 6: /* Cyrillic */
838       /* Assume the KeySym is a legal value (ignore discontinuities) */
839       if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE)
840         xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
841       else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze)
842         xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
843       else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN)
844         xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
845       else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign)
846         xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
847       break;
848
849     case 7: /* Greek */
850       /* Assume the KeySym is a legal value (ignore discontinuities) */
851       if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent)
852         xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
853       else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent &&
854                symbol != GDK_KEY_Greek_iotaaccentdieresis &&
855                symbol != GDK_KEY_Greek_upsilonaccentdieresis)
856         xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
857       else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA)
858         xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
859       else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega &&
860                symbol != GDK_KEY_Greek_finalsmallsigma)
861         xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
862       break;
863     }
864
865   if (lower)
866     *lower = xlower;
867   if (upper)
868     *upper = xupper;
869 }