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, 0x01000003, 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 { 0xf303, GDK_KEY_dead_tilde },
224 { 0xf342, GDK_KEY_dead_perispomeni },
225 { 0xf0af, GDK_KEY_dead_macron },
226 { 0xf304, GDK_KEY_dead_macron },
227 { 0xf2d8, GDK_KEY_dead_breve },
228 { 0xf306, GDK_KEY_dead_breve },
229 { 0xf2d9, GDK_KEY_dead_abovedot },
230 { 0xf307, GDK_KEY_dead_abovedot },
231 { 0xf0a8, GDK_KEY_dead_diaeresis },
232 { 0xf308, GDK_KEY_dead_diaeresis },
233 { 0xf2da, GDK_KEY_dead_abovering },
234 { 0xf30A, GDK_KEY_dead_abovering },
235 { 0xf022, GDK_KEY_dead_doubleacute },
236 { 0xf2dd, GDK_KEY_dead_doubleacute },
237 { 0xf30B, GDK_KEY_dead_doubleacute },
238 { 0xf2c7, GDK_KEY_dead_caron },
239 { 0xf30C, GDK_KEY_dead_caron },
240 { 0xf0be, GDK_KEY_dead_cedilla },
241 { 0xf327, GDK_KEY_dead_cedilla },
242 { 0xf2db, GDK_KEY_dead_ogonek },
243 { 0xf328, GDK_KEY_dead_ogonek },
244 { 0xfe5d, GDK_KEY_dead_iota },
245 { 0xf323, GDK_KEY_dead_belowdot },
246 { 0xf309, GDK_KEY_dead_hook },
247 { 0xf31B, GDK_KEY_dead_horn },
248 { 0xf02d, GDK_KEY_dead_stroke },
249 { 0xf335, GDK_KEY_dead_stroke },
250 { 0xf336, GDK_KEY_dead_stroke },
251 { 0xf313, GDK_KEY_dead_abovecomma },
252 /* { 0xf313, GDK_KEY_dead_psili }, */
253 { 0xf314, GDK_KEY_dead_abovereversedcomma },
254 /* { 0xf314, GDK_KEY_dead_dasia }, */
255 { 0xf30F, GDK_KEY_dead_doublegrave },
256 { 0xf325, GDK_KEY_dead_belowring },
257 { 0xf2cd, GDK_KEY_dead_belowmacron },
258 { 0xf331, GDK_KEY_dead_belowmacron },
259 { 0xf32D, GDK_KEY_dead_belowcircumflex },
260 { 0xf330, GDK_KEY_dead_belowtilde },
261 { 0xf32E, GDK_KEY_dead_belowbreve },
262 { 0xf324, GDK_KEY_dead_belowdiaeresis },
263 { 0xf311, GDK_KEY_dead_invertedbreve },
264 { 0xf02c, GDK_KEY_dead_belowcomma },
265 { 0xf326, GDK_KEY_dead_belowcomma }
269 maybe_update_keymap (void)
271 const void *chr_data = NULL;
274 TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
275 CFDataRef layout_data_ref;
278 KeyboardLayoutRef new_layout;
279 KeyboardLayoutKind layout_kind;
281 KLGetCurrentKeyboardLayout (&new_layout);
284 if (new_layout != current_layout)
289 g_free (keyval_array);
290 keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
293 layout_data_ref = (CFDataRef) TISGetInputSourceProperty
294 (new_layout, kTISPropertyUnicodeKeyLayoutData);
297 chr_data = CFDataGetBytePtr (layout_data_ref);
299 if (chr_data == NULL)
301 g_error ("cannot get keyboard layout data");
305 /* Get the layout kind */
306 KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
308 /* 8-bit-only keyabord layout */
309 if (layout_kind == kKLKCHRKind)
312 KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
314 for (i = 0; i < NUM_KEYCODES; i++)
317 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
319 p = keyval_array + i * KEYVALS_PER_KEYCODE;
321 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
327 key_code = modifiers[j] | i;
328 c = KeyTranslate (chr_data, key_code, &state);
333 c = KeyTranslate (chr_data, key_code | 128, &state2);
336 if (c != 0 && c != 0x10)
339 gboolean found = FALSE;
341 /* FIXME: some keyboard layouts (e.g. Russian) use
342 * a different 8-bit character set. We should
343 * check for this. Not a serious problem, because
344 * most (all?) of these layouts also have a
347 uc = macroman2ucs (c);
349 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
351 if (special_ucs_table[k].ucs_value == uc)
353 p[j] = special_ucs_table[k].keyval;
359 /* Special-case shift-tab since GTK+ expects
360 * GDK_KEY_ISO_Left_Tab for that.
362 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
363 p[j] = GDK_KEY_ISO_Left_Tab;
366 p[j] = gdk_unicode_to_keyval (uc);
381 /* unicode keyboard layout */
382 else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
385 KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
388 for (i = 0; i < NUM_KEYCODES; i++)
391 UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
395 p = keyval_array + i * KEYVALS_PER_KEYCODE;
397 for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
404 key_code = modifiers[j] | i;
405 err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
406 (modifiers[j] >> 8) & 0xFF,
409 &state, 4, &nChars, chars);
411 /* FIXME: Theoretically, we can get multiple UTF-16 values;
412 * we should convert them to proper unicode and figure
413 * out whether there are really keyboard layouts that
414 * give us more than one character for one keypress. */
415 if (err == noErr && nChars == 1)
418 gboolean found = FALSE;
420 /* A few <Shift><Option>keys return two
421 * characters, the first of which is U+00a0,
422 * which isn't interesting; so we return the
423 * second. More sophisticated handling is the
424 * job of a GtkIMContext.
426 * If state isn't zero, it means that it's a
427 * dead key of some sort. Some of those are
428 * enumerated in the special_ucs_table with the
429 * high nibble set to f to push it into the
430 * private use range. Here we do the same.
433 chars[nChars - 1] |= 0xf000;
434 uc = chars[nChars - 1];
436 for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
438 if (special_ucs_table[k].ucs_value == uc)
440 p[j] = special_ucs_table[k].keyval;
446 /* Special-case shift-tab since GTK+ expects
447 * GDK_KEY_ISO_Left_Tab for that.
449 if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
450 p[j] = GDK_KEY_ISO_Left_Tab;
453 p[j] = gdk_unicode_to_keyval (uc);
471 g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
472 " - not supported right now");
476 for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
478 p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
480 if (p[0] == 0 && p[1] == 0 &&
481 p[2] == 0 && p[3] == 0)
482 p[0] = modifier_keys[i].keyval;
485 for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
487 p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
489 p[0] = function_keys[i].keyval;
490 p[1] = p[2] = p[3] = 0;
493 for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
495 p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
497 if (p[0] == known_numeric_keys[i].normal_keyval)
498 p[0] = known_numeric_keys[i].keypad_keyval;
502 g_signal_emit_by_name (default_keymap, "keys_changed");
504 current_layout = new_layout;
508 static PangoDirection
509 gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
511 return PANGO_DIRECTION_NEUTRAL;
515 gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
517 /* FIXME: Can we implement this? */
522 gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
524 /* FIXME: Implement this. */
529 gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
531 /* FIXME: Implement this. */
536 gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap *keymap,
544 maybe_update_keymap ();
547 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
549 for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
553 if (keyval_array[i] != keyval)
558 key.keycode = i / KEYVALS_PER_KEYCODE;
559 key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
562 g_array_append_val (keys_array, key);
565 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
571 gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap *keymap,
572 guint hardware_keycode,
577 GArray *keys_array, *keyvals_array;
581 maybe_update_keymap ();
585 if (hardware_keycode > NUM_KEYCODES)
589 keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
594 keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
596 keyvals_array = NULL;
598 p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
600 for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
608 g_array_append_val (keyvals_array, p[i]);
614 key.keycode = hardware_keycode;
618 g_array_append_val (keys_array, key);
623 *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
626 *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
628 return *n_entries > 0;
632 gdk_quartz_keymap_lookup_key (GdkKeymap *keymap,
633 const GdkKeymapKey *key)
635 /* FIXME: Implement */
640 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
643 translate_keysym (guint hardware_keycode,
645 GdkModifierType state,
646 gint *effective_group,
647 gint *effective_level)
652 level = (state & GDK_SHIFT_MASK) ? 1 : 0;
654 if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
655 (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
658 if (!GET_KEYVAL (hardware_keycode, group, level) &&
659 GET_KEYVAL (hardware_keycode, group, 0))
662 tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
664 if (state & GDK_LOCK_MASK)
666 guint upper = gdk_keyval_to_upper (tmp_keyval);
667 if (upper != tmp_keyval)
672 *effective_group = group;
674 *effective_level = level;
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 modifiers modify the keyval */
708 for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
710 if (translate_keysym (hardware_keycode,
711 (bit == GDK_MOD1_MASK) ? 0 : group,
714 translate_keysym (hardware_keycode,
715 (bit == GDK_MOD1_MASK) ? 1 : group,
718 tmp_modifiers |= bit;
721 tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
723 if (consumed_modifiers)
724 *consumed_modifiers = tmp_modifiers;
727 *keyval = tmp_keyval;
733 gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap *keymap,
734 GdkModifierType *state)
736 if (*state & GDK_MOD2_MASK)
737 *state |= GDK_META_MASK;
741 gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap *keymap,
742 GdkModifierType *state)
744 if (*state & GDK_META_MASK)
745 *state |= GDK_MOD2_MASK;
750 static GdkModifierType
751 gdk_quartz_keymap_get_modifier_mask (GdkKeymap *keymap,
752 GdkModifierIntent intent)
756 case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
757 return GDK_MOD2_MASK;
759 case GDK_MODIFIER_INTENT_CONTEXT_MENU:
760 return GDK_CONTROL_MASK;
762 case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
763 return GDK_SHIFT_MASK;
765 case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
766 return GDK_MOD2_MASK;
768 case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
769 return GDK_MOD2_MASK | GDK_CONTROL_MASK;
771 case GDK_MODIFIER_INTENT_SHIFT_GROUP:
772 return GDK_MOD1_MASK;
775 g_return_val_if_reached (0);
779 /* What sort of key event is this? Returns one of
780 * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
783 _gdk_quartz_keys_event_type (NSEvent *event)
785 unsigned short keycode;
789 switch ([event type])
792 return GDK_KEY_PRESS;
794 return GDK_KEY_RELEASE;
798 g_assert_not_reached ();
801 /* For flags-changed events, we have to find the special key that caused the
802 * event, and see if it's in the modifier mask. */
803 keycode = [event keyCode];
804 flags = [event modifierFlags];
806 for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
808 if (modifier_keys[i].keycode == keycode)
810 if (flags & modifier_keys[i].modmask)
811 return GDK_KEY_PRESS;
813 return GDK_KEY_RELEASE;
817 /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
818 * events for no good reason. Ignore them! */
823 _gdk_quartz_keys_is_modifier (guint keycode)
827 for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
829 if (modifier_keys[i].modmask == 0)
832 if (modifier_keys[i].keycode == keycode)
840 gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
845 gdk_quartz_keymap_finalize (GObject *object)
847 G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
851 gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
853 GObjectClass *object_class = G_OBJECT_CLASS (klass);
854 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
856 object_class->finalize = gdk_quartz_keymap_finalize;
858 keymap_class->get_direction = gdk_quartz_keymap_get_direction;
859 keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
860 keymap_class->get_caps_lock_state = gdk_quartz_keymap_get_caps_lock_state;
861 keymap_class->get_num_lock_state = gdk_quartz_keymap_get_num_lock_state;
862 keymap_class->get_entries_for_keyval = gdk_quartz_keymap_get_entries_for_keyval;
863 keymap_class->get_entries_for_keycode = gdk_quartz_keymap_get_entries_for_keycode;
864 keymap_class->lookup_key = gdk_quartz_keymap_lookup_key;
865 keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
866 keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
867 keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
868 keymap_class->get_modifier_mask = gdk_quartz_keymap_get_modifier_mask;