3 * Copyright (C) 2000 Red Hat, Inc.
4 * Copyright (C) 2005 Imendio AB
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 /* Some parts of this code come from quartzKeyboard.c,
22 * from the Apple X11 Server.
24 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
26 * Permission is hereby granted, free of charge, to any person
27 * obtaining a copy of this software and associated documentation files
28 * (the "Software"), to deal in the Software without restriction,
29 * including without limitation the rights to use, copy, modify, merge,
30 * publish, distribute, sublicense, and/or sell copies of the Software,
31 * and to permit persons to whom the Software is furnished to do so,
32 * subject to the following conditions:
34 * The above copyright notice and this permission notice shall be
35 * included in all copies or substantial portions of the Software.
37 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
40 * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
41 * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
44 * DEALINGS IN THE SOFTWARE.
46 * Except as contained in this notice, the name(s) of the above
47 * copyright holders shall not be used in advertising or otherwise to
48 * promote the sale, use or other dealings in this Software without
49 * prior written authorization.
54 #include <Carbon/Carbon.h>
55 #include <AppKit/NSEvent.h>
57 #include "gdkkeysyms.h"
59 #define NUM_KEYCODES 128
60 #define KEYVALS_PER_KEYCODE 4
62 static GdkKeymap *default_keymap = NULL;
64 /* Note: we could check only if building against the 10.5 SDK instead, but
65 * that would make non-xml layouts not work in 32-bit which would be a quite
66 * bad regression. This way, old unsupported layouts will just not work in
70 static TISInputSourceRef current_layout = NULL;
72 static KeyboardLayoutRef current_layout = NULL;
75 /* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
76 * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
78 static guint *keyval_array = NULL;
81 macroman2ucs (unsigned char c)
83 /* Precalculated table mapping MacRoman-128 to Unicode. Generated
84 by creating single element CFStringRefs then extracting the
87 static const unsigned short table[128] = {
88 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
89 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
90 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
91 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
92 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
93 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
94 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
95 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
96 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
97 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
98 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
99 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
100 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
101 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
102 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
103 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
109 return table[c - 128];
112 const static struct {
115 unsigned int modmask; /* So we can tell when a mod key is pressed/released */
117 { 54, GDK_Meta_R, NSCommandKeyMask },
118 { 55, GDK_Meta_L, NSCommandKeyMask },
119 { 56, GDK_Shift_L, NSShiftKeyMask },
120 { 57, GDK_Caps_Lock, NSAlphaShiftKeyMask },
121 { 58, GDK_Alt_L, NSAlternateKeyMask },
122 { 59, GDK_Control_L, NSControlKeyMask },
123 { 60, GDK_Shift_R, NSShiftKeyMask },
124 { 61, GDK_Alt_R, NSAlternateKeyMask },
125 { 62, GDK_Control_R, NSControlKeyMask },
144 const static struct {
146 guint normal_keyval, keypad_keyval;
147 } known_numeric_keys[] = {
148 { 65, GDK_period, GDK_KP_Decimal },
149 { 67, GDK_asterisk, GDK_KP_Multiply },
150 { 69, GDK_plus, GDK_KP_Add },
151 { 75, GDK_slash, GDK_KP_Divide },
152 { 76, 0x01000003, GDK_KP_Enter },
153 { 78, GDK_minus, GDK_KP_Subtract },
154 { 81, GDK_equal, GDK_KP_Equal },
155 { 82, GDK_0, GDK_KP_0 },
156 { 83, GDK_1, GDK_KP_1 },
157 { 84, GDK_2, GDK_KP_2 },
158 { 85, GDK_3, GDK_KP_3 },
159 { 86, GDK_4, GDK_KP_4 },
160 { 87, GDK_5, GDK_KP_5 },
161 { 88, GDK_6, GDK_KP_6 },
162 { 89, GDK_7, GDK_KP_7 },
163 { 91, GDK_8, GDK_KP_8 },
164 { 92, GDK_9, GDK_KP_9 }
167 /* These values aren't covered by gdk_unicode_to_keyval */
168 const static struct {
171 } special_ucs_table [] = {
172 { 0x0001, GDK_Home },
173 { 0x0003, GDK_Return },
175 { 0x0008, GDK_BackSpace },
177 { 0x000b, GDK_Page_Up },
178 { 0x000c, GDK_Page_Down },
179 { 0x000d, GDK_Return },
180 { 0x001b, GDK_Escape },
181 { 0x001c, GDK_Left },
182 { 0x001d, GDK_Right },
184 { 0x001f, GDK_Down },
185 { 0x007f, GDK_Delete }
189 maybe_update_keymap (void)
191 const void *chr_data = NULL;
194 TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
195 CFDataRef layout_data_ref;
198 KeyboardLayoutRef new_layout;
199 KeyboardLayoutKind layout_kind;
201 KLGetCurrentKeyboardLayout (&new_layout);
204 if (new_layout != current_layout)
209 g_free (keyval_array);
210 keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
213 layout_data_ref = (CFDataRef) TISGetInputSourceProperty
214 (new_layout, kTISPropertyUnicodeKeyLayoutData);
217 chr_data = CFDataGetBytePtr (layout_data_ref);
219 if (chr_data == NULL)
221 g_error ("cannot get keyboard layout data");
225 /* Get the layout kind */
226 KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
228 /* 8-bit-only keyabord layout */
229 if (layout_kind == kKLKCHRKind)
232 KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
234 for (i = 0; i < NUM_KEYCODES; i++)
237 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
239 p = keyval_array + i * KEYVALS_PER_KEYCODE;
241 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
247 key_code = modifiers[j] | i;
248 c = KeyTranslate (chr_data, key_code, &state);
253 c = KeyTranslate (chr_data, key_code | 128, &state2);
256 if (c != 0 && c != 0x10)
259 gboolean found = FALSE;
261 /* FIXME: some keyboard layouts (e.g. Russian) use
262 * a different 8-bit character set. We should
263 * check for this. Not a serious problem, because
264 * most (all?) of these layouts also have a
267 uc = macroman2ucs (c);
269 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
271 if (special_ucs_table[k].ucs_value == uc)
273 p[j] = special_ucs_table[k].keyval;
279 /* Special-case shift-tab since GTK+ expects
280 * GDK_ISO_Left_Tab for that.
282 if (found && p[j] == GDK_Tab && modifiers[j] == shiftKey)
283 p[j] = GDK_ISO_Left_Tab;
289 tmp = gdk_unicode_to_keyval (uc);
290 if (tmp != (uc | 0x01000000))
309 /* unicode keyboard layout */
310 else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
313 KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
316 for (i = 0; i < NUM_KEYCODES; i++)
319 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
323 p = keyval_array + i * KEYVALS_PER_KEYCODE;
325 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
332 key_code = modifiers[j] | i;
333 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
334 (modifiers[j] >> 8) & 0xFF,
336 kUCKeyTranslateNoDeadKeysMask,
337 &state, 4, &nChars, chars);
340 /* FIXME: Theoretically, we can get multiple UTF-16 values;
341 * we should convert them to proper unicode and figure
342 * out whether there are really keyboard layouts that
343 * give us more than one character for one keypress. */
344 if (err == noErr && nChars == 1)
347 gboolean found = FALSE;
351 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
353 if (special_ucs_table[k].ucs_value == uc)
355 p[j] = special_ucs_table[k].keyval;
361 /* Special-case shift-tab since GTK+ expects
362 * GDK_ISO_Left_Tab for that.
364 if (found && p[j] == GDK_Tab && modifiers[j] == shiftKey)
365 p[j] = GDK_ISO_Left_Tab;
371 tmp = gdk_unicode_to_keyval (uc);
372 if (tmp != (uc | 0x01000000))
394 g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
395 " - not supported right now");
399 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
401 p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE;
403 if (p[0] == 0 && p[1] == 0 &&
404 p[2] == 0 && p[3] == 0)
405 p[0] = known_keys[i].keyval;
408 for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
410 p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
412 if (p[0] == known_numeric_keys[i].normal_keyval)
413 p[0] = known_numeric_keys[i].keypad_keyval;
417 g_signal_emit_by_name (default_keymap, "keys_changed");
419 current_layout = new_layout;
424 gdk_keymap_get_for_display (GdkDisplay *display)
426 g_return_val_if_fail (display == gdk_display_get_default (), NULL);
428 if (default_keymap == NULL)
429 default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
431 return default_keymap;
435 gdk_keymap_get_direction (GdkKeymap *keymap)
437 return PANGO_DIRECTION_NEUTRAL;
441 gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
443 /* FIXME: Can we implement this? */
448 gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
450 /* FIXME: Implement this. */
455 gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
463 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
464 g_return_val_if_fail (keys != NULL, FALSE);
465 g_return_val_if_fail (n_keys != NULL, FALSE);
466 g_return_val_if_fail (keyval != 0, FALSE);
468 maybe_update_keymap ();
471 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
473 for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
477 if (keyval_array[i] != keyval)
482 key.keycode = i / KEYVALS_PER_KEYCODE;
484 key.level = i % KEYVALS_PER_KEYCODE;
486 g_array_append_val (keys_array, key);
489 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
495 gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
496 guint hardware_keycode,
501 GArray *keys_array, *keyvals_array;
505 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
506 g_return_val_if_fail (n_entries != NULL, FALSE);
508 maybe_update_keymap ();
512 if (hardware_keycode > NUM_KEYCODES)
516 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
521 keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
523 keyvals_array = NULL;
525 p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
527 for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
535 g_array_append_val (keyvals_array, p[i]);
541 key.keycode = hardware_keycode;
545 g_array_append_val (keys_array, key);
550 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
553 *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
555 return *n_entries > 0;
559 gdk_keymap_lookup_key (GdkKeymap *keymap,
560 const GdkKeymapKey *key)
562 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
563 g_return_val_if_fail (key != NULL, 0);
564 g_return_val_if_fail (key->group < 4, 0);
566 /* FIXME: Implement */
571 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
574 translate_keysym (guint hardware_keycode,
576 GdkModifierType state,
577 gint *effective_group,
578 gint *effective_level)
583 level = (state & GDK_SHIFT_MASK) ? 1 : 0;
585 if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
586 (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
589 if (!GET_KEYVAL (hardware_keycode, group, level) &&
590 GET_KEYVAL (hardware_keycode, group, 0))
593 tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
595 if (state & GDK_LOCK_MASK)
597 guint upper = gdk_keyval_to_upper (tmp_keyval);
598 if (upper != tmp_keyval)
606 gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
607 guint hardware_keycode,
608 GdkModifierType state,
611 gint *effective_group,
613 GdkModifierType *consumed_modifiers)
617 guint tmp_modifiers = 0;
619 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
620 g_return_val_if_fail (group >= 0 && group <= 1, FALSE);
622 maybe_update_keymap ();
627 *effective_group = 0;
630 if (consumed_modifiers)
631 *consumed_modifiers = 0;
633 if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
636 /* Check if shift or capslock modify the keyval */
637 for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
639 if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
640 translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
641 tmp_modifiers |= bit;
644 tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
646 if (consumed_modifiers)
647 *consumed_modifiers = tmp_modifiers;
650 *keyval = tmp_keyval;
656 gdk_keymap_map_virtual_modifiers (GdkKeymap *keymap,
657 GdkModifierType *state)
659 /* FIXME: For now, we've mimiced the Windows backend. */
663 /* What sort of key event is this? Returns one of
664 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
667 _gdk_quartz_keys_event_type (NSEvent *event)
669 unsigned short keycode;
673 switch ([event type])
676 return GDK_KEY_PRESS;
678 return GDK_KEY_RELEASE;
682 g_assert_not_reached ();
685 /* For flags-changed events, we have to find the special key that caused the
686 * event, and see if it's in the modifier mask. */
687 keycode = [event keyCode];
688 flags = [event modifierFlags];
690 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
692 if (known_keys[i].keycode == keycode)
694 if (flags & known_keys[i].modmask)
695 return GDK_KEY_PRESS;
697 return GDK_KEY_RELEASE;
701 /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
702 * events for no good reason. Ignore them! */
707 _gdk_quartz_keys_is_modifier (guint keycode)
711 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
713 if (known_keys[i].modmask == 0)
716 if (known_keys[i].keycode == keycode)