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