Set svn:ignore recursively
[synfig.git] / synfig-osx / trunk / launcher / darwin-keyboard.c
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
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
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
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
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
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
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
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
298 LegalModifier (unsigned int key, DevicePtr pDev)
299 {
300     return 1;
301 }