1 /* darwin-keyboard.c -- Keyboard support for the Darwin X Server
3 Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
4 Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. The name of the author may not be used to endorse or promote products
15 derived from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
20 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
28 /* $XFree86: xc/programs/Xserver/hw/darwin/darwinKeyboard.c,v 1.16 2002/03/28 02:21:08 torrey Exp $ */
31 /* An X keyCode must be in the range XkbMinLegalKeyCode (8) to
32 XkbMaxLegalKeyCode(255).
34 The keyCodes we get from the kernel range from 0 to 127, so we need to
35 offset the range before passing the keyCode to X.
37 An X KeySym is an extended ascii code that is device independent.
39 The modifier map is accessed by the keyCode, but the normal map is
40 accessed by keyCode - MIN_KEYCODE. Sigh. */
43 /* Define this to get a diagnostic output to stderr which is helpful
44 in determining how the X server is interpreting the Darwin keymap. */
45 #undef DUMP_DARWIN_KEYMAP
47 /* Define this to use Alt for Mode_switch. */
48 #define ALT_IS_MODE_SWITCH 1
51 #include "darwin-keyboard.h"
56 #include "quartz-audio.h"
58 /* For NX_ constants */
59 #include <IOKit/hidsystem/IOLLEvent.h>
60 #include <IOKit/hidsystem/ev_keymap.h>
64 static darwin_keyboard_info info;
67 DarwinChangeKeyboardControl (DeviceIntPtr device, KeybdCtrl *ctrl)
69 /* keyclick, bell volume / pitch, autorepeat, LED's */
72 /* Use the key_map field of INFO to populate the mod_map and
73 modifier_keycodes fields */
75 build_modifier_maps (darwin_keyboard_info *info)
80 memset (info->mod_map, NoSymbol, sizeof (info->mod_map));
81 memset (info->modifier_keycodes, 0, sizeof (info->modifier_keycodes));
83 for (i = 0; i < NUM_KEYCODES; i++)
85 k = info->key_map + i * GLYPHS_PER_KEY;
90 info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][0] = i;
91 info->mod_map[MIN_KEYCODE + i] = ShiftMask;
95 info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][1] = i;
96 info->mod_map[MIN_KEYCODE + i] = ShiftMask;
100 info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][0] = i;
101 info->mod_map[MIN_KEYCODE + i] = ControlMask;
105 info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][1] = i;
106 info->mod_map[MIN_KEYCODE + i] = ControlMask;
110 info->modifier_keycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
111 info->mod_map[MIN_KEYCODE + i] = LockMask;
115 info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
116 info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
120 info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][1] = i;
121 info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
125 info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
129 info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][0] = i;
130 info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
134 info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][1] = i;
135 info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
139 info->mod_map[MIN_KEYCODE + i] = Mod3Mask;
143 if (darwinSwapAltMeta)
148 k[0] = XK_Meta_L; break;
150 k[0] = XK_Meta_R; break;
152 k[0] = XK_Alt_L; break;
154 k[0] = XK_Alt_R; break;
158 #if ALT_IS_MODE_SWITCH
159 if (k[0] == XK_Alt_L || k[0] == XK_Alt_R)
160 k[0] = XK_Mode_switch;
166 load_keyboard_mapping (KeySymsRec *keysyms)
168 memset (info.key_map, 0, sizeof (info.key_map));
170 if (darwinKeymapFile == NULL
171 || !DarwinParseKeymapFile (&info))
173 /* Load the system keymapping. */
175 DarwinReadSystemKeymap (&info);
178 build_modifier_maps (&info);
180 #ifdef DUMP_DARWIN_KEYMAP
181 ErrorF("Darwin -> X converted keyboard map\n");
182 for (i = 0, k = map; i < NX_NUMKEYCODES; i++, k += GLYPHS_PER_KEY) {
184 ErrorF("0x%02x:", i);
185 for (j = 0; j < GLYPHS_PER_KEY; j++) {
186 if (k[j] == NoSymbol) {
189 ErrorF("\t0x%x", k[j]);
196 keysyms->map = info.key_map;
197 keysyms->mapWidth = GLYPHS_PER_KEY;
198 keysyms->minKeyCode = MIN_KEYCODE;
199 keysyms->maxKeyCode = MAX_KEYCODE;
202 /* Get the Darwin keyboard map and compute an equivalent X keyboard map
203 and modifier map. Set the new keyboard device structure. */
205 DarwinKeyboardInit (DeviceIntPtr pDev)
208 BellProcPtr bellProc;
210 load_keyboard_mapping (&keysyms);
212 /* Initialize the seed, so we don't reload the keymap unnecessarily
213 (and possibly overwrite xinitrc changes) */
214 DarwinSystemKeymapSeed ();
216 bellProc = QuartzBell;
218 InitKeyboardDeviceStruct ((DevicePtr) pDev, &keysyms, info.mod_map,
219 bellProc, DarwinChangeKeyboardControl);
222 /* Borrowed from dix/devices.c */
224 InitModMap(register KeyClassPtr keyc)
227 CARD8 keysPerModifier[8];
230 if (keyc->modifierKeyMap != NULL)
231 xfree (keyc->modifierKeyMap);
233 keyc->maxKeysPerModifier = 0;
234 for (i = 0; i < 8; i++)
235 keysPerModifier[i] = 0;
236 for (i = 8; i < MAP_LENGTH; i++)
238 for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
240 if (mask & keyc->modifierMap[i])
242 if (++keysPerModifier[j] > keyc->maxKeysPerModifier)
243 keyc->maxKeysPerModifier = keysPerModifier[j];
247 keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier);
248 if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier)
250 bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier);
251 for (i = 0; i < 8; i++)
252 keysPerModifier[i] = 0;
253 for (i = 8; i < MAP_LENGTH; i++)
255 for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
257 if (mask & keyc->modifierMap[i])
259 keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) +
260 keysPerModifier[j]] = i;
261 keysPerModifier[j]++;
269 DarwinKeyboardReload (DeviceIntPtr pDev)
273 load_keyboard_mapping (&keysyms);
275 if (SetKeySymsMap (&pDev->key->curKeySyms, &keysyms))
277 /* now try to update modifiers. */
279 memmove (pDev->key->modifierMap, info.mod_map, MAP_LENGTH);
280 InitModMap (pDev->key);
283 SendMappingNotify (MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0);
284 SendMappingNotify (MappingModifier, 0, 0, 0);
287 /* Return the keycode for an NX_MODIFIERKEY_* modifier. side = 0 for left
288 or 1 for right. Returns 0 if key+side is not a known modifier. */
290 DarwinModifierNXKeyToNXKeycode (int key, int side)
292 return info.modifier_keycodes[key][side];
295 /* This allows the ddx layer to prevent some keys from being remapped
298 LegalModifier (unsigned int key, DevicePtr pDev)