First import
[xorg_rtime.git] / xorg-server-1.4 / hw / darwin / quartz / quartzKeyboard.c
blobbdd541663ff8c284a02d1e4143611472862b4711
1 /*
2 quartzKeyboard.c
4 Code to build a keymap using the Carbon Keyboard Layout API,
5 which is supported on Mac OS X 10.2 and newer.
7 Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
9 Permission is hereby granted, free of charge, to any person
10 obtaining a copy of this software and associated documentation files
11 (the "Software"), to deal in the Software without restriction,
12 including without limitation the rights to use, copy, modify, merge,
13 publish, distribute, sublicense, and/or sell copies of the Software,
14 and to permit persons to whom the Software is furnished to do so,
15 subject to the following conditions:
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
24 HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
29 Except as contained in this notice, the name(s) of the above
30 copyright holders shall not be used in advertising or otherwise to
31 promote the sale, use or other dealings in this Software without
32 prior written authorization.
35 #ifdef HAVE_XORG_CONFIG_H
36 #include <xorg-config.h>
37 #endif
38 #include "quartzCommon.h"
40 #include <CoreServices/CoreServices.h>
41 #include <Carbon/Carbon.h>
43 #include "darwinKeyboard.h"
44 #include "X11/keysym.h"
45 #include "keysym2ucs.h"
47 #ifdef HAS_KL_API
49 #define HACK_MISSING 1
50 #define HACK_KEYPAD 1
52 enum {
53 MOD_COMMAND = 256,
54 MOD_SHIFT = 512,
55 MOD_OPTION = 2048,
56 MOD_CONTROL = 4096,
59 #define UKEYSYM(u) ((u) | 0x01000000)
61 /* Table of keycode->keysym mappings we use to fallback on for important
62 keys that are often not in the Unicode mapping. */
64 const static struct {
65 unsigned short keycode;
66 KeySym keysym;
67 } known_keys[] = {
68 {55, XK_Meta_L},
69 {56, XK_Shift_L},
70 {57, XK_Caps_Lock},
71 {58, XK_Alt_L},
72 {59, XK_Control_L},
74 {60, XK_Shift_R},
75 {61, XK_Alt_R},
76 {62, XK_Control_R},
77 {63, XK_Meta_R},
79 {122, XK_F1},
80 {120, XK_F2},
81 {99, XK_F3},
82 {118, XK_F4},
83 {96, XK_F5},
84 {97, XK_F6},
85 {98, XK_F7},
86 {100, XK_F8},
87 {101, XK_F9},
88 {109, XK_F10},
89 {103, XK_F11},
90 {111, XK_F12},
91 {105, XK_F13},
92 {107, XK_F14},
93 {113, XK_F15},
96 /* Table of keycode->old,new-keysym mappings we use to fixup the numeric
97 keypad entries. */
99 const static struct {
100 unsigned short keycode;
101 KeySym normal, keypad;
102 } known_numeric_keys[] = {
103 {65, XK_period, XK_KP_Decimal},
104 {67, XK_asterisk, XK_KP_Multiply},
105 {69, XK_plus, XK_KP_Add},
106 {75, XK_slash, XK_KP_Divide},
107 {76, 0x01000003, XK_KP_Enter},
108 {78, XK_minus, XK_KP_Subtract},
109 {81, XK_equal, XK_KP_Equal},
110 {82, XK_0, XK_KP_0},
111 {83, XK_1, XK_KP_1},
112 {84, XK_2, XK_KP_2},
113 {85, XK_3, XK_KP_3},
114 {86, XK_4, XK_KP_4},
115 {87, XK_5, XK_KP_5},
116 {88, XK_6, XK_KP_6},
117 {89, XK_7, XK_KP_7},
118 {91, XK_8, XK_KP_8},
119 {92, XK_9, XK_KP_9},
122 /* Table mapping normal keysyms to their dead equivalents.
123 FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
125 const static struct {
126 KeySym normal, dead;
127 } dead_keys[] = {
128 {XK_grave, XK_dead_grave},
129 {XK_acute, XK_dead_acute},
130 {XK_asciicircum, XK_dead_circumflex},
131 {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
132 {XK_asciitilde, XK_dead_tilde},
133 {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */
134 {XK_macron, XK_dead_macron},
135 {XK_breve, XK_dead_breve},
136 {XK_abovedot, XK_dead_abovedot},
137 {XK_diaeresis, XK_dead_diaeresis},
138 {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */
139 {XK_doubleacute, XK_dead_doubleacute},
140 {XK_caron, XK_dead_caron},
141 {XK_cedilla, XK_dead_cedilla},
142 {XK_ogonek, XK_dead_ogonek},
143 {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */
144 {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */
145 /* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
146 {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */
147 {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */
148 {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
151 unsigned int
152 DarwinModeSystemKeymapSeed (void)
154 static unsigned int seed;
156 static KeyboardLayoutRef last_key_layout;
157 KeyboardLayoutRef key_layout;
159 KLGetCurrentKeyboardLayout (&key_layout);
161 if (key_layout != last_key_layout)
162 seed++;
164 last_key_layout = key_layout;
166 return seed;
169 static inline UniChar
170 macroman2ucs (unsigned char c)
172 /* Precalculated table mapping MacRoman-128 to Unicode. Generated
173 by creating single element CFStringRefs then extracting the
174 first character. */
176 static const unsigned short table[128] = {
177 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
178 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
179 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
180 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
181 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
182 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
183 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
184 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
185 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
186 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
187 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
188 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
189 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
190 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
191 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
192 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
195 if (c < 128)
196 return c;
197 else
198 return table[c - 128];
201 static KeySym
202 make_dead_key (KeySym in)
204 int i;
206 for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++)
208 if (dead_keys[i].normal == in)
209 return dead_keys[i].dead;
212 return in;
215 Bool
216 DarwinModeReadSystemKeymap (darwinKeyboardInfo *info)
218 KeyboardLayoutRef key_layout;
219 const void *chr_data;
220 int num_keycodes = NUM_KEYCODES;
221 UInt32 keyboard_type = 0;
222 int is_uchr, i, j;
223 OSStatus err;
224 KeySym *k;
226 KLGetCurrentKeyboardLayout (&key_layout);
227 KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data);
229 if (chr_data != NULL)
231 is_uchr = 1;
232 keyboard_type = LMGetKbdType ();
234 else
236 KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data);
238 if (chr_data == NULL)
240 ErrorF ( "Couldn't get uchr or kchr resource\n");
241 return FALSE;
244 is_uchr = 0;
245 num_keycodes = 128;
249 /* Scan the keycode range for the Unicode character that each
250 key produces in the four shift states. Then convert that to
251 an X11 keysym (which may just the bit that says "this is
252 Unicode" if it can't find the real symbol.) */
254 for (i = 0; i < num_keycodes; i++)
256 static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION,
257 MOD_OPTION | MOD_SHIFT};
259 k = info->keyMap + i * GLYPHS_PER_KEY;
261 for (j = 0; j < 4; j++)
263 if (is_uchr)
265 UniChar s[8];
266 UniCharCount len;
267 UInt32 dead_key_state, extra_dead;
269 dead_key_state = 0;
270 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
271 mods[j] >> 8, keyboard_type, 0,
272 &dead_key_state, 8, &len, s);
273 if (err != noErr)
274 continue;
276 if (len == 0 && dead_key_state != 0)
278 /* Found a dead key. Work out which one it is, but
279 remembering that it's dead. */
281 extra_dead = 0;
282 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
283 mods[j] >> 8, keyboard_type,
284 kUCKeyTranslateNoDeadKeysMask,
285 &extra_dead, 8, &len, s);
286 if (err != noErr)
287 continue;
290 if (len > 0 && s[0] != 0x0010)
292 k[j] = ucs2keysym (s[0]);
294 if (dead_key_state != 0)
295 k[j] = make_dead_key (k[j]);
298 else
300 UInt32 c, state = 0;
301 UInt16 code;
303 code = i | mods[j];
304 c = KeyTranslate (chr_data, code, &state);
306 /* Dead keys are only processed on key-down, so ask
307 to translate those events. When we find a dead key,
308 translating the matching key up event will give
309 us the actual dead character. */
311 if (state != 0)
313 UInt32 state2 = 0;
314 c = KeyTranslate (chr_data, code | 128, &state2);
317 /* Characters seem to be in MacRoman encoding. */
319 if (c != 0 && c != 0x0010)
321 k[j] = ucs2keysym (macroman2ucs (c & 255));
323 if (state != 0)
324 k[j] = make_dead_key (k[j]);
329 if (k[3] == k[2])
330 k[3] = NoSymbol;
331 if (k[2] == k[1])
332 k[2] = NoSymbol;
333 if (k[1] == k[0])
334 k[1] = NoSymbol;
335 if (k[0] == k[2] && k[1] == k[3])
336 k[2] = k[3] = NoSymbol;
339 /* Fix up some things that are normally missing.. */
341 if (HACK_MISSING)
343 for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++)
345 k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY;
347 if (k[0] == NoSymbol && k[1] == NoSymbol
348 && k[2] == NoSymbol && k[3] == NoSymbol)
350 k[0] = known_keys[i].keysym;
355 /* And some more things. We find the right symbols for the numeric
356 keypad, but not the KP_ keysyms. So try to convert known keycodes. */
358 if (HACK_KEYPAD)
360 for (i = 0; i < sizeof (known_numeric_keys)
361 / sizeof (known_numeric_keys[0]); i++)
363 k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
365 if (k[0] == known_numeric_keys[i].normal)
367 k[0] = known_numeric_keys[i].keypad;
372 return TRUE;
375 #else /* !HAS_KL_API */
377 unsigned int
378 DarwinModeSystemKeymapSeed (void)
380 return 0;
383 Bool
384 DarwinModeReadSystemKeymap (darwinKeyboardInfo *info)
386 return FALSE;
389 #endif /* HAS_KL_API */