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;
362 p[j] = gdk_unicode_to_keyval (uc);
377 /* unicode keyboard layout */
378 else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
381 KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
384 for (i = 0; i < NUM_KEYCODES; i++)
387 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
391 p = keyval_array + i * KEYVALS_PER_KEYCODE;
393 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
400 key_code = modifiers[j] | i;
401 err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
402 (modifiers[j] >> 8) & 0xFF,
405 &state, 4, &nChars, chars);
408 /* FIXME: Theoretically, we can get multiple UTF-16 values;
409 * we should convert them to proper unicode and figure
410 * out whether there are really keyboard layouts that
411 * give us more than one character for one keypress. */
412 if (err == noErr && nChars == 1)
415 gboolean found = FALSE;
417 /* A few <Shift><Option>keys return two
418 * characters, the first of which is U+00a0,
419 * which isn't interesting; so we return the
420 * second. More sophisticated handling is the
421 * job of a GtkIMContext.
423 * If state isn't zero, it means that it's a
424 * dead key of some sort. Some of those are
425 * enumerated in the special_ucs_table with the
426 * high nibble set to f to push it into the
427 * private use range. Here we do the same.
430 chars[nChars - 1] |= 0xf000;
431 uc = chars[nChars - 1];
433 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
435 if (special_ucs_table[k].ucs_value == uc)
437 p[j] = special_ucs_table[k].keyval;
443 /* Special-case shift-tab since GTK+ expects
444 * GDK_KEY_ISO_Left_Tab for that.
446 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
447 p[j] = GDK_KEY_ISO_Left_Tab;
450 p[j] = gdk_unicode_to_keyval (uc);
468 g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
469 " - not supported right now");
473 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
475 p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE;
477 if (p[0] == 0 && p[1] == 0 &&
478 p[2] == 0 && p[3] == 0)
479 p[0] = known_keys[i].keyval;
482 for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
484 p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
486 if (p[0] == known_numeric_keys[i].normal_keyval)
487 p[0] = known_numeric_keys[i].keypad_keyval;
491 g_signal_emit_by_name (default_keymap, "keys_changed");
493 current_layout = new_layout;
497 static PangoDirection
498 gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
500 return PANGO_DIRECTION_NEUTRAL;
504 gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
506 /* FIXME: Can we implement this? */
511 gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
513 /* FIXME: Implement this. */
518 gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
520 /* FIXME: Implement this. */
525 gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap *keymap,
533 maybe_update_keymap ();
536 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
538 for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
542 if (keyval_array[i] != keyval)
547 key.keycode = i / KEYVALS_PER_KEYCODE;
548 key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
551 g_array_append_val (keys_array, key);
554 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
560 gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap *keymap,
561 guint hardware_keycode,
566 GArray *keys_array, *keyvals_array;
570 maybe_update_keymap ();
574 if (hardware_keycode > NUM_KEYCODES)
578 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
583 keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
585 keyvals_array = NULL;
587 p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
589 for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
597 g_array_append_val (keyvals_array, p[i]);
603 key.keycode = hardware_keycode;
607 g_array_append_val (keys_array, key);
612 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
615 *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
617 return *n_entries > 0;
621 gdk_quartz_keymap_lookup_key (GdkKeymap *keymap,
622 const GdkKeymapKey *key)
624 /* FIXME: Implement */
629 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
632 translate_keysym (guint hardware_keycode,
634 GdkModifierType state,
635 gint *effective_group,
636 gint *effective_level)
641 level = (state & GDK_SHIFT_MASK) ? 1 : 0;
643 if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
644 (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
647 if (!GET_KEYVAL (hardware_keycode, group, level) &&
648 GET_KEYVAL (hardware_keycode, group, 0))
651 tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
653 if (state & GDK_LOCK_MASK)
655 guint upper = gdk_keyval_to_upper (tmp_keyval);
656 if (upper != tmp_keyval)
661 *effective_group = group;
663 *effective_level = level;
669 gdk_quartz_keymap_translate_keyboard_state (GdkKeymap *keymap,
670 guint hardware_keycode,
671 GdkModifierType state,
674 gint *effective_group,
676 GdkModifierType *consumed_modifiers)
680 guint tmp_modifiers = 0;
682 maybe_update_keymap ();
687 *effective_group = 0;
690 if (consumed_modifiers)
691 *consumed_modifiers = 0;
693 if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
696 /* Check if modifiers modify the keyval */
697 for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
699 if (translate_keysym (hardware_keycode,
700 (bit == GDK_MOD1_MASK) ? 0 : group,
703 translate_keysym (hardware_keycode,
704 (bit == GDK_MOD1_MASK) ? 1 : group,
707 tmp_modifiers |= bit;
710 tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
712 if (consumed_modifiers)
713 *consumed_modifiers = tmp_modifiers;
716 *keyval = tmp_keyval;
722 gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap *keymap,
723 GdkModifierType *state)
725 if (*state & GDK_MOD2_MASK)
726 *state |= GDK_META_MASK;
730 gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap *keymap,
731 GdkModifierType *state)
733 if (*state & GDK_META_MASK)
734 *state |= GDK_MOD2_MASK;
739 static GdkModifierType
740 gdk_quartz_keymap_get_modifier_mask (GdkKeymap *keymap,
741 GdkModifierIntent intent)
745 case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
746 return GDK_MOD2_MASK;
748 case GDK_MODIFIER_INTENT_CONTEXT_MENU:
749 return GDK_CONTROL_MASK;
751 case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
752 return GDK_SHIFT_MASK;
754 case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
755 return GDK_MOD2_MASK;
757 case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
758 return GDK_MOD2_MASK | GDK_CONTROL_MASK;
760 case GDK_MODIFIER_INTENT_SHIFT_GROUP:
761 return GDK_MOD1_MASK;
764 g_return_val_if_reached (0);
768 /* What sort of key event is this? Returns one of
769 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
772 _gdk_quartz_keys_event_type (NSEvent *event)
774 unsigned short keycode;
778 switch ([event type])
781 return GDK_KEY_PRESS;
783 return GDK_KEY_RELEASE;
787 g_assert_not_reached ();
790 /* For flags-changed events, we have to find the special key that caused the
791 * event, and see if it's in the modifier mask. */
792 keycode = [event keyCode];
793 flags = [event modifierFlags];
795 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
797 if (known_keys[i].keycode == keycode)
799 if (flags & known_keys[i].modmask)
800 return GDK_KEY_PRESS;
802 return GDK_KEY_RELEASE;
806 /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
807 * events for no good reason. Ignore them! */
812 _gdk_quartz_keys_is_modifier (guint keycode)
816 for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
818 if (known_keys[i].modmask == 0)
821 if (known_keys[i].keycode == keycode)
829 gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
834 gdk_quartz_keymap_finalize (GObject *object)
836 G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
840 gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
842 GObjectClass *object_class = G_OBJECT_CLASS (klass);
843 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
845 object_class->finalize = gdk_quartz_keymap_finalize;
847 keymap_class->get_direction = gdk_quartz_keymap_get_direction;
848 keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
849 keymap_class->get_caps_lock_state = gdk_quartz_keymap_get_caps_lock_state;
850 keymap_class->get_num_lock_state = gdk_quartz_keymap_get_num_lock_state;
851 keymap_class->get_entries_for_keyval = gdk_quartz_keymap_get_entries_for_keyval;
852 keymap_class->get_entries_for_keycode = gdk_quartz_keymap_get_entries_for_keycode;
853 keymap_class->lookup_key = gdk_quartz_keymap_lookup_key;
854 keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
855 keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
856 keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
857 keymap_class->get_modifier_mask = gdk_quartz_keymap_get_modifier_mask;