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, see <http://www.gnu.org/licenses/>.
19 /* Some parts of this code come from quartzKeyboard.c,
20 * from the Apple X11 Server.
22 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
24 * Permission is hereby granted, free of charge, to any person
25 * obtaining a copy of this software and associated documentation files
26 * (the "Software"), to deal in the Software without restriction,
27 * including without limitation the rights to use, copy, modify, merge,
28 * publish, distribute, sublicense, and/or sell copies of the Software,
29 * and to permit persons to whom the Software is furnished to do so,
30 * subject to the following conditions:
32 * The above copyright notice and this permission notice shall be
33 * included in all copies or substantial portions of the Software.
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
38 * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
39 * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
40 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
42 * DEALINGS IN THE SOFTWARE.
44 * Except as contained in this notice, the name(s) of the above
45 * copyright holders shall not be used in advertising or otherwise to
46 * promote the sale, use or other dealings in this Software without
47 * prior written authorization.
52 #include <Carbon/Carbon.h>
53 #include <AppKit/NSEvent.h>
55 #include "gdkquartzkeys.h"
56 #include "gdkkeysprivate.h"
57 #include "gdkkeysyms.h"
59 #define NUM_KEYCODES 128
60 #define KEYVALS_PER_KEYCODE 4
62 static GdkKeymap *default_keymap = NULL;
64 struct _GdkQuartzKeymap
69 struct _GdkQuartzKeymapClass
71 GdkKeymapClass keymap_class;
74 G_DEFINE_TYPE (GdkQuartzKeymap, gdk_quartz_keymap, GDK_TYPE_KEYMAP)
77 _gdk_quartz_display_get_keymap (GdkDisplay *display)
79 if (default_keymap == NULL)
80 default_keymap = g_object_new (gdk_quartz_keymap_get_type (), NULL);
82 return default_keymap;
85 /* Note: we could check only if building against the 10.5 SDK instead, but
86 * that would make non-xml layouts not work in 32-bit which would be a quite
87 * bad regression. This way, old unsupported layouts will just not work in
91 static TISInputSourceRef current_layout = NULL;
93 static KeyboardLayoutRef current_layout = NULL;
96 /* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
97 * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
99 static guint *keyval_array = NULL;
101 static inline UniChar
102 macroman2ucs (unsigned char c)
104 /* Precalculated table mapping MacRoman-128 to Unicode. Generated
105 by creating single element CFStringRefs then extracting the
108 static const unsigned short table[128] = {
109 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
110 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
111 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
112 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
113 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
114 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
115 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
116 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
117 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
118 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
119 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
120 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
121 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
122 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
123 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
124 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
130 return table[c - 128];
133 const static struct {
136 unsigned int modmask; /* So we can tell when a mod key is pressed/released */
137 } modifier_keys[] = {
138 { 54, GDK_KEY_Meta_R, NSCommandKeyMask },
139 { 55, GDK_KEY_Meta_L, NSCommandKeyMask },
140 { 56, GDK_KEY_Shift_L, NSShiftKeyMask },
141 { 57, GDK_KEY_Caps_Lock, NSAlphaShiftKeyMask },
142 { 58, GDK_KEY_Alt_L, NSAlternateKeyMask },
143 { 59, GDK_KEY_Control_L, NSControlKeyMask },
144 { 60, GDK_KEY_Shift_R, NSShiftKeyMask },
145 { 61, GDK_KEY_Alt_R, NSAlternateKeyMask },
146 { 62, GDK_KEY_Control_R, NSControlKeyMask }
149 const static struct {
152 } function_keys[] = {
162 { 109, GDK_KEY_F10 },
163 { 103, GDK_KEY_F11 },
164 { 111, GDK_KEY_F12 },
165 { 105, GDK_KEY_F13 },
166 { 107, GDK_KEY_F14 },
167 { 113, GDK_KEY_F15 },
171 const static struct {
173 guint normal_keyval, keypad_keyval;
174 } known_numeric_keys[] = {
175 { 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
176 { 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
177 { 69, GDK_KEY_plus, GDK_KEY_KP_Add },
178 { 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
179 { 76, GDK_KEY_Return, GDK_KEY_KP_Enter },
180 { 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
181 { 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
182 { 82, GDK_KEY_0, GDK_KEY_KP_0 },
183 { 83, GDK_KEY_1, GDK_KEY_KP_1 },
184 { 84, GDK_KEY_2, GDK_KEY_KP_2 },
185 { 85, GDK_KEY_3, GDK_KEY_KP_3 },
186 { 86, GDK_KEY_4, GDK_KEY_KP_4 },
187 { 87, GDK_KEY_5, GDK_KEY_KP_5 },
188 { 88, GDK_KEY_6, GDK_KEY_KP_6 },
189 { 89, GDK_KEY_7, GDK_KEY_KP_7 },
190 { 91, GDK_KEY_8, GDK_KEY_KP_8 },
191 { 92, GDK_KEY_9, GDK_KEY_KP_9 }
194 /* These values aren't covered by gdk_unicode_to_keyval */
195 const static struct {
198 } special_ucs_table [] = {
199 { 0x0001, GDK_KEY_Home },
200 { 0x0003, GDK_KEY_Return },
201 { 0x0004, GDK_KEY_End },
202 { 0x0008, GDK_KEY_BackSpace },
203 { 0x0009, GDK_KEY_Tab },
204 { 0x000b, GDK_KEY_Page_Up },
205 { 0x000c, GDK_KEY_Page_Down },
206 { 0x000d, GDK_KEY_Return },
207 { 0x001b, GDK_KEY_Escape },
208 { 0x001c, GDK_KEY_Left },
209 { 0x001d, GDK_KEY_Right },
210 { 0x001e, GDK_KEY_Up },
211 { 0x001f, GDK_KEY_Down },
212 { 0x007f, GDK_KEY_Delete },
213 { 0xf027, GDK_KEY_dead_acute },
214 { 0xf060, GDK_KEY_dead_grave },
215 { 0xf300, GDK_KEY_dead_grave },
216 { 0xf0b4, GDK_KEY_dead_acute },
217 { 0xf301, GDK_KEY_dead_acute },
218 { 0xf385, GDK_KEY_dead_acute },
219 { 0xf05e, GDK_KEY_dead_circumflex },
220 { 0xf2c6, GDK_KEY_dead_circumflex },
221 { 0xf302, GDK_KEY_dead_circumflex },
222 { 0xf07e, GDK_KEY_dead_tilde },
223 { 0xf2dc, GDK_KEY_dead_tilde },
224 { 0xf303, GDK_KEY_dead_tilde },
225 { 0xf342, GDK_KEY_dead_perispomeni },
226 { 0xf0af, GDK_KEY_dead_macron },
227 { 0xf304, GDK_KEY_dead_macron },
228 { 0xf2d8, GDK_KEY_dead_breve },
229 { 0xf306, GDK_KEY_dead_breve },
230 { 0xf2d9, GDK_KEY_dead_abovedot },
231 { 0xf307, GDK_KEY_dead_abovedot },
232 { 0xf0a8, GDK_KEY_dead_diaeresis },
233 { 0xf308, GDK_KEY_dead_diaeresis },
234 { 0xf2da, GDK_KEY_dead_abovering },
235 { 0xf30A, GDK_KEY_dead_abovering },
236 { 0xf022, GDK_KEY_dead_doubleacute },
237 { 0xf2dd, GDK_KEY_dead_doubleacute },
238 { 0xf30B, GDK_KEY_dead_doubleacute },
239 { 0xf2c7, GDK_KEY_dead_caron },
240 { 0xf30C, GDK_KEY_dead_caron },
241 { 0xf0be, GDK_KEY_dead_cedilla },
242 { 0xf327, GDK_KEY_dead_cedilla },
243 { 0xf2db, GDK_KEY_dead_ogonek },
244 { 0xf328, GDK_KEY_dead_ogonek },
245 { 0xfe5d, GDK_KEY_dead_iota },
246 { 0xf323, GDK_KEY_dead_belowdot },
247 { 0xf309, GDK_KEY_dead_hook },
248 { 0xf31B, GDK_KEY_dead_horn },
249 { 0xf02d, GDK_KEY_dead_stroke },
250 { 0xf335, GDK_KEY_dead_stroke },
251 { 0xf336, GDK_KEY_dead_stroke },
252 { 0xf313, GDK_KEY_dead_abovecomma },
253 /* { 0xf313, GDK_KEY_dead_psili }, */
254 { 0xf314, GDK_KEY_dead_abovereversedcomma },
255 /* { 0xf314, GDK_KEY_dead_dasia }, */
256 { 0xf30F, GDK_KEY_dead_doublegrave },
257 { 0xf325, GDK_KEY_dead_belowring },
258 { 0xf2cd, GDK_KEY_dead_belowmacron },
259 { 0xf331, GDK_KEY_dead_belowmacron },
260 { 0xf32D, GDK_KEY_dead_belowcircumflex },
261 { 0xf330, GDK_KEY_dead_belowtilde },
262 { 0xf32E, GDK_KEY_dead_belowbreve },
263 { 0xf324, GDK_KEY_dead_belowdiaeresis },
264 { 0xf311, GDK_KEY_dead_invertedbreve },
265 { 0xf02c, GDK_KEY_dead_belowcomma },
266 { 0xf326, GDK_KEY_dead_belowcomma }
270 maybe_update_keymap (void)
272 const void *chr_data = NULL;
275 TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
276 CFDataRef layout_data_ref;
279 KeyboardLayoutRef new_layout;
280 KeyboardLayoutKind layout_kind;
282 KLGetCurrentKeyboardLayout (&new_layout);
285 if (new_layout != current_layout)
290 g_free (keyval_array);
291 keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
294 layout_data_ref = (CFDataRef) TISGetInputSourceProperty
295 (new_layout, kTISPropertyUnicodeKeyLayoutData);
298 chr_data = CFDataGetBytePtr (layout_data_ref);
300 if (chr_data == NULL)
302 g_error ("cannot get keyboard layout data");
306 /* Get the layout kind */
307 KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
309 /* 8-bit-only keyabord layout */
310 if (layout_kind == kKLKCHRKind)
313 KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
315 for (i = 0; i < NUM_KEYCODES; i++)
318 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
320 p = keyval_array + i * KEYVALS_PER_KEYCODE;
322 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
328 key_code = modifiers[j] | i;
329 c = KeyTranslate (chr_data, key_code, &state);
334 c = KeyTranslate (chr_data, key_code | 128, &state2);
337 if (c != 0 && c != 0x10)
340 gboolean found = FALSE;
342 /* FIXME: some keyboard layouts (e.g. Russian) use
343 * a different 8-bit character set. We should
344 * check for this. Not a serious problem, because
345 * most (all?) of these layouts also have a
348 uc = macroman2ucs (c);
350 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
352 if (special_ucs_table[k].ucs_value == uc)
354 p[j] = special_ucs_table[k].keyval;
360 /* Special-case shift-tab since GTK+ expects
361 * GDK_KEY_ISO_Left_Tab for that.
363 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
364 p[j] = GDK_KEY_ISO_Left_Tab;
367 p[j] = gdk_unicode_to_keyval (uc);
382 /* unicode keyboard layout */
383 else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
386 KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
389 for (i = 0; i < NUM_KEYCODES; i++)
392 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
396 p = keyval_array + i * KEYVALS_PER_KEYCODE;
398 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
405 key_code = modifiers[j] | i;
406 err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
407 (modifiers[j] >> 8) & 0xFF,
410 &state, 4, &nChars, chars);
412 /* FIXME: Theoretically, we can get multiple UTF-16 values;
413 * we should convert them to proper unicode and figure
414 * out whether there are really keyboard layouts that
415 * give us more than one character for one keypress. */
416 if (err == noErr && nChars == 1)
419 gboolean found = FALSE;
421 /* A few <Shift><Option>keys return two
422 * characters, the first of which is U+00a0,
423 * which isn't interesting; so we return the
424 * second. More sophisticated handling is the
425 * job of a GtkIMContext.
427 * If state isn't zero, it means that it's a
428 * dead key of some sort. Some of those are
429 * enumerated in the special_ucs_table with the
430 * high nibble set to f to push it into the
431 * private use range. Here we do the same.
434 chars[nChars - 1] |= 0xf000;
435 uc = chars[nChars - 1];
437 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
439 if (special_ucs_table[k].ucs_value == uc)
441 p[j] = special_ucs_table[k].keyval;
447 /* Special-case shift-tab since GTK+ expects
448 * GDK_KEY_ISO_Left_Tab for that.
450 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
451 p[j] = GDK_KEY_ISO_Left_Tab;
454 p[j] = gdk_unicode_to_keyval (uc);
472 g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
473 " - not supported right now");
477 for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
479 p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
481 if (p[0] == 0 && p[1] == 0 &&
482 p[2] == 0 && p[3] == 0)
483 p[0] = modifier_keys[i].keyval;
486 for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
488 p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
490 p[0] = function_keys[i].keyval;
491 p[1] = p[2] = p[3] = 0;
494 for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
496 p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
498 if (p[0] == known_numeric_keys[i].normal_keyval)
499 p[0] = known_numeric_keys[i].keypad_keyval;
503 g_signal_emit_by_name (default_keymap, "keys_changed");
505 current_layout = new_layout;
509 static PangoDirection
510 gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
512 return PANGO_DIRECTION_NEUTRAL;
516 gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
518 /* FIXME: Can we implement this? */
523 gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
525 /* FIXME: Implement this. */
530 gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
532 /* FIXME: Implement this. */
537 gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap *keymap,
545 maybe_update_keymap ();
548 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
550 for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
554 if (keyval_array[i] != keyval)
559 key.keycode = i / KEYVALS_PER_KEYCODE;
560 key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
563 g_array_append_val (keys_array, key);
566 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
572 gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap *keymap,
573 guint hardware_keycode,
578 GArray *keys_array, *keyvals_array;
582 maybe_update_keymap ();
586 if (hardware_keycode > NUM_KEYCODES)
590 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
595 keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
597 keyvals_array = NULL;
599 p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
601 for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
609 g_array_append_val (keyvals_array, p[i]);
615 key.keycode = hardware_keycode;
619 g_array_append_val (keys_array, key);
624 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
627 *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
629 return *n_entries > 0;
632 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
635 gdk_quartz_keymap_lookup_key (GdkKeymap *keymap,
636 const GdkKeymapKey *key)
638 return GET_KEYVAL (key->keycode, key->group, key->level);
642 translate_keysym (guint hardware_keycode,
644 GdkModifierType state,
645 gint *effective_group,
646 gint *effective_level)
651 level = (state & GDK_SHIFT_MASK) ? 1 : 0;
653 if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
654 (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
657 if (!GET_KEYVAL (hardware_keycode, group, level) &&
658 GET_KEYVAL (hardware_keycode, group, 0))
661 tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
663 if (state & GDK_LOCK_MASK)
665 guint upper = gdk_keyval_to_upper (tmp_keyval);
666 if (upper != tmp_keyval)
671 *effective_group = group;
673 *effective_level = level;
679 gdk_quartz_keymap_translate_keyboard_state (GdkKeymap *keymap,
680 guint hardware_keycode,
681 GdkModifierType state,
684 gint *effective_group,
686 GdkModifierType *consumed_modifiers)
690 guint tmp_modifiers = 0;
692 maybe_update_keymap ();
697 *effective_group = 0;
700 if (consumed_modifiers)
701 *consumed_modifiers = 0;
703 if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
706 /* Check if modifiers modify the keyval */
707 for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
709 if (translate_keysym (hardware_keycode,
710 (bit == GDK_MOD1_MASK) ? 0 : group,
713 translate_keysym (hardware_keycode,
714 (bit == GDK_MOD1_MASK) ? 1 : group,
717 tmp_modifiers |= bit;
720 tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
722 if (consumed_modifiers)
723 *consumed_modifiers = tmp_modifiers;
726 *keyval = tmp_keyval;
732 gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap *keymap,
733 GdkModifierType *state)
735 if (*state & GDK_MOD2_MASK)
736 *state |= GDK_META_MASK;
740 gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap *keymap,
741 GdkModifierType *state)
743 if (*state & GDK_META_MASK)
744 *state |= GDK_MOD2_MASK;
749 static GdkModifierType
750 gdk_quartz_keymap_get_modifier_mask (GdkKeymap *keymap,
751 GdkModifierIntent intent)
755 case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
756 return GDK_MOD2_MASK;
758 case GDK_MODIFIER_INTENT_CONTEXT_MENU:
759 return GDK_CONTROL_MASK;
761 case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
762 return GDK_SHIFT_MASK;
764 case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
765 return GDK_MOD2_MASK;
767 case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
768 return GDK_MOD2_MASK | GDK_CONTROL_MASK;
770 case GDK_MODIFIER_INTENT_SHIFT_GROUP:
771 return GDK_MOD1_MASK;
774 g_return_val_if_reached (0);
778 /* What sort of key event is this? Returns one of
779 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
782 _gdk_quartz_keys_event_type (NSEvent *event)
784 unsigned short keycode;
788 switch ([event type])
791 return GDK_KEY_PRESS;
793 return GDK_KEY_RELEASE;
797 g_assert_not_reached ();
800 /* For flags-changed events, we have to find the special key that caused the
801 * event, and see if it's in the modifier mask. */
802 keycode = [event keyCode];
803 flags = [event modifierFlags];
805 for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
807 if (modifier_keys[i].keycode == keycode)
809 if (flags & modifier_keys[i].modmask)
810 return GDK_KEY_PRESS;
812 return GDK_KEY_RELEASE;
816 /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
817 * events for no good reason. Ignore them! */
822 _gdk_quartz_keys_is_modifier (guint keycode)
826 for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
828 if (modifier_keys[i].modmask == 0)
831 if (modifier_keys[i].keycode == keycode)
839 gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
844 gdk_quartz_keymap_finalize (GObject *object)
846 G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
850 gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
852 GObjectClass *object_class = G_OBJECT_CLASS (klass);
853 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
855 object_class->finalize = gdk_quartz_keymap_finalize;
857 keymap_class->get_direction = gdk_quartz_keymap_get_direction;
858 keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
859 keymap_class->get_caps_lock_state = gdk_quartz_keymap_get_caps_lock_state;
860 keymap_class->get_num_lock_state = gdk_quartz_keymap_get_num_lock_state;
861 keymap_class->get_entries_for_keyval = gdk_quartz_keymap_get_entries_for_keyval;
862 keymap_class->get_entries_for_keycode = gdk_quartz_keymap_get_entries_for_keycode;
863 keymap_class->lookup_key = gdk_quartz_keymap_lookup_key;
864 keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
865 keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
866 keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
867 keymap_class->get_modifier_mask = gdk_quartz_keymap_get_modifier_mask;