]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkkeys-quartz.c
Change FSF Address
[~andy/gtk] / gdk / quartz / gdkkeys-quartz.c
1 /* gdkkeys-quartz.c
2  *
3  * Copyright (C) 2000 Red Hat, Inc.
4  * Copyright (C) 2005 Imendio AB
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 /* Some parts of this code come from quartzKeyboard.c,
20  * from the Apple X11 Server.
21  *
22  * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
23  *
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:
31  *
32  *  The above copyright notice and this permission notice shall be
33  *  included in all copies or substantial portions of the Software.
34  *
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.
43  *
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.
48  */
49
50 #include "config.h"
51
52 #include <Carbon/Carbon.h>
53 #include <AppKit/NSEvent.h>
54 #include "gdk.h"
55 #include "gdkquartzkeys.h"
56 #include "gdkkeysprivate.h"
57 #include "gdkkeysyms.h"
58
59 #define NUM_KEYCODES 128
60 #define KEYVALS_PER_KEYCODE 4
61
62 static GdkKeymap *default_keymap = NULL;
63
64 struct _GdkQuartzKeymap
65 {
66   GdkKeymap keymap;
67 };
68
69 struct _GdkQuartzKeymapClass
70 {
71   GdkKeymapClass keymap_class;
72 };
73
74 G_DEFINE_TYPE (GdkQuartzKeymap, gdk_quartz_keymap, GDK_TYPE_KEYMAP)
75
76 GdkKeymap *
77 _gdk_quartz_display_get_keymap (GdkDisplay *display)
78 {
79   if (default_keymap == NULL)
80     default_keymap = g_object_new (gdk_quartz_keymap_get_type (), NULL);
81
82   return default_keymap;
83 }
84
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
88  * 64-bit.
89  */
90 #ifdef __LP64__
91 static TISInputSourceRef current_layout = NULL;
92 #else
93 static KeyboardLayoutRef current_layout = NULL;
94 #endif
95
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);
98  */
99 static guint *keyval_array = NULL;
100
101 static inline UniChar
102 macroman2ucs (unsigned char c)
103 {
104   /* Precalculated table mapping MacRoman-128 to Unicode. Generated
105      by creating single element CFStringRefs then extracting the
106      first character. */
107   
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
125   };
126
127   if (c < 128)
128     return c;
129   else
130     return table[c - 128];
131 }
132
133 const static struct {
134   guint keycode;
135   guint keyval;
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 }
147 };
148
149 const static struct {
150   guint keycode;
151   guint keyval;
152 } function_keys[] = {
153   { 122, GDK_KEY_F1 },
154   { 120, GDK_KEY_F2 },
155   {  99, GDK_KEY_F3 },
156   { 118, GDK_KEY_F4 },
157   {  96, GDK_KEY_F5 },
158   {  97, GDK_KEY_F6 },
159   {  98, GDK_KEY_F7 },
160   { 100, GDK_KEY_F8 },
161   { 101, GDK_KEY_F9 },
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 },
168   { 106, GDK_KEY_F16 }
169 };
170
171 const static struct {
172   guint keycode;
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 }
192 };
193
194 /* These values aren't covered by gdk_unicode_to_keyval */
195 const static struct {
196   gunichar ucs_value;
197   guint keyval;
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 }
266 };
267
268 static void
269 maybe_update_keymap (void)
270 {
271   const void *chr_data = NULL;
272
273 #ifdef __LP64__
274   TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
275   CFDataRef layout_data_ref;
276
277 #else
278   KeyboardLayoutRef new_layout;
279   KeyboardLayoutKind layout_kind;
280
281   KLGetCurrentKeyboardLayout (&new_layout);
282 #endif
283
284   if (new_layout != current_layout)
285     {
286       guint *p;
287       int i;
288
289       g_free (keyval_array);
290       keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
291
292 #ifdef __LP64__
293       layout_data_ref = (CFDataRef) TISGetInputSourceProperty
294         (new_layout, kTISPropertyUnicodeKeyLayoutData);
295
296       if (layout_data_ref)
297         chr_data = CFDataGetBytePtr (layout_data_ref);
298
299       if (chr_data == NULL)
300         {
301           g_error ("cannot get keyboard layout data");
302           return;
303         }
304 #else
305       /* Get the layout kind */
306       KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
307
308       /* 8-bit-only keyabord layout */
309       if (layout_kind == kKLKCHRKind)
310         { 
311           /* Get chr data */
312           KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
313           
314           for (i = 0; i < NUM_KEYCODES; i++) 
315             {
316               int j;
317               UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
318
319               p = keyval_array + i * KEYVALS_PER_KEYCODE;
320               
321               for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
322                 {
323                   UInt32 c, state = 0;
324                   UInt16 key_code;
325                   UniChar uc;
326                   
327                   key_code = modifiers[j] | i;
328                   c = KeyTranslate (chr_data, key_code, &state);
329
330                   if (state != 0)
331                     {
332                       UInt32 state2 = 0;
333                       c = KeyTranslate (chr_data, key_code | 128, &state2);
334                     }
335
336                   if (c != 0 && c != 0x10)
337                     {
338                       int k;
339                       gboolean found = FALSE;
340
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
345                        * uchr version. 
346                        */
347                       uc = macroman2ucs (c);
348
349                       for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++) 
350                         {
351                           if (special_ucs_table[k].ucs_value == uc)
352                             {
353                               p[j] = special_ucs_table[k].keyval;
354                               found = TRUE;
355                               break;
356                             }
357                         }
358                       
359                       /* Special-case shift-tab since GTK+ expects
360                        * GDK_KEY_ISO_Left_Tab for that.
361                        */
362                       if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
363                         p[j] = GDK_KEY_ISO_Left_Tab;
364
365                       if (!found)
366                         p[j] = gdk_unicode_to_keyval (uc);
367                     }
368                 }
369
370               if (p[3] == p[2])
371                 p[3] = 0;
372               if (p[2] == p[1])
373                 p[2] = 0;
374               if (p[1] == p[0])
375                 p[1] = 0;
376               if (p[0] == p[2] && 
377                   p[1] == p[3])
378                 p[2] = p[3] = 0;
379             }
380         }
381       /* unicode keyboard layout */
382       else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
383         { 
384           /* Get chr data */
385           KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
386 #endif
387           
388           for (i = 0; i < NUM_KEYCODES; i++) 
389             {
390               int j;
391               UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
392               UniChar chars[4];
393               UniCharCount nChars;
394
395               p = keyval_array + i * KEYVALS_PER_KEYCODE;
396
397               for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
398                 {
399                   UInt32 state = 0;
400                   OSStatus err;
401                   UInt16 key_code;
402                   UniChar uc;
403                   
404                   key_code = modifiers[j] | i;
405                   err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
406                                         (modifiers[j] >> 8) & 0xFF,
407                                         LMGetKbdType(),
408                                         0,
409                                         &state, 4, &nChars, chars);
410
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)
416                     {
417                       int k;
418                       gboolean found = FALSE;
419
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.
425                        *
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.
431                        */
432                       if (state != 0)
433                         chars[nChars - 1] |= 0xf000;
434                       uc = chars[nChars - 1];
435
436                       for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++) 
437                         {
438                           if (special_ucs_table[k].ucs_value == uc)
439                             {
440                               p[j] = special_ucs_table[k].keyval;
441                               found = TRUE;
442                               break;
443                             }
444                         }
445
446                       /* Special-case shift-tab since GTK+ expects
447                        * GDK_KEY_ISO_Left_Tab for that.
448                        */
449                       if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
450                         p[j] = GDK_KEY_ISO_Left_Tab;
451
452                       if (!found)
453                         p[j] = gdk_unicode_to_keyval (uc);
454                     }
455                 }
456
457               if (p[3] == p[2])
458                 p[3] = 0;
459               if (p[2] == p[1])
460                 p[2] = 0;
461               if (p[1] == p[0])
462                 p[1] = 0;
463               if (p[0] == p[2] && 
464                   p[1] == p[3])
465                 p[2] = p[3] = 0;
466             }
467 #ifndef __LP64__
468         }
469       else
470         {
471           g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
472                    " - not supported right now");
473         }
474 #endif
475
476       for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
477         {
478           p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
479
480           if (p[0] == 0 && p[1] == 0 && 
481               p[2] == 0 && p[3] == 0)
482             p[0] = modifier_keys[i].keyval;
483         }
484
485       for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
486         {
487           p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
488
489           p[0] = function_keys[i].keyval;
490           p[1] = p[2] = p[3] = 0;
491         }
492
493       for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
494         {
495           p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
496
497           if (p[0] == known_numeric_keys[i].normal_keyval)
498             p[0] = known_numeric_keys[i].keypad_keyval;
499         }
500       
501       if (current_layout)
502         g_signal_emit_by_name (default_keymap, "keys_changed");
503
504       current_layout = new_layout;
505     }
506 }
507
508 static PangoDirection
509 gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
510 {
511   return PANGO_DIRECTION_NEUTRAL;
512 }
513
514 static gboolean
515 gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
516 {
517   /* FIXME: Can we implement this? */
518   return FALSE;
519 }
520
521 static gboolean
522 gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
523 {
524   /* FIXME: Implement this. */
525   return FALSE;
526 }
527
528 static gboolean
529 gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
530 {
531   /* FIXME: Implement this. */
532   return FALSE;
533 }
534
535 static gboolean
536 gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
537                                           guint          keyval,
538                                           GdkKeymapKey **keys,
539                                           gint          *n_keys)
540 {
541   GArray *keys_array;
542   int i;
543
544   maybe_update_keymap ();
545
546   *n_keys = 0;
547   keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
548
549   for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
550     {
551       GdkKeymapKey key;
552
553       if (keyval_array[i] != keyval)
554         continue;
555
556       (*n_keys)++;
557
558       key.keycode = i / KEYVALS_PER_KEYCODE;
559       key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
560       key.level = i % 2;
561
562       g_array_append_val (keys_array, key);
563     }
564
565   *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
566   
567   return *n_keys > 0;;
568 }
569
570 static gboolean
571 gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
572                                            guint          hardware_keycode,
573                                            GdkKeymapKey **keys,
574                                            guint        **keyvals,
575                                            gint          *n_entries)
576 {
577   GArray *keys_array, *keyvals_array;
578   int i;
579   guint *p;
580
581   maybe_update_keymap ();
582
583   *n_entries = 0;
584
585   if (hardware_keycode > NUM_KEYCODES)
586     return FALSE;
587
588   if (keys)
589     keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
590   else
591     keys_array = NULL;
592
593   if (keyvals)
594     keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
595   else
596     keyvals_array = NULL;
597
598   p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
599   
600   for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
601     {
602       if (!p[i])
603         continue;
604
605       (*n_entries)++;
606       
607       if (keyvals_array)
608         g_array_append_val (keyvals_array, p[i]);
609
610       if (keys_array)
611         {
612           GdkKeymapKey key;
613
614           key.keycode = hardware_keycode;
615           key.group = i >= 2;
616           key.level = i % 2;
617
618           g_array_append_val (keys_array, key);
619         }
620     }
621   
622   if (keys)
623     *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
624
625   if (keyvals)
626     *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
627
628   return *n_entries > 0;
629 }
630
631 static guint
632 gdk_quartz_keymap_lookup_key (GdkKeymap          *keymap,
633                               const GdkKeymapKey *key)
634 {
635   /* FIXME: Implement */
636
637   return 0;
638 }
639
640 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
641
642 static guint
643 translate_keysym (guint           hardware_keycode,
644                   gint            group,
645                   GdkModifierType state,
646                   gint           *effective_group,
647                   gint           *effective_level)
648 {
649   gint level;
650   guint tmp_keyval;
651
652   level = (state & GDK_SHIFT_MASK) ? 1 : 0;
653
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)))
656     group = 0;
657
658   if (!GET_KEYVAL (hardware_keycode, group, level) &&
659       GET_KEYVAL (hardware_keycode, group, 0))
660     level = 0;
661
662   tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
663
664   if (state & GDK_LOCK_MASK)
665     {
666       guint upper = gdk_keyval_to_upper (tmp_keyval);
667       if (upper != tmp_keyval)
668         tmp_keyval = upper;
669     }
670
671   if (effective_group)
672     *effective_group = group;
673   if (effective_level)
674     *effective_level = level;
675
676   return tmp_keyval;
677 }
678
679 static gboolean
680 gdk_quartz_keymap_translate_keyboard_state (GdkKeymap       *keymap,
681                                             guint            hardware_keycode,
682                                             GdkModifierType  state,
683                                             gint             group,
684                                             guint           *keyval,
685                                             gint            *effective_group,
686                                             gint            *level,
687                                             GdkModifierType *consumed_modifiers)
688 {
689   guint tmp_keyval;
690   GdkModifierType bit;
691   guint tmp_modifiers = 0;
692
693   maybe_update_keymap ();
694
695   if (keyval)
696     *keyval = 0;
697   if (effective_group)
698     *effective_group = 0;
699   if (level)
700     *level = 0;
701   if (consumed_modifiers)
702     *consumed_modifiers = 0;
703
704   if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
705     return FALSE;
706
707   /* Check if modifiers modify the keyval */
708   for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
709     {
710       if (translate_keysym (hardware_keycode,
711                             (bit == GDK_MOD1_MASK) ? 0 : group,
712                             state & ~bit,
713                             NULL, NULL) !=
714           translate_keysym (hardware_keycode,
715                             (bit == GDK_MOD1_MASK) ? 1 : group,
716                             state | bit,
717                             NULL, NULL))
718         tmp_modifiers |= bit;
719     }
720
721   tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
722
723   if (consumed_modifiers)
724     *consumed_modifiers = tmp_modifiers;
725
726   if (keyval)
727     *keyval = tmp_keyval; 
728
729   return TRUE;
730 }
731
732 static void
733 gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
734                                          GdkModifierType *state)
735 {
736   if (*state & GDK_MOD2_MASK)
737     *state |= GDK_META_MASK;
738 }
739
740 static gboolean
741 gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
742                                          GdkModifierType *state)
743 {
744   if (*state & GDK_META_MASK)
745     *state |= GDK_MOD2_MASK;
746
747   return TRUE;
748 }
749
750 static GdkModifierType
751 gdk_quartz_keymap_get_modifier_mask (GdkKeymap         *keymap,
752                                      GdkModifierIntent  intent)
753 {
754   switch (intent)
755     {
756     case GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR:
757       return GDK_MOD2_MASK;
758
759     case GDK_MODIFIER_INTENT_CONTEXT_MENU:
760       return GDK_CONTROL_MASK;
761
762     case GDK_MODIFIER_INTENT_EXTEND_SELECTION:
763       return GDK_SHIFT_MASK;
764
765     case GDK_MODIFIER_INTENT_MODIFY_SELECTION:
766       return GDK_MOD2_MASK;
767
768     case GDK_MODIFIER_INTENT_NO_TEXT_INPUT:
769       return GDK_MOD2_MASK | GDK_CONTROL_MASK;
770
771     case GDK_MODIFIER_INTENT_SHIFT_GROUP:
772       return GDK_MOD1_MASK;
773
774     default:
775       g_return_val_if_reached (0);
776     }
777 }
778
779 /* What sort of key event is this? Returns one of
780  * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
781  */
782 GdkEventType
783 _gdk_quartz_keys_event_type (NSEvent *event)
784 {
785   unsigned short keycode;
786   unsigned int flags;
787   int i;
788   
789   switch ([event type])
790     {
791     case NSKeyDown:
792       return GDK_KEY_PRESS;
793     case NSKeyUp:
794       return GDK_KEY_RELEASE;
795     case NSFlagsChanged:
796       break;
797     default:
798       g_assert_not_reached ();
799     }
800   
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];
805   
806   for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
807     {
808       if (modifier_keys[i].keycode == keycode)
809         {
810           if (flags & modifier_keys[i].modmask)
811             return GDK_KEY_PRESS;
812           else
813             return GDK_KEY_RELEASE;
814         }
815     }
816   
817   /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
818    * events for no good reason. Ignore them! */
819   return GDK_NOTHING;
820 }
821
822 gboolean
823 _gdk_quartz_keys_is_modifier (guint keycode)
824 {
825   gint i;
826   
827   for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
828     {
829       if (modifier_keys[i].modmask == 0)
830         break;
831
832       if (modifier_keys[i].keycode == keycode)
833         return TRUE;
834     }
835
836   return FALSE;
837 }
838
839 static void
840 gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
841 {
842 }
843
844 static void
845 gdk_quartz_keymap_finalize (GObject *object)
846 {
847   G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
848 }
849
850 static void
851 gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
852 {
853   GObjectClass *object_class = G_OBJECT_CLASS (klass);
854   GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
855
856   object_class->finalize = gdk_quartz_keymap_finalize;
857
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;
869 }