]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkkeys-quartz.c
Add quartz backend.
[~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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 /* Some parts of this code come from quartzKeyboard.c,
22  * from the Apple X11 Server.
23  *
24  * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
25  *
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:
33  *
34  *  The above copyright notice and this permission notice shall be
35  *  included in all copies or substantial portions of the Software.
36  *
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.
45  *
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.
50  */
51
52 #include <config.h>
53
54 #include <Carbon/Carbon.h>
55 #include "gdk.h"
56 #include "gdkkeysyms.h"
57
58 #define NUM_KEYCODES 128
59 #define KEYVALS_PER_KEYCODE 4
60
61 static GdkKeymap *default_keymap = NULL;
62
63 static KeyboardLayoutRef current_layout = NULL;
64
65 /* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
66  * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
67  */
68 static guint *keyval_array = NULL;
69
70 static inline UniChar
71 macroman2ucs (unsigned char c)
72 {
73   /* Precalculated table mapping MacRoman-128 to Unicode. Generated
74      by creating single element CFStringRefs then extracting the
75      first character. */
76   
77   static const unsigned short table[128] = {
78     0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
79     0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
80     0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
81     0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
82     0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
83     0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
84     0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
85     0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
86     0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
87     0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
88     0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
89     0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
90     0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
91     0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
92     0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
93     0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
94   };
95
96   if (c < 128)
97     return c;
98   else
99     return table[c - 128];
100 }
101
102 const static struct {
103   guint keycode;
104   guint keyval;
105 } known_keys[] = {
106   {  55, GDK_Meta_L },
107   {  56, GDK_Shift_L },
108   {  57, GDK_Caps_Lock },
109   {  58, GDK_Alt_L },
110   {  59, GDK_Control_L },
111   {  60, GDK_Shift_R },
112   {  61, GDK_Alt_R },
113   {  62, GDK_Control_R },
114   { 122, GDK_F1 },
115   { 120, GDK_F2 },
116   {  99, GDK_F3 },
117   { 118, GDK_F4 },
118   {  96, GDK_F5 },
119   {  97, GDK_F6 },
120   {  98, GDK_F7 },
121   { 100, GDK_F8 },
122   { 101, GDK_F9 },
123   { 109, GDK_F10 },
124   { 103, GDK_F11 },
125   { 111, GDK_F12 },
126   { 105, GDK_F13 },
127   { 107, GDK_F14 },
128   { 113, GDK_F15 },
129 };
130
131 const static struct {
132   guint keycode;
133   guint normal_keyval, keypad_keyval;
134 } known_numeric_keys[] = {
135   { 65, GDK_period, GDK_KP_Decimal },
136   { 67, GDK_asterisk, GDK_KP_Multiply },
137   { 69, GDK_plus, GDK_KP_Add },
138   { 75, GDK_slash, GDK_KP_Divide },
139   { 76, 0x01000003, GDK_KP_Enter },
140   { 78, GDK_minus, GDK_KP_Subtract },
141   { 81, GDK_equal, GDK_KP_Equal },
142   { 82, GDK_0, GDK_KP_0 },
143   { 83, GDK_1, GDK_KP_1 },
144   { 84, GDK_2, GDK_KP_2 },
145   { 85, GDK_3, GDK_KP_3 },
146   { 86, GDK_4, GDK_KP_4 },
147   { 87, GDK_5, GDK_KP_5 },
148   { 88, GDK_6, GDK_KP_6 },
149   { 89, GDK_7, GDK_KP_7 },
150   { 91, GDK_8, GDK_KP_8 },
151   { 92, GDK_9, GDK_KP_9 },
152 };
153
154 /* These values aren't covered by gdk_unicode_to_keyval */
155 const static struct {
156   gunichar ucs_value;
157   guint keyval;
158 } special_ucs_table [] = {
159   { 0x0001, GDK_Home },
160   { 0x0008, GDK_BackSpace },
161   { 0x0009, GDK_Tab },
162   { 0x000d, GDK_Return },
163   { 0x001c, GDK_Left },
164   { 0x001d, GDK_Right },
165   { 0x001e, GDK_Up },
166   { 0x001f, GDK_Down },
167 };
168
169 static void
170 maybe_update_keymap (void)
171 {
172   KeyboardLayoutRef new_layout;
173
174   KLGetCurrentKeyboardLayout (&new_layout);
175
176   if (new_layout != current_layout)
177     {
178       guint *p;
179       int i;
180
181       KeyboardLayoutKind layout_kind;
182       
183       g_free (keyval_array);
184       keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
185
186       /* Get the layout kind */
187       KLGetKeyboardLayoutProperty (new_layout, kKLKind, &layout_kind);
188
189       /* FIXME: When we have UCHR support, I think that should be preffered
190        * if a keymap has both.
191        */
192       if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLKCHRKind)
193         {
194           const void *chr_data;
195
196           /* Get chr data */
197           KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (void **)&chr_data);
198           
199           for (i = 0; i < NUM_KEYCODES; i++) 
200             {
201               int j;
202               UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey|optionKey};
203
204               p = keyval_array + i * KEYVALS_PER_KEYCODE;
205
206               for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
207                 {
208                   UInt32 c, state = 0;
209                   UInt16 key_code;
210                   UniChar uc;
211                   
212                   key_code = modifiers[j]|i;
213                   c = KeyTranslate (chr_data, key_code, &state);
214
215                   if (state != 0)
216                     {
217                       UInt32 state2 = 0;
218                       c = KeyTranslate (chr_data, key_code | 128, &state2);
219                     }
220
221                   if (c != 0 && c != 0x10)
222                     {
223                       guint keyval;
224                       int k;
225                       gboolean found = FALSE;
226
227                       uc = macroman2ucs (c);
228                       
229                       for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++) 
230                         {
231                           if (special_ucs_table[k].ucs_value == uc)
232                             {
233                               p[j] = special_ucs_table[k].keyval;
234                               found = TRUE;
235                               break;
236                             }
237                         }
238                       
239                       if (!found)
240                         p[j] = gdk_unicode_to_keyval (uc);
241                     }
242                 }
243
244               if (p[3] == p[2])
245                 p[3] = 0;
246               if (p[2] == p[1])
247                 p[2] = 0;
248               if (p[1] == p[0])
249                 p[1] = 0;
250               if (p[0] == p[2] && 
251                   p[1] == p[3])
252                 p[2] = p[3] = 0;
253             }
254         }
255       else
256         {
257           g_error ("uchr type layouts aren't supported right now");
258         }
259
260       for (i = 0; i < G_N_ELEMENTS (known_keys); i++)
261         {
262           p = keyval_array + known_keys[i].keycode * KEYVALS_PER_KEYCODE;
263
264           if (p[0] == 0 && p[1] == 0 && 
265               p[2] == 0 && p[3] == 0)
266             p[0] = known_keys[i].keyval;
267         }
268
269       for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
270         {
271           p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
272
273           if (p[0] == known_numeric_keys[i].normal_keyval);
274               p[0] = known_numeric_keys[i].keypad_keyval;
275         }
276       
277       if (current_layout)
278         g_signal_emit_by_name (default_keymap, "keys_changed");
279
280       current_layout = new_layout;
281     }
282 }
283
284 GdkKeymap *
285 gdk_keymap_get_for_display (GdkDisplay *display)
286 {
287   g_return_val_if_fail (display == gdk_display_get_default (), NULL);
288
289   if (default_keymap == NULL)
290     default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
291
292   return default_keymap;
293 }
294
295 PangoDirection
296 gdk_keymap_get_direction (GdkKeymap *keymap)
297 {
298   return PANGO_DIRECTION_NEUTRAL;
299 }
300
301 gboolean
302 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
303                                    guint          keyval,
304                                    GdkKeymapKey **keys,
305                                    gint          *n_keys)
306 {
307   GArray *keys_array;
308   int i;
309
310   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
311   g_return_val_if_fail (keys != NULL, FALSE);
312   g_return_val_if_fail (n_keys != NULL, FALSE);
313   g_return_val_if_fail (keyval != 0, FALSE);
314
315   maybe_update_keymap ();
316
317   *n_keys = 0;
318   keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
319
320   for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
321     {
322       GdkKeymapKey key;
323
324       if (keyval_array[i] != keyval)
325         continue;
326
327       (*n_keys)++;
328
329       key.keycode = i / KEYVALS_PER_KEYCODE;
330       key.group = 0;
331       key.level = i % KEYVALS_PER_KEYCODE;
332
333       g_array_append_val (keys_array, key);
334     }
335
336   *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
337   
338   return *n_keys > 0;;
339 }
340
341 gboolean
342 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
343                                     guint          hardware_keycode,
344                                     GdkKeymapKey **keys,
345                                     guint        **keyvals,
346                                     gint          *n_entries)
347 {
348   GArray *keys_array, *keyvals_array;
349   int i;
350   guint *p;
351
352   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
353   g_return_val_if_fail (n_entries != NULL, FALSE);
354
355   maybe_update_keymap ();
356
357   *n_entries = 0;
358
359   if (hardware_keycode > NUM_KEYCODES)
360     return FALSE;
361
362   if (keys)
363     keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
364   else
365     keys_array = NULL;
366
367   if (keyvals)
368     keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
369   else
370     keyvals_array = NULL;
371
372   p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
373   
374   for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
375     {
376       if (!p[i])
377         continue;
378
379       (*n_entries)++;
380       
381       if (keyvals_array)
382         g_array_append_val (keyvals_array, p[i]);
383
384       if (keys_array)
385         {
386           GdkKeymapKey key;
387
388           key.keycode = hardware_keycode;
389           key.group = i / 2;
390           key.level = i % 2;
391
392           g_array_append_val (keys_array, key);
393         }
394     }
395   
396   if (keys)
397     *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
398
399   if (keyvals)
400     *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
401
402   return *n_entries > 0;
403 }
404
405 #define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
406
407 static guint
408 translate_keysym (guint           hardware_keycode,
409                   gint            group,
410                   GdkModifierType state,
411                   guint          *effective_group,
412                   guint          *effective_level)
413 {
414   gint level;
415   guint tmp_keyval;
416
417   level = (state & GDK_SHIFT_MASK) ? 1 : 0;
418
419   if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
420       (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
421     group = 0;
422
423   if (!GET_KEYVAL (hardware_keycode, group, level) &&
424       GET_KEYVAL (hardware_keycode, group, 0))
425     level = 0;
426
427   tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
428
429   if (state & GDK_LOCK_MASK)
430     {
431       guint upper = gdk_keyval_to_upper (tmp_keyval);
432         if (upper != tmp_keyval)
433           tmp_keyval = upper;
434     }
435
436   return tmp_keyval;
437 }
438
439 gboolean
440 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
441                                      guint            hardware_keycode,
442                                      GdkModifierType  state,
443                                      gint             group,
444                                      guint           *keyval,
445                                      gint            *effective_group,
446                                      gint            *level,
447                                      GdkModifierType *consumed_modifiers)
448 {
449   guint tmp_keyval;
450   GdkModifierType bit;
451   guint tmp_modifiers = 0;
452
453   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
454   g_return_val_if_fail (group >= 0 && group <= 1, FALSE);
455   
456   maybe_update_keymap ();
457
458   if (keyval)
459     *keyval = 0;
460   if (effective_group)
461     *effective_group = 0;
462   if (level)
463     *level = 0;
464   if (consumed_modifiers)
465     *consumed_modifiers = 0;
466
467   if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
468     return FALSE;
469   
470   /* Check if shift or capslock modify the keyval */
471   for (bit = GDK_SHIFT_MASK; bit < GDK_CONTROL_MASK; bit <<= 1)
472     {
473       if (translate_keysym (hardware_keycode, group, state & ~bit, NULL, NULL) !=
474           translate_keysym (hardware_keycode, group, state | bit, NULL, NULL))
475         tmp_modifiers |= bit;
476     }
477
478   tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
479
480   if (consumed_modifiers)
481     *consumed_modifiers = tmp_modifiers;
482
483   if (keyval)
484     *keyval = tmp_keyval; 
485
486   return TRUE;
487 }