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_num_lock_state (GdkKeymap *keymap)
457 /* FIXME: Implement this. */
462 gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
470 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
471 g_return_val_if_fail (keys != NULL, FALSE);
472 g_return_val_if_fail (n_keys != NULL, FALSE);
473 g_return_val_if_fail (keyval != 0, FALSE);
475 maybe_update_keymap ();
478 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
480 for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
484 if (keyval_array[i] != keyval)
489 key.keycode = i / KEYVALS_PER_KEYCODE;
491 key.level = i % KEYVALS_PER_KEYCODE;
493 g_array_append_val (keys_array, key);
496 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
502 gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
503 guint hardware_keycode,
508 GArray *keys_array, *keyvals_array;
512 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
513 g_return_val_if_fail (n_entries != NULL, FALSE);
515 maybe_update_keymap ();
519 if (hardware_keycode > NUM_KEYCODES)
523 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
528 keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
530 keyvals_array = NULL;
532 p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
534 for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
542 g_array_append_val (keyvals_array, p[i]);
548 key.keycode = hardware_keycode;
552 g_array_append_val (keys_array, key);
557 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
560 *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
562 return *n_entries > 0;
566 gdk_keymap_lookup_key (GdkKeymap *keymap,
567 const GdkKeymapKey *key)
569 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
570 g_return_val_if_fail (key != NULL, 0);
571 g_return_val_if_fail (key->group < 4, 0);
573 /* FIXME: Implement */
578 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
581 translate_keysym (guint hardware_keycode,
583 GdkModifierType state,
584 gint *effective_group,
585 gint *effective_level)
590 level = (state & GDK_SHIFT_MASK) ? 1 : 0;
592 if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
593 (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
596 if (!GET_KEYVAL (hardware_keycode, group, level) &&
597 GET_KEYVAL (hardware_keycode, group, 0))
600 tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
602 if (state & GDK_LOCK_MASK)
604 guint upper = gdk_keyval_to_upper (tmp_keyval);
605 if (upper != tmp_keyval)
613 gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
614 guint hardware_keycode,
615 GdkModifierType state,
618 gint *effective_group,
620 GdkModifierType *consumed_modifiers)
624 guint tmp_modifiers = 0;
626 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
627 g_return_val_if_fail (group >= 0 && group <= 1, FALSE);
629 maybe_update_keymap ();
634 *effective_group = 0;
637 if (consumed_modifiers)
638 *consumed_modifiers = 0;
640 if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
643 /* Check if shift or capslock modify the keyval */
644 for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
646 if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
647 translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
648 tmp_modifiers |= bit;
651 tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
653 if (consumed_modifiers)
654 *consumed_modifiers = tmp_modifiers;
657 *keyval = tmp_keyval;
663 gdk_keymap_add_virtual_modifiers (GdkKeymap *keymap,
664 GdkModifierType *state)
666 /* FIXME: For now, we've mimiced the Windows backend. */
670 gdk_keymap_map_virtual_modifiers (GdkKeymap *keymap,
671 GdkModifierType *state)
673 /* FIXME: For now, we've mimiced the Windows backend. */
677 /* What sort of key event is this? Returns one of
678 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
681 _gdk_quartz_keys_event_type (NSEvent *event)
683 unsigned short keycode;
687 switch ([event type])
690 return GDK_KEY_PRESS;
692 return GDK_KEY_RELEASE;
696 g_assert_not_reached ();
699 /* For flags-changed events, we have to find the special key that caused the
700 * event, and see if it's in the modifier mask. */
701 keycode = [event keyCode];
702 flags = [event modifierFlags];
704 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
706 if (known_keys[i].keycode == keycode)
708 if (flags & known_keys[i].modmask)
709 return GDK_KEY_PRESS;
711 return GDK_KEY_RELEASE;
715 /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
716 * events for no good reason. Ignore them! */
721 _gdk_quartz_keys_is_modifier (guint keycode)
725 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
727 if (known_keys[i].modmask == 0)
730 if (known_keys[i].keycode == keycode)