1 /* darwin-keyboard.c -- Keyboard support for the Darwin X Server
2
3 Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
4 Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
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.
16
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. */
27
28 /* $XFree86: xc/programs/Xserver/hw/darwin/darwinKeyboard.c,v 1.16 2002/03/28 02:21:08 torrey Exp $ */
29
30
31 /* An X keyCode must be in the range XkbMinLegalKeyCode (8) to
32 XkbMaxLegalKeyCode(255).
33
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.
36
37 An X KeySym is an extended ascii code that is device independent.
38
39 The modifier map is accessed by the keyCode, but the normal map is
40 accessed by keyCode - MIN_KEYCODE. Sigh. */
41
42
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
46
47 /* Define this to use Alt for Mode_switch. */
48 #define ALT_IS_MODE_SWITCH 1
49
50 #include "darwin.h"
51 #include "darwin-keyboard.h"
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include "darwin.h"
56 #include "quartz-audio.h"
57
58 /* For NX_ constants */
59 #include <IOKit/hidsystem/IOLLEvent.h>
60 #include <IOKit/hidsystem/ev_keymap.h>
61
62 #include "keysym.h"
63
64 static darwin_keyboard_info info;
65
66 static void
DarwinChangeKeyboardControl(DeviceIntPtr device,KeybdCtrl * ctrl)67 DarwinChangeKeyboardControl (DeviceIntPtr device, KeybdCtrl *ctrl)
68 {
69 /* keyclick, bell volume / pitch, autorepeat, LED's */
70 }
71
72 /* Use the key_map field of INFO to populate the mod_map and
73 modifier_keycodes fields */
74 static void
build_modifier_maps(darwin_keyboard_info * info)75 build_modifier_maps (darwin_keyboard_info *info)
76 {
77 int i;
78 KeySym *k;
79
80 memset (info->mod_map, NoSymbol, sizeof (info->mod_map));
81 memset (info->modifier_keycodes, 0, sizeof (info->modifier_keycodes));
82
83 for (i = 0; i < NUM_KEYCODES; i++)
84 {
85 k = info->key_map + i * GLYPHS_PER_KEY;
86
87 switch (k[0])
88 {
89 case XK_Shift_L:
90 info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][0] = i;
91 info->mod_map[MIN_KEYCODE + i] = ShiftMask;
92 break;
93
94 case XK_Shift_R:
95 info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][1] = i;
96 info->mod_map[MIN_KEYCODE + i] = ShiftMask;
97 break;
98
99 case XK_Control_L:
100 info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][0] = i;
101 info->mod_map[MIN_KEYCODE + i] = ControlMask;
102 break;
103
104 case XK_Control_R:
105 info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][1] = i;
106 info->mod_map[MIN_KEYCODE + i] = ControlMask;
107 break;
108
109 case XK_Caps_Lock:
110 info->modifier_keycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
111 info->mod_map[MIN_KEYCODE + i] = LockMask;
112 break;
113
114 case XK_Alt_L:
115 info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
116 info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
117 break;
118
119 case XK_Alt_R:
120 info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][1] = i;
121 info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
122 break;
123
124 case XK_Mode_switch:
125 info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
126 break;
127
128 case XK_Meta_L:
129 info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][0] = i;
130 info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
131 break;
132
133 case XK_Meta_R:
134 info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][1] = i;
135 info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
136 break;
137
138 case XK_Num_Lock:
139 info->mod_map[MIN_KEYCODE + i] = Mod3Mask;
140 break;
141 }
142
143 if (darwinSwapAltMeta)
144 {
145 switch (k[0])
146 {
147 case XK_Alt_L:
148 k[0] = XK_Meta_L; break;
149 case XK_Alt_R:
150 k[0] = XK_Meta_R; break;
151 case XK_Meta_L:
152 k[0] = XK_Alt_L; break;
153 case XK_Meta_R:
154 k[0] = XK_Alt_R; break;
155 }
156 }
157
158 #if ALT_IS_MODE_SWITCH
159 if (k[0] == XK_Alt_L || k[0] == XK_Alt_R)
160 k[0] = XK_Mode_switch;
161 #endif
162 }
163 }
164
165 static void
load_keyboard_mapping(KeySymsRec * keysyms)166 load_keyboard_mapping (KeySymsRec *keysyms)
167 {
168 memset (info.key_map, 0, sizeof (info.key_map));
169
170 if (darwinKeymapFile == NULL
171 || !DarwinParseKeymapFile (&info))
172 {
173 /* Load the system keymapping. */
174
175 DarwinReadSystemKeymap (&info);
176 }
177
178 build_modifier_maps (&info);
179
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) {
183 int j;
184 ErrorF("0x%02x:", i);
185 for (j = 0; j < GLYPHS_PER_KEY; j++) {
186 if (k[j] == NoSymbol) {
187 ErrorF("\tNoSym");
188 } else {
189 ErrorF("\t0x%x", k[j]);
190 }
191 }
192 ErrorF("\n");
193 }
194 #endif
195
196 keysyms->map = info.key_map;
197 keysyms->mapWidth = GLYPHS_PER_KEY;
198 keysyms->minKeyCode = MIN_KEYCODE;
199 keysyms->maxKeyCode = MAX_KEYCODE;
200 }
201
202 /* Get the Darwin keyboard map and compute an equivalent X keyboard map
203 and modifier map. Set the new keyboard device structure. */
204 void
DarwinKeyboardInit(DeviceIntPtr pDev)205 DarwinKeyboardInit (DeviceIntPtr pDev)
206 {
207 KeySymsRec keysyms;
208 BellProcPtr bellProc;
209
210 load_keyboard_mapping (&keysyms);
211
212 /* Initialize the seed, so we don't reload the keymap unnecessarily
213 (and possibly overwrite xinitrc changes) */
214 DarwinSystemKeymapSeed ();
215
216 bellProc = QuartzBell;
217
218 InitKeyboardDeviceStruct ((DevicePtr) pDev, &keysyms, info.mod_map,
219 bellProc, DarwinChangeKeyboardControl);
220 }
221
222 /* Borrowed from dix/devices.c */
223 static Bool
InitModMap(register KeyClassPtr keyc)224 InitModMap(register KeyClassPtr keyc)
225 {
226 int i, j;
227 CARD8 keysPerModifier[8];
228 CARD8 mask;
229
230 if (keyc->modifierKeyMap != NULL)
231 xfree (keyc->modifierKeyMap);
232
233 keyc->maxKeysPerModifier = 0;
234 for (i = 0; i < 8; i++)
235 keysPerModifier[i] = 0;
236 for (i = 8; i < MAP_LENGTH; i++)
237 {
238 for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
239 {
240 if (mask & keyc->modifierMap[i])
241 {
242 if (++keysPerModifier[j] > keyc->maxKeysPerModifier)
243 keyc->maxKeysPerModifier = keysPerModifier[j];
244 }
245 }
246 }
247 keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier);
248 if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier)
249 return (FALSE);
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++)
254 {
255 for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
256 {
257 if (mask & keyc->modifierMap[i])
258 {
259 keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) +
260 keysPerModifier[j]] = i;
261 keysPerModifier[j]++;
262 }
263 }
264 }
265 return TRUE;
266 }
267
268 void
DarwinKeyboardReload(DeviceIntPtr pDev)269 DarwinKeyboardReload (DeviceIntPtr pDev)
270 {
271 KeySymsRec keysyms;
272
273 load_keyboard_mapping (&keysyms);
274
275 if (SetKeySymsMap (&pDev->key->curKeySyms, &keysyms))
276 {
277 /* now try to update modifiers. */
278
279 memmove (pDev->key->modifierMap, info.mod_map, MAP_LENGTH);
280 InitModMap (pDev->key);
281 }
282
283 SendMappingNotify (MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0);
284 SendMappingNotify (MappingModifier, 0, 0, 0);
285 }
286
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. */
289 int
DarwinModifierNXKeyToNXKeycode(int key,int side)290 DarwinModifierNXKeyToNXKeycode (int key, int side)
291 {
292 return info.modifier_keycodes[key][side];
293 }
294
295 /* This allows the ddx layer to prevent some keys from being remapped
296 as modifier keys. */
297 Bool
LegalModifier(unsigned int key,DevicePtr pDev)298 LegalModifier (unsigned int key, DevicePtr pDev)
299 {
300 return 1;
301 }
302