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 "gdkquartzkeys.h"
58 #include "gdkkeysprivate.h"
59 #include "gdkkeysyms.h"
61 #define NUM_KEYCODES 128
62 #define KEYVALS_PER_KEYCODE 4
64 static GdkKeymap *default_keymap = NULL;
66 struct _GdkQuartzKeymap
71 struct _GdkQuartzKeymapClass
73 GdkKeymapClass keymap_class;
76 G_DEFINE_TYPE (GdkQuartzKeymap, gdk_quartz_keymap, GDK_TYPE_KEYMAP)
79 _gdk_quartz_display_get_keymap (GdkDisplay *display)
81 if (default_keymap == NULL)
82 default_keymap = g_object_new (gdk_quartz_keymap_get_type (), NULL);
84 return default_keymap;
87 /* Note: we could check only if building against the 10.5 SDK instead, but
88 * that would make non-xml layouts not work in 32-bit which would be a quite
89 * bad regression. This way, old unsupported layouts will just not work in
93 static TISInputSourceRef current_layout = NULL;
95 static KeyboardLayoutRef current_layout = NULL;
98 /* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
99 * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
101 static guint *keyval_array = NULL;
103 static inline UniChar
104 macroman2ucs (unsigned char c)
106 /* Precalculated table mapping MacRoman-128 to Unicode. Generated
107 by creating single element CFStringRefs then extracting the
110 static const unsigned short table[128] = {
111 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
112 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
113 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
114 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
115 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
116 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
117 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
118 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
119 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
120 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
121 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
122 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
123 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
124 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
125 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
126 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
132 return table[c - 128];
135 const static struct {
138 unsigned int modmask; /* So we can tell when a mod key is pressed/released */
140 { 54, GDK_KEY_Meta_R, NSCommandKeyMask },
141 { 55, GDK_KEY_Meta_L, NSCommandKeyMask },
142 { 56, GDK_KEY_Shift_L, NSShiftKeyMask },
143 { 57, GDK_KEY_Caps_Lock, NSAlphaShiftKeyMask },
144 { 58, GDK_KEY_Alt_L, NSAlternateKeyMask },
145 { 59, GDK_KEY_Control_L, NSControlKeyMask },
146 { 60, GDK_KEY_Shift_R, NSShiftKeyMask },
147 { 61, GDK_KEY_Alt_R, NSAlternateKeyMask },
148 { 62, GDK_KEY_Control_R, NSControlKeyMask },
149 { 122, GDK_KEY_F1, 0 },
150 { 120, GDK_KEY_F2, 0 },
151 { 99, GDK_KEY_F3, 0 },
152 { 118, GDK_KEY_F4, 0 },
153 { 96, GDK_KEY_F5, 0 },
154 { 97, GDK_KEY_F6, 0 },
155 { 98, GDK_KEY_F7, 0 },
156 { 100, GDK_KEY_F8, 0 },
157 { 101, GDK_KEY_F9, 0 },
158 { 109, GDK_KEY_F10, 0 },
159 { 103, GDK_KEY_F11, 0 },
160 { 111, GDK_KEY_F12, 0 },
161 { 105, GDK_KEY_F13, 0 },
162 { 107, GDK_KEY_F14, 0 },
163 { 113, GDK_KEY_F15, 0 },
164 { 106, GDK_KEY_F16, 0 }
167 const static struct {
169 guint normal_keyval, keypad_keyval;
170 } known_numeric_keys[] = {
171 { 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
172 { 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
173 { 69, GDK_KEY_plus, GDK_KEY_KP_Add },
174 { 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
175 { 76, 0x01000003, GDK_KEY_KP_Enter },
176 { 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
177 { 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
178 { 82, GDK_KEY_0, GDK_KEY_KP_0 },
179 { 83, GDK_KEY_1, GDK_KEY_KP_1 },
180 { 84, GDK_KEY_2, GDK_KEY_KP_2 },
181 { 85, GDK_KEY_3, GDK_KEY_KP_3 },
182 { 86, GDK_KEY_4, GDK_KEY_KP_4 },
183 { 87, GDK_KEY_5, GDK_KEY_KP_5 },
184 { 88, GDK_KEY_6, GDK_KEY_KP_6 },
185 { 89, GDK_KEY_7, GDK_KEY_KP_7 },
186 { 91, GDK_KEY_8, GDK_KEY_KP_8 },
187 { 92, GDK_KEY_9, GDK_KEY_KP_9 }
190 /* These values aren't covered by gdk_unicode_to_keyval */
191 const static struct {
194 } special_ucs_table [] = {
195 { 0x0001, GDK_KEY_Home },
196 { 0x0003, GDK_KEY_Return },
197 { 0x0004, GDK_KEY_End },
198 { 0x0008, GDK_KEY_BackSpace },
199 { 0x0009, GDK_KEY_Tab },
200 { 0x000b, GDK_KEY_Page_Up },
201 { 0x000c, GDK_KEY_Page_Down },
202 { 0x000d, GDK_KEY_Return },
203 { 0x001b, GDK_KEY_Escape },
204 { 0x001c, GDK_KEY_Left },
205 { 0x001d, GDK_KEY_Right },
206 { 0x001e, GDK_KEY_Up },
207 { 0x001f, GDK_KEY_Down },
208 { 0x007f, GDK_KEY_Delete },
209 { 0xf027, GDK_KEY_dead_acute },
210 { 0xf060, GDK_KEY_dead_grave },
211 { 0xf300, GDK_KEY_dead_grave },
212 { 0xf0b4, GDK_KEY_dead_acute },
213 { 0xf301, GDK_KEY_dead_acute },
214 { 0xf385, GDK_KEY_dead_acute },
215 { 0xf05e, GDK_KEY_dead_circumflex },
216 { 0xf2c6, GDK_KEY_dead_circumflex },
217 { 0xf302, GDK_KEY_dead_circumflex },
218 { 0xf07e, GDK_KEY_dead_tilde },
219 { 0xf303, GDK_KEY_dead_tilde },
220 { 0xf342, GDK_KEY_dead_perispomeni },
221 { 0xf0af, GDK_KEY_dead_macron },
222 { 0xf304, GDK_KEY_dead_macron },
223 { 0xf2d8, GDK_KEY_dead_breve },
224 { 0xf306, GDK_KEY_dead_breve },
225 { 0xf2d9, GDK_KEY_dead_abovedot },
226 { 0xf307, GDK_KEY_dead_abovedot },
227 { 0xf0a8, GDK_KEY_dead_diaeresis },
228 { 0xf308, GDK_KEY_dead_diaeresis },
229 { 0xf2da, GDK_KEY_dead_abovering },
230 { 0xf30A, GDK_KEY_dead_abovering },
231 { 0xf022, GDK_KEY_dead_doubleacute },
232 { 0xf2dd, GDK_KEY_dead_doubleacute },
233 { 0xf30B, GDK_KEY_dead_doubleacute },
234 { 0xf2c7, GDK_KEY_dead_caron },
235 { 0xf30C, GDK_KEY_dead_caron },
236 { 0xf0be, GDK_KEY_dead_cedilla },
237 { 0xf327, GDK_KEY_dead_cedilla },
238 { 0xf2db, GDK_KEY_dead_ogonek },
239 { 0xf328, GDK_KEY_dead_ogonek },
240 { 0xfe5d, GDK_KEY_dead_iota },
241 { 0xf323, GDK_KEY_dead_belowdot },
242 { 0xf309, GDK_KEY_dead_hook },
243 { 0xf31B, GDK_KEY_dead_horn },
244 { 0xf02d, GDK_KEY_dead_stroke },
245 { 0xf335, GDK_KEY_dead_stroke },
246 { 0xf336, GDK_KEY_dead_stroke },
247 { 0xf313, GDK_KEY_dead_abovecomma },
248 /* { 0xf313, GDK_KEY_dead_psili }, */
249 { 0xf314, GDK_KEY_dead_abovereversedcomma },
250 /* { 0xf314, GDK_KEY_dead_dasia }, */
251 { 0xf30F, GDK_KEY_dead_doublegrave },
252 { 0xf325, GDK_KEY_dead_belowring },
253 { 0xf2cd, GDK_KEY_dead_belowmacron },
254 { 0xf331, GDK_KEY_dead_belowmacron },
255 { 0xf32D, GDK_KEY_dead_belowcircumflex },
256 { 0xf330, GDK_KEY_dead_belowtilde },
257 { 0xf32E, GDK_KEY_dead_belowbreve },
258 { 0xf324, GDK_KEY_dead_belowdiaeresis },
259 { 0xf311, GDK_KEY_dead_invertedbreve },
260 { 0xf02c, GDK_KEY_dead_belowcomma },
261 { 0xf326, GDK_KEY_dead_belowcomma }
265 maybe_update_keymap (void)
267 const void *chr_data = NULL;
270 TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
271 CFDataRef layout_data_ref;
274 KeyboardLayoutRef new_layout;
275 KeyboardLayoutKind layout_kind;
277 KLGetCurrentKeyboardLayout (&new_layout);
280 if (new_layout != current_layout)
285 g_free (keyval_array);
286 keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
289 layout_data_ref = (CFDataRef) TISGetInputSourceProperty
290 (new_layout, kTISPropertyUnicodeKeyLayoutData);
293 chr_data = CFDataGetBytePtr (layout_data_ref);
295 if (chr_data == NULL)
297 g_error ("cannot get keyboard layout data");
301 /* Get the layout kind */
302 KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
304 /* 8-bit-only keyabord layout */
305 if (layout_kind == kKLKCHRKind)
308 KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
310 for (i = 0; i < NUM_KEYCODES; i++)
313 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
315 p = keyval_array + i * KEYVALS_PER_KEYCODE;
317 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
323 key_code = modifiers[j] | i;
324 c = KeyTranslate (chr_data, key_code, &state);
329 c = KeyTranslate (chr_data, key_code | 128, &state2);
332 if (c != 0 && c != 0x10)
335 gboolean found = FALSE;
337 /* FIXME: some keyboard layouts (e.g. Russian) use
338 * a different 8-bit character set. We should
339 * check for this. Not a serious problem, because
340 * most (all?) of these layouts also have a
343 uc = macroman2ucs (c);
345 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
347 if (special_ucs_table[k].ucs_value == uc)
349 p[j] = special_ucs_table[k].keyval;
355 /* Special-case shift-tab since GTK+ expects
356 * GDK_KEY_ISO_Left_Tab for that.
358 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
359 p[j] = GDK_KEY_ISO_Left_Tab;
365 tmp = gdk_unicode_to_keyval (uc);
366 if (tmp != (uc | 0x01000000))
385 /* unicode keyboard layout */
386 else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
389 KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
392 for (i = 0; i < NUM_KEYCODES; i++)
395 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
399 p = keyval_array + i * KEYVALS_PER_KEYCODE;
401 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
408 key_code = modifiers[j] | i;
409 err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
410 (modifiers[j] >> 8) & 0xFF,
413 &state, 4, &nChars, chars);
416 /* FIXME: Theoretically, we can get multiple UTF-16 values;
417 * we should convert them to proper unicode and figure
418 * out whether there are really keyboard layouts that
419 * give us more than one character for one keypress. */
420 if (err == noErr && nChars == 1)
423 gboolean found = FALSE;
425 /* A few <Shift><Option>keys return two
426 * characters, the first of which is U+00a0,
427 * which isn't interesting; so we return the
428 * second. More sophisticated handling is the
429 * job of a GtkIMContext.
431 * If state isn't zero, it means that it's a
432 * dead key of some sort. Some of those are
433 * enumerated in the special_ucs_table with the
434 * high nibble set to f to push it into the
435 * private use range. Here we do the same.
438 chars[nChars - 1] |= 0xf000;
439 uc = chars[nChars - 1];
441 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
443 if (special_ucs_table[k].ucs_value == uc)
445 p[j] = special_ucs_table[k].keyval;
451 /* Special-case shift-tab since GTK+ expects
452 * GDK_KEY_ISO_Left_Tab for that.
454 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
455 p[j] = GDK_KEY_ISO_Left_Tab;
461 tmp = gdk_unicode_to_keyval (uc);
462 if (tmp != (uc | 0x01000000))
484 g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
485 " - not supported right now");
489 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
491 p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE;
493 if (p[0] == 0 && p[1] == 0 &&
494 p[2] == 0 && p[3] == 0)
495 p[0] = known_keys[i].keyval;
498 for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
500 p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
502 if (p[0] == known_numeric_keys[i].normal_keyval)
503 p[0] = known_numeric_keys[i].keypad_keyval;
507 g_signal_emit_by_name (default_keymap, "keys_changed");
509 current_layout = new_layout;
513 static PangoDirection
514 gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
516 return PANGO_DIRECTION_NEUTRAL;
520 gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
522 /* FIXME: Can we implement this? */
527 gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
529 /* FIXME: Implement this. */
534 gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
536 /* FIXME: Implement this. */
541 gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap *keymap,
549 maybe_update_keymap ();
552 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
554 for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
558 if (keyval_array[i] != keyval)
563 key.keycode = i / KEYVALS_PER_KEYCODE;
565 key.level = i % KEYVALS_PER_KEYCODE;
567 g_array_append_val (keys_array, key);
570 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
576 gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap *keymap,
577 guint hardware_keycode,
582 GArray *keys_array, *keyvals_array;
586 maybe_update_keymap ();
590 if (hardware_keycode > NUM_KEYCODES)
594 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
599 keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
601 keyvals_array = NULL;
603 p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
605 for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
613 g_array_append_val (keyvals_array, p[i]);
619 key.keycode = hardware_keycode;
623 g_array_append_val (keys_array, key);
628 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
631 *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
633 return *n_entries > 0;
637 gdk_quartz_keymap_lookup_key (GdkKeymap *keymap,
638 const GdkKeymapKey *key)
640 /* FIXME: Implement */
645 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
648 translate_keysym (guint hardware_keycode,
650 GdkModifierType state,
651 gint *effective_group,
652 gint *effective_level)
657 level = (state & GDK_SHIFT_MASK) ? 1 : 0;
659 if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
660 (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
663 if (!GET_KEYVAL (hardware_keycode, group, level) &&
664 GET_KEYVAL (hardware_keycode, group, 0))
667 tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
669 if (state & GDK_LOCK_MASK)
671 guint upper = gdk_keyval_to_upper (tmp_keyval);
672 if (upper != tmp_keyval)
680 gdk_quartz_keymap_translate_keyboard_state (GdkKeymap *keymap,
681 guint hardware_keycode,
682 GdkModifierType state,
685 gint *effective_group,
687 GdkModifierType *consumed_modifiers)
691 guint tmp_modifiers = 0;
693 maybe_update_keymap ();
698 *effective_group = 0;
701 if (consumed_modifiers)
702 *consumed_modifiers = 0;
704 if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
707 /* Check if shift or capslock modify the keyval */
708 for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
710 if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
711 translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
712 tmp_modifiers |= bit;
715 tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
717 if (consumed_modifiers)
718 *consumed_modifiers = tmp_modifiers;
721 *keyval = tmp_keyval;
727 gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap *keymap,
728 GdkModifierType *state)
730 /* FIXME: For now, we've mimiced the Windows backend. */
734 gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap *keymap,
735 GdkModifierType *state)
737 /* FIXME: For now, we've mimiced the Windows backend. */
741 /* What sort of key event is this? Returns one of
742 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
745 _gdk_quartz_keys_event_type (NSEvent *event)
747 unsigned short keycode;
751 switch ([event type])
754 return GDK_KEY_PRESS;
756 return GDK_KEY_RELEASE;
760 g_assert_not_reached ();
763 /* For flags-changed events, we have to find the special key that caused the
764 * event, and see if it's in the modifier mask. */
765 keycode = [event keyCode];
766 flags = [event modifierFlags];
768 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
770 if (known_keys[i].keycode == keycode)
772 if (flags & known_keys[i].modmask)
773 return GDK_KEY_PRESS;
775 return GDK_KEY_RELEASE;
779 /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
780 * events for no good reason. Ignore them! */
785 _gdk_quartz_keys_is_modifier (guint keycode)
789 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
791 if (known_keys[i].modmask == 0)
794 if (known_keys[i].keycode == keycode)
802 gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
807 gdk_quartz_keymap_finalize (GObject *object)
809 G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
813 gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
815 GObjectClass *object_class = G_OBJECT_CLASS (klass);
816 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
818 object_class->finalize = gdk_quartz_keymap_finalize;
820 keymap_class->get_direction = gdk_quartz_keymap_get_direction;
821 keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
822 keymap_class->get_caps_lock_state = gdk_quartz_keymap_get_caps_lock_state;
823 keymap_class->get_num_lock_state = gdk_quartz_keymap_get_num_lock_state;
824 keymap_class->get_entries_for_keyval = gdk_quartz_keymap_get_entries_for_keyval;
825 keymap_class->get_entries_for_keycode = gdk_quartz_keymap_get_entries_for_keycode;
826 keymap_class->lookup_key = gdk_quartz_keymap_lookup_key;
827 keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
828 keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
829 keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;