Remove ancient trunk folder from svn repository
[synfig.git] / synfig-osx / launcher / darwin-keyboard.c
diff --git a/synfig-osx/launcher/darwin-keyboard.c b/synfig-osx/launcher/darwin-keyboard.c
new file mode 100644 (file)
index 0000000..0e8594e
--- /dev/null
@@ -0,0 +1,301 @@
+/* darwin-keyboard.c -- Keyboard support for the Darwin X Server
+
+   Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
+   Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+     3. The name of the author may not be used to endorse or promote products
+        derived from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+   NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+/* $XFree86: xc/programs/Xserver/hw/darwin/darwinKeyboard.c,v 1.16 2002/03/28 02:21:08 torrey Exp $ */
+
+
+/* An X keyCode must be in the range XkbMinLegalKeyCode (8) to
+   XkbMaxLegalKeyCode(255).
+
+   The keyCodes we get from the kernel range from 0 to 127, so we need to
+   offset the range before passing the keyCode to X.
+
+   An X KeySym is an extended ascii code that is device independent.
+
+   The modifier map is accessed by the keyCode, but the normal map is
+   accessed by keyCode - MIN_KEYCODE.  Sigh. */
+
+
+/* Define this to get a diagnostic output to stderr which is helpful
+   in determining how the X server is interpreting the Darwin keymap. */
+#undef DUMP_DARWIN_KEYMAP
+
+/* Define this to use Alt for Mode_switch. */
+#define ALT_IS_MODE_SWITCH 1
+
+#include "darwin.h"
+#include "darwin-keyboard.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "darwin.h"
+#include "quartz-audio.h"
+
+/* For NX_ constants */
+#include <IOKit/hidsystem/IOLLEvent.h>
+#include <IOKit/hidsystem/ev_keymap.h>
+
+#include "keysym.h"
+
+static darwin_keyboard_info info;
+
+static void
+DarwinChangeKeyboardControl (DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+    /* keyclick, bell volume / pitch, autorepeat, LED's */
+}
+
+/* Use the key_map field of INFO to populate the mod_map and
+   modifier_keycodes fields */
+static void
+build_modifier_maps (darwin_keyboard_info *info)
+{
+    int i;
+    KeySym *k;
+
+    memset (info->mod_map, NoSymbol, sizeof (info->mod_map));
+    memset (info->modifier_keycodes, 0, sizeof (info->modifier_keycodes));
+
+    for (i = 0; i < NUM_KEYCODES; i++)
+    {
+       k = info->key_map + i * GLYPHS_PER_KEY;
+
+       switch (k[0])
+       {
+       case XK_Shift_L:
+           info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][0] = i;
+           info->mod_map[MIN_KEYCODE + i] = ShiftMask;
+           break;
+
+       case XK_Shift_R:
+           info->modifier_keycodes[NX_MODIFIERKEY_SHIFT][1] = i;
+           info->mod_map[MIN_KEYCODE + i] = ShiftMask;
+           break;
+
+       case XK_Control_L:
+           info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][0] = i;
+           info->mod_map[MIN_KEYCODE + i] = ControlMask;
+           break;
+
+       case XK_Control_R:
+           info->modifier_keycodes[NX_MODIFIERKEY_CONTROL][1] = i;
+           info->mod_map[MIN_KEYCODE + i] = ControlMask;
+           break;
+
+       case XK_Caps_Lock:
+           info->modifier_keycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
+           info->mod_map[MIN_KEYCODE + i] = LockMask;
+           break;
+
+       case XK_Alt_L:
+           info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+           info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
+           break;
+
+       case XK_Alt_R:
+           info->modifier_keycodes[NX_MODIFIERKEY_ALTERNATE][1] = i;
+           info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
+           break;
+
+       case XK_Mode_switch:
+           info->mod_map[MIN_KEYCODE + i] = Mod1Mask;
+           break;
+
+       case XK_Meta_L:
+           info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][0] = i;
+           info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
+           break;
+
+       case XK_Meta_R:
+           info->modifier_keycodes[NX_MODIFIERKEY_COMMAND][1] = i;
+           info->mod_map[MIN_KEYCODE + i] = Mod2Mask;
+           break;
+
+       case XK_Num_Lock:
+           info->mod_map[MIN_KEYCODE + i] = Mod3Mask;
+           break;    
+       }
+
+       if (darwinSwapAltMeta)
+       {
+           switch (k[0])
+           {
+           case XK_Alt_L:
+               k[0] = XK_Meta_L; break;
+           case XK_Alt_R:
+               k[0] = XK_Meta_R; break;
+           case XK_Meta_L:
+               k[0] = XK_Alt_L; break;
+           case XK_Meta_R:
+               k[0] = XK_Alt_R; break;
+           }
+       }
+
+#if ALT_IS_MODE_SWITCH
+       if (k[0] == XK_Alt_L || k[0] == XK_Alt_R)
+           k[0] = XK_Mode_switch;
+#endif
+    }
+}
+
+static void
+load_keyboard_mapping (KeySymsRec *keysyms)
+{
+    memset (info.key_map, 0, sizeof (info.key_map));
+
+    if (darwinKeymapFile == NULL
+       || !DarwinParseKeymapFile (&info))
+    {
+       /* Load the system keymapping. */
+
+       DarwinReadSystemKeymap (&info);
+    }
+
+    build_modifier_maps (&info);
+
+#ifdef DUMP_DARWIN_KEYMAP
+    ErrorF("Darwin -> X converted keyboard map\n");
+    for (i = 0, k = map; i < NX_NUMKEYCODES; i++, k += GLYPHS_PER_KEY) {
+        int j;
+        ErrorF("0x%02x:", i);
+        for (j = 0; j < GLYPHS_PER_KEY; j++) {
+            if (k[j] == NoSymbol) {
+                ErrorF("\tNoSym");
+            } else {
+                ErrorF("\t0x%x", k[j]);
+            }
+        }
+        ErrorF("\n");
+    }
+#endif
+
+    keysyms->map = info.key_map;
+    keysyms->mapWidth = GLYPHS_PER_KEY;
+    keysyms->minKeyCode = MIN_KEYCODE;
+    keysyms->maxKeyCode = MAX_KEYCODE;
+}
+
+/* Get the Darwin keyboard map and compute an equivalent X keyboard map
+   and modifier map. Set the new keyboard device structure. */
+void
+DarwinKeyboardInit (DeviceIntPtr pDev)
+{
+    KeySymsRec keysyms;
+    BellProcPtr bellProc;
+
+    load_keyboard_mapping (&keysyms);
+
+    /* Initialize the seed, so we don't reload the keymap unnecessarily
+       (and possibly overwrite xinitrc changes) */
+    DarwinSystemKeymapSeed ();
+
+    bellProc = QuartzBell;
+
+    InitKeyboardDeviceStruct ((DevicePtr) pDev, &keysyms, info.mod_map,
+                             bellProc, DarwinChangeKeyboardControl);
+}
+
+/* Borrowed from dix/devices.c */
+static Bool
+InitModMap(register KeyClassPtr keyc)
+{
+    int i, j;
+    CARD8 keysPerModifier[8];
+    CARD8 mask;
+
+    if (keyc->modifierKeyMap != NULL)
+       xfree (keyc->modifierKeyMap);
+
+    keyc->maxKeysPerModifier = 0;
+    for (i = 0; i < 8; i++)
+       keysPerModifier[i] = 0;
+    for (i = 8; i < MAP_LENGTH; i++)
+    {
+       for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
+       {
+           if (mask & keyc->modifierMap[i])
+           {
+               if (++keysPerModifier[j] > keyc->maxKeysPerModifier)
+                   keyc->maxKeysPerModifier = keysPerModifier[j];
+           }
+       }
+    }
+    keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier);
+    if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier)
+       return (FALSE);
+    bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier);
+    for (i = 0; i < 8; i++)
+       keysPerModifier[i] = 0;
+    for (i = 8; i < MAP_LENGTH; i++)
+    {
+       for (j = 0, mask = 1; j < 8; j++, mask <<= 1)
+       {
+           if (mask & keyc->modifierMap[i])
+           {
+               keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) +
+                                    keysPerModifier[j]] = i;
+               keysPerModifier[j]++;
+           }
+       }
+    }
+    return TRUE;
+}
+
+void
+DarwinKeyboardReload (DeviceIntPtr pDev)
+{
+    KeySymsRec keysyms;
+
+    load_keyboard_mapping (&keysyms);
+
+    if (SetKeySymsMap (&pDev->key->curKeySyms, &keysyms))
+    {
+       /* now try to update modifiers. */
+
+       memmove (pDev->key->modifierMap, info.mod_map, MAP_LENGTH);
+       InitModMap (pDev->key);
+    }
+
+    SendMappingNotify (MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0);
+    SendMappingNotify (MappingModifier, 0, 0, 0);
+}
+
+/* Return the keycode for an NX_MODIFIERKEY_* modifier. side = 0 for left
+   or 1 for right. Returns 0 if key+side is not a known modifier. */
+int
+DarwinModifierNXKeyToNXKeycode (int key, int side)
+{
+    return info.modifier_keycodes[key][side];
+}
+
+/* This allows the ddx layer to prevent some keys from being remapped
+   as modifier keys. */
+Bool
+LegalModifier (unsigned int key, DevicePtr pDev)
+{
+    return 1;
+}