1027 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1027 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
| //=============================================================================
 | |
| //
 | |
| // Keyboard support for the Darwin X Server
 | |
| //
 | |
| // Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved.
 | |
| // Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved.
 | |
| // Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
 | |
| //
 | |
| // The code to parse the Darwin keymap is derived from dumpkeymap.c
 | |
| // by Eric Sunshine, which includes the following copyright:
 | |
| //
 | |
| // Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
 | |
| // 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.
 | |
| //
 | |
| //=============================================================================
 | |
| 
 | |
| 
 | |
| /*
 | |
| ===========================================================================
 | |
| 
 | |
|  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 <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <errno.h>
 | |
| #include <sys/stat.h>
 | |
| #include <IOKit/hidsystem/event_status_driver.h>
 | |
| #include <IOKit/hidsystem/ev_keymap.h>
 | |
| #include <architecture/byte_order.h>  // For the NXSwap*
 | |
| #include "darwin.h"
 | |
| #include "darwinKeyboard.h"
 | |
| #include <assert.h>
 | |
| #define AltMask         Mod1Mask
 | |
| #define MetaMask        Mod2Mask
 | |
| #define FunctionMask    Mod3Mask
 | |
| 
 | |
| // FIXME: It would be nice to support some of the extra keys in XF86keysym.h,
 | |
| // at least the volume controls that now ship on every Apple keyboard.
 | |
| 
 | |
| #define UK(a)           NoSymbol    // unknown symbol
 | |
| 
 | |
| static KeySym const next_to_x[256] = {
 | |
| 	NoSymbol,	NoSymbol,	NoSymbol,	XK_KP_Enter,
 | |
| 	NoSymbol,	NoSymbol,	NoSymbol,	NoSymbol,
 | |
| 	XK_BackSpace,	XK_Tab,		XK_Linefeed,	NoSymbol,
 | |
| 	NoSymbol,	XK_Return,	NoSymbol,	NoSymbol,
 | |
| 	NoSymbol,	NoSymbol,	NoSymbol,	NoSymbol,
 | |
| 	NoSymbol,	NoSymbol,	NoSymbol,	NoSymbol,
 | |
| 	NoSymbol,	NoSymbol,	NoSymbol,	XK_Escape,
 | |
| 	NoSymbol,	NoSymbol,	NoSymbol,	NoSymbol,
 | |
| 	XK_space,	XK_exclam,	XK_quotedbl,	XK_numbersign,
 | |
| 	XK_dollar,	XK_percent,	XK_ampersand,	XK_apostrophe,
 | |
| 	XK_parenleft,	XK_parenright,	XK_asterisk,	XK_plus,
 | |
| 	XK_comma,	XK_minus,	XK_period,	XK_slash,
 | |
| 	XK_0,		XK_1,		XK_2,		XK_3,
 | |
| 	XK_4,		XK_5,		XK_6,		XK_7,
 | |
| 	XK_8,		XK_9,		XK_colon,	XK_semicolon,
 | |
| 	XK_less,	XK_equal,	XK_greater,	XK_question,
 | |
| 	XK_at,		XK_A,		XK_B,		XK_C,
 | |
| 	XK_D,		XK_E,		XK_F,		XK_G,
 | |
| 	XK_H,		XK_I,		XK_J,		XK_K,
 | |
| 	XK_L,		XK_M,		XK_N,		XK_O,
 | |
| 	XK_P,		XK_Q,		XK_R,		XK_S,
 | |
| 	XK_T,		XK_U,		XK_V,		XK_W,
 | |
| 	XK_X,		XK_Y,		XK_Z,		XK_bracketleft,
 | |
| 	XK_backslash,	XK_bracketright,XK_asciicircum,	XK_underscore,
 | |
| 	XK_grave,	XK_a,		XK_b,		XK_c,
 | |
| 	XK_d,		XK_e,		XK_f,		XK_g,
 | |
| 	XK_h,		XK_i,		XK_j,		XK_k,
 | |
| 	XK_l,		XK_m,		XK_n,		XK_o,
 | |
| 	XK_p,		XK_q,		XK_r,		XK_s,
 | |
| 	XK_t,		XK_u,		XK_v,		XK_w,
 | |
| 	XK_x,		XK_y,		XK_z,		XK_braceleft,
 | |
| 	XK_bar,		XK_braceright,	XK_asciitilde,	XK_BackSpace,
 | |
| // 128
 | |
| 	NoSymbol,	XK_Agrave,	XK_Aacute,	XK_Acircumflex,
 | |
| 	XK_Atilde,	XK_Adiaeresis,	XK_Aring,	XK_Ccedilla,
 | |
| 	XK_Egrave,	XK_Eacute,	XK_Ecircumflex,	XK_Ediaeresis,
 | |
| 	XK_Igrave,	XK_Iacute,	XK_Icircumflex,	XK_Idiaeresis,
 | |
| // 144
 | |
| 	XK_ETH,		XK_Ntilde,	XK_Ograve,	XK_Oacute,
 | |
| 	XK_Ocircumflex,	XK_Otilde,	XK_Odiaeresis,	XK_Ugrave,
 | |
| 	XK_Uacute,	XK_Ucircumflex,	XK_Udiaeresis,	XK_Yacute,
 | |
| 	XK_THORN,	XK_mu,		XK_multiply,	XK_division,
 | |
| // 160
 | |
| 	XK_copyright,	XK_exclamdown,	XK_cent,	XK_sterling,
 | |
| 	UK(fraction),	XK_yen,		UK(fhook),	XK_section,
 | |
| 	XK_currency,	XK_rightsinglequotemark,
 | |
| 					XK_leftdoublequotemark,
 | |
| 							XK_guillemotleft,
 | |
| 	XK_leftanglebracket,
 | |
| 			XK_rightanglebracket,
 | |
| 					UK(filigature),	UK(flligature),
 | |
| // 176
 | |
| 	XK_registered,	XK_endash,	XK_dagger,	XK_doubledagger,
 | |
| 	XK_periodcentered,XK_brokenbar,	XK_paragraph,	UK(bullet),
 | |
| 	XK_singlelowquotemark,
 | |
| 			XK_doublelowquotemark,
 | |
| 					XK_rightdoublequotemark,
 | |
| 							XK_guillemotright,
 | |
| 	XK_ellipsis,	UK(permille),	XK_notsign,	XK_questiondown,
 | |
| // 192
 | |
| 	XK_onesuperior,	XK_dead_grave,	XK_dead_acute,	XK_dead_circumflex,
 | |
| 	XK_dead_tilde,	XK_dead_macron,	XK_dead_breve,	XK_dead_abovedot,
 | |
| 	XK_dead_diaeresis,
 | |
| 			XK_twosuperior,	XK_dead_abovering,
 | |
| 							XK_dead_cedilla,
 | |
| 	XK_threesuperior,
 | |
| 			XK_dead_doubleacute,
 | |
| 					XK_dead_ogonek,	XK_dead_caron,
 | |
| // 208
 | |
| 	XK_emdash,	XK_plusminus,	XK_onequarter,	XK_onehalf,
 | |
| 	XK_threequarters,
 | |
| 			XK_agrave,	XK_aacute,	XK_acircumflex,
 | |
| 	XK_atilde,	XK_adiaeresis,	XK_aring,	XK_ccedilla,
 | |
| 	XK_egrave,	XK_eacute,	XK_ecircumflex,	XK_ediaeresis,
 | |
| // 224
 | |
| 	XK_igrave,	XK_AE,		XK_iacute,	XK_ordfeminine,
 | |
| 	XK_icircumflex,	XK_idiaeresis,	XK_eth,		XK_ntilde,
 | |
| 	XK_Lstroke,	XK_Ooblique,	XK_OE,		XK_masculine,
 | |
| 	XK_ograve,	XK_oacute,	XK_ocircumflex, XK_otilde,
 | |
| // 240
 | |
| 	XK_odiaeresis,	XK_ae,		XK_ugrave,	XK_uacute,
 | |
| 	XK_ucircumflex,	XK_idotless,	XK_udiaeresis,	XK_ygrave,
 | |
| 	XK_lstroke,	XK_ooblique,	XK_oe,		XK_ssharp,
 | |
| 	XK_thorn,	XK_ydiaeresis,	NoSymbol,	NoSymbol,
 | |
|   };
 | |
| 
 | |
| #define MIN_SYMBOL      0xAC
 | |
| static KeySym const symbol_to_x[] = {
 | |
|     XK_Left,        XK_Up,          XK_Right,      XK_Down
 | |
|   };
 | |
| int const NUM_SYMBOL = sizeof(symbol_to_x) / sizeof(symbol_to_x[0]);
 | |
| 
 | |
| #define MIN_FUNCKEY     0x20
 | |
| static KeySym const funckey_to_x[] = {
 | |
|     XK_F1,          XK_F2,          XK_F3,          XK_F4,
 | |
|     XK_F5,          XK_F6,          XK_F7,          XK_F8,
 | |
|     XK_F9,          XK_F10,         XK_F11,         XK_F12,
 | |
|     XK_Insert,      XK_Delete,      XK_Home,        XK_End,
 | |
|     XK_Page_Up,     XK_Page_Down,   XK_F13,         XK_F14,
 | |
|     XK_F15
 | |
|   };
 | |
| int const NUM_FUNCKEY = sizeof(funckey_to_x) / sizeof(funckey_to_x[0]);
 | |
| 
 | |
| typedef struct {
 | |
|     KeySym      normalSym;
 | |
|     KeySym      keypadSym;
 | |
| } darwinKeyPad_t;
 | |
| 
 | |
| static darwinKeyPad_t const normal_to_keypad[] = {
 | |
|     { XK_0,         XK_KP_0 },
 | |
|     { XK_1,         XK_KP_1 },
 | |
|     { XK_2,         XK_KP_2 },
 | |
|     { XK_3,         XK_KP_3 },
 | |
|     { XK_4,         XK_KP_4 },
 | |
|     { XK_5,         XK_KP_5 },
 | |
|     { XK_6,         XK_KP_6 },
 | |
|     { XK_7,         XK_KP_7 },
 | |
|     { XK_8,         XK_KP_8 },
 | |
|     { XK_9,         XK_KP_9 },
 | |
|     { XK_equal,     XK_KP_Equal },
 | |
|     { XK_asterisk,  XK_KP_Multiply },
 | |
|     { XK_plus,      XK_KP_Add },
 | |
|     { XK_comma,     XK_KP_Separator },
 | |
|     { XK_minus,     XK_KP_Subtract },
 | |
|     { XK_period,    XK_KP_Decimal },
 | |
|     { XK_slash,     XK_KP_Divide }
 | |
| };
 | |
| int const NUM_KEYPAD = sizeof(normal_to_keypad) / sizeof(normal_to_keypad[0]);
 | |
| 
 | |
| static void DarwinChangeKeyboardControl( DeviceIntPtr device, KeybdCtrl *ctrl )
 | |
| {
 | |
|     // keyclick, bell volume / pitch, autorepead, LED's
 | |
| }
 | |
| 
 | |
| static darwinKeyboardInfo keyInfo;
 | |
| static FILE *fref = NULL;
 | |
| static char *inBuffer = NULL;
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // Data Stream Object
 | |
| //      Can be configured to treat embedded "numbers" as being composed of
 | |
| //      either 1, 2, or 4 bytes, apiece.
 | |
| //-----------------------------------------------------------------------------
 | |
| typedef struct _DataStream
 | |
| {
 | |
|     unsigned char const *data;
 | |
|     unsigned char const *data_end;
 | |
|     short number_size;  // Size in bytes of a "number" in the stream.
 | |
| } DataStream;
 | |
| 
 | |
| static DataStream* new_data_stream( unsigned char const* data, int size )
 | |
| {
 | |
|     DataStream* s = (DataStream*)xalloc( sizeof(DataStream) );
 | |
|     s->data = data;
 | |
|     s->data_end = data + size;
 | |
|     s->number_size = 1; // Default to byte-sized numbers.
 | |
|     return s;
 | |
| }
 | |
| 
 | |
| static void destroy_data_stream( DataStream* s )
 | |
| {
 | |
|     xfree(s);
 | |
| }
 | |
| 
 | |
| static unsigned char get_byte( DataStream* s )
 | |
| {
 | |
|     assert(s->data + 1 <= s->data_end);
 | |
|     return *s->data++;
 | |
| }
 | |
| 
 | |
| static short get_word( DataStream* s )
 | |
| {
 | |
|     short hi, lo;
 | |
|     assert(s->data + 2 <= s->data_end);
 | |
|     hi = *s->data++;
 | |
|     lo = *s->data++;
 | |
|     return ((hi << 8) | lo);
 | |
| }
 | |
| 
 | |
| static int get_dword( DataStream* s )
 | |
| {
 | |
|     int b1, b2, b3, b4;
 | |
|     assert(s->data + 4 <= s->data_end);
 | |
|     b4 = *s->data++;
 | |
|     b3 = *s->data++;
 | |
|     b2 = *s->data++;
 | |
|     b1 = *s->data++;
 | |
|     return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
 | |
| }
 | |
| 
 | |
| static int get_number( DataStream* s )
 | |
| {
 | |
|     switch (s->number_size) {
 | |
|         case 4:  return get_dword(s);
 | |
|         case 2:  return get_word(s);
 | |
|         default: return get_byte(s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // Utility functions to help parse Darwin keymap
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| /*
 | |
|  * bits_set
 | |
|  *      Calculate number of bits set in the modifier mask.
 | |
|  */
 | |
| static short bits_set( short mask )
 | |
| {
 | |
|     short n = 0;
 | |
| 
 | |
|     for ( ; mask != 0; mask >>= 1)
 | |
|         if ((mask & 0x01) != 0)
 | |
|             n++;
 | |
|     return n;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * parse_next_char_code
 | |
|  *      Read the next character code from the Darwin keymapping
 | |
|  *      and write it to the X keymap.
 | |
|  */
 | |
| static void parse_next_char_code(
 | |
|     DataStream  *s,
 | |
|     KeySym      *k )
 | |
| {
 | |
|     const short charSet = get_number(s);
 | |
|     const short charCode = get_number(s);
 | |
| 
 | |
|     if (charSet == 0) {                 // ascii character
 | |
|         if (charCode >= 0 && charCode < 256)
 | |
|             *k = next_to_x[charCode];
 | |
|     } else if (charSet == 0x01) {       // symbol character
 | |
|         if (charCode >= MIN_SYMBOL &&
 | |
|             charCode <= MIN_SYMBOL + NUM_SYMBOL)
 | |
|             *k = symbol_to_x[charCode - MIN_SYMBOL];
 | |
|     } else if (charSet == 0xFE) {       // function key
 | |
|         if (charCode >= MIN_FUNCKEY &&
 | |
|             charCode <= MIN_FUNCKEY + NUM_FUNCKEY)
 | |
|             *k = funckey_to_x[charCode - MIN_FUNCKEY];
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * DarwinReadKeymapFile
 | |
|  *      Read the appropriate keymapping from a keymapping file.
 | |
|  */
 | |
| Bool DarwinReadKeymapFile(
 | |
|     NXKeyMapping        *keyMap)
 | |
| {
 | |
|     struct stat         st;
 | |
|     NXEventSystemDevice info[20];
 | |
|     int                 interface = 0, handler_id = 0;
 | |
|     int                 map_interface, map_handler_id, map_size = 0;
 | |
|     unsigned int        i, size;
 | |
|     int                 *bufferEnd;
 | |
|     union km_tag {
 | |
|         int             *intP;
 | |
|         char            *charP;
 | |
|     } km;
 | |
| 
 | |
|     fref = fopen( darwinKeymapFile, "rb" );
 | |
|     if (fref == NULL) {
 | |
|         ErrorF("Unable to open keymapping file '%s' (errno %d).\n",
 | |
|                darwinKeymapFile, errno);
 | |
|         return FALSE;
 | |
|     }
 | |
|     if (fstat(fileno(fref), &st) == -1) {
 | |
|         ErrorF("Could not stat keymapping file '%s' (errno %d).\n",
 | |
|                darwinKeymapFile, errno);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     // check to make sure we don't crash later
 | |
|     if (st.st_size <= 16*sizeof(int)) {
 | |
|         ErrorF("Keymapping file '%s' is invalid (too small).\n",
 | |
|                darwinKeymapFile);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     inBuffer = (char*) xalloc( st.st_size );
 | |
|     bufferEnd = (int *) (inBuffer + st.st_size);
 | |
|     if (fread(inBuffer, st.st_size, 1, fref) != 1) {
 | |
|         ErrorF("Could not read %qd bytes from keymapping file '%s' (errno %d).\n",
 | |
|                st.st_size, darwinKeymapFile, errno);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (strncmp( inBuffer, "KYM1", 4 ) == 0) {
 | |
|         // Magic number OK.
 | |
|     } else if (strncmp( inBuffer, "KYMP", 4 ) == 0) {
 | |
|         ErrorF("Keymapping file '%s' is intended for use with the original NeXT keyboards and cannot be used by XDarwin.\n", darwinKeymapFile);
 | |
|         return FALSE;
 | |
|     } else {
 | |
|         ErrorF("Keymapping file '%s' has a bad magic number and cannot be used by XDarwin.\n", darwinKeymapFile);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     // find the keyboard interface and handler id
 | |
|     size = sizeof( info ) / sizeof( int );
 | |
|     if (!NXEventSystemInfo( darwinParamConnect, NX_EVS_DEVICE_INFO,
 | |
|                             (NXEventSystemInfoType) info, &size )) {
 | |
|         ErrorF("Error reading event status driver info.\n");
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     size = size * sizeof( int ) / sizeof( info[0] );
 | |
|     for( i = 0; i < size; i++) {
 | |
|         if (info[i].dev_type == NX_EVS_DEVICE_TYPE_KEYBOARD) {
 | |
|             Bool hasInterface = FALSE;
 | |
|             Bool hasMatch = FALSE;
 | |
| 
 | |
|             interface = info[i].interface;
 | |
|             handler_id = info[i].id;
 | |
| 
 | |
|             // Find an appropriate keymapping:
 | |
|             // The first time we try to match both interface and handler_id.
 | |
|             // If we can't match both, we take the first match for interface.
 | |
| 
 | |
|             do {
 | |
|                 km.charP = inBuffer;
 | |
|                 km.intP++;
 | |
|                 while (km.intP+3 < bufferEnd) {
 | |
|                     map_interface = NXSwapBigIntToHost(*(km.intP++));
 | |
|                     map_handler_id = NXSwapBigIntToHost(*(km.intP++));
 | |
|                     map_size = NXSwapBigIntToHost(*(km.intP++));
 | |
|                     if (map_interface == interface) {
 | |
|                         if (map_handler_id == handler_id || hasInterface) {
 | |
|                             hasMatch = TRUE;
 | |
|                             break;
 | |
|                         } else {
 | |
|                             hasInterface = TRUE;
 | |
|                         }
 | |
|                     }
 | |
|                     km.charP += map_size;
 | |
|                 }
 | |
|             } while (hasInterface && !hasMatch);
 | |
| 
 | |
|             if (hasMatch) {
 | |
|                 // fill in NXKeyMapping structure
 | |
|                 keyMap->size = map_size;
 | |
|                 keyMap->mapping = (char*) xalloc(map_size);
 | |
|                 memcpy(keyMap->mapping, km.charP, map_size);
 | |
|                 return TRUE;
 | |
|             }
 | |
|         } // if dev_id == keyboard device
 | |
|     } // foreach info struct
 | |
| 
 | |
|     // The keymapping file didn't match any of the info structs
 | |
|     // returned by NXEventSystemInfo.
 | |
|     ErrorF("Keymapping file '%s' did not contain appropriate keyboard interface.\n", darwinKeymapFile);
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * DarwinParseNXKeyMapping
 | |
|  */
 | |
| Bool DarwinParseNXKeyMapping(
 | |
|     darwinKeyboardInfo  *info)
 | |
| {
 | |
|     KeySym              *k;
 | |
|     int                 i;
 | |
|     short               numMods, numKeys, numPadKeys = 0;
 | |
|     Bool                haveKeymap = FALSE;
 | |
|     NXKeyMapping        keyMap;
 | |
|     DataStream          *keyMapStream;
 | |
|     unsigned char const *numPadStart = 0;
 | |
| 
 | |
|     if (darwinKeymapFile) {
 | |
|         haveKeymap = DarwinReadKeymapFile(&keyMap);
 | |
|         if (fref)
 | |
|             fclose(fref);
 | |
|         if (inBuffer)
 | |
|             xfree(inBuffer);
 | |
|         if (!haveKeymap) {
 | |
|             ErrorF("Reverting to kernel keymapping.\n");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!haveKeymap) {
 | |
|         // get the Darwin keyboard map
 | |
|         keyMap.size = NXKeyMappingLength( darwinParamConnect );
 | |
|         keyMap.mapping = (char*) xalloc( keyMap.size );
 | |
|         if (!NXGetKeyMapping( darwinParamConnect, &keyMap )) {
 | |
|             return FALSE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     keyMapStream = new_data_stream( (unsigned char const*)keyMap.mapping,
 | |
|                                     keyMap.size );
 | |
| 
 | |
|     // check the type of map
 | |
|     if (get_word(keyMapStream)) {
 | |
|         keyMapStream->number_size = 2;
 | |
|         ErrorF("Current 16-bit keymapping may not be interpreted correctly.\n");
 | |
|     }
 | |
| 
 | |
|     // Insert X modifier KeySyms into the keyboard map.
 | |
|     numMods = get_number(keyMapStream);
 | |
|     while (numMods-- > 0) {
 | |
|         int             left = 1;               // first keycode is left
 | |
|         short const     charCode = get_number(keyMapStream);
 | |
|         short           numKeyCodes = get_number(keyMapStream);
 | |
| 
 | |
|         // This is just a marker, not a real modifier.
 | |
|         // Store numeric keypad keys for later.
 | |
|         if (charCode == NX_MODIFIERKEY_NUMERICPAD) {
 | |
|             numPadStart = keyMapStream->data;
 | |
|             numPadKeys = numKeyCodes;
 | |
|         }
 | |
| 
 | |
|         while (numKeyCodes-- > 0) {
 | |
|             const short keyCode = get_number(keyMapStream);
 | |
|             if (charCode != NX_MODIFIERKEY_NUMERICPAD) {
 | |
|                 switch (charCode) {
 | |
|                     case NX_MODIFIERKEY_ALPHALOCK:
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] = XK_Caps_Lock;
 | |
|                         break;
 | |
|                     case NX_MODIFIERKEY_SHIFT:
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] =
 | |
|                                 (left ? XK_Shift_L : XK_Shift_R);
 | |
|                         break;
 | |
|                     case NX_MODIFIERKEY_CONTROL:
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] =
 | |
|                                 (left ? XK_Control_L : XK_Control_R);
 | |
|                         break;
 | |
|                     case NX_MODIFIERKEY_ALTERNATE:
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] =
 | |
|                                 (left ? XK_Mode_switch : XK_Alt_R);
 | |
|                         break;
 | |
|                     case NX_MODIFIERKEY_COMMAND:
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] =
 | |
|                                 (left ? XK_Meta_L : XK_Meta_R);
 | |
|                         break;
 | |
|                     case NX_MODIFIERKEY_SECONDARYFN:
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] =
 | |
|                                 (left ? XK_Control_L : XK_Control_R);
 | |
|                         break;
 | |
|                     case NX_MODIFIERKEY_HELP:
 | |
|                         // Help is not an X11 modifier; treat as normal key
 | |
|                         info->keyMap[keyCode * GLYPHS_PER_KEY] = XK_Help;
 | |
|                         break;
 | |
|                 }
 | |
|             }
 | |
|             left = 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Convert the Darwin keyboard mapping to an X keyboard map.
 | |
|     // A key can have a different character code for each combination of
 | |
|     // modifiers. We currently ignore all modifier combinations except
 | |
|     // those with Shift, AlphaLock, and Alt.
 | |
|     numKeys = get_number(keyMapStream);
 | |
|     for (i = 0, k = info->keyMap; i < numKeys; i++, k += GLYPHS_PER_KEY) {
 | |
|         short const     charGenMask = get_number(keyMapStream);
 | |
|         if (charGenMask != 0xFF) {              // is key bound?
 | |
|             short       numKeyCodes = 1 << bits_set(charGenMask);
 | |
| 
 | |
|             // Record unmodified case
 | |
|             parse_next_char_code( keyMapStream, k );
 | |
|             numKeyCodes--;
 | |
| 
 | |
|             // If AlphaLock and Shift modifiers produce different codes,
 | |
|             // we record the Shift case since X handles AlphaLock.
 | |
|             if (charGenMask & 0x01) {       // AlphaLock
 | |
|                 parse_next_char_code( keyMapStream, k+1 );
 | |
|                 numKeyCodes--;
 | |
|             }
 | |
| 
 | |
|             if (charGenMask & 0x02) {       // Shift
 | |
|                 parse_next_char_code( keyMapStream, k+1 );
 | |
|                 numKeyCodes--;
 | |
| 
 | |
|                 if (charGenMask & 0x01) {   // Shift-AlphaLock
 | |
|                     get_number(keyMapStream); get_number(keyMapStream);
 | |
|                     numKeyCodes--;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // Skip the Control cases
 | |
|             if (charGenMask & 0x04) {       // Control
 | |
|                 get_number(keyMapStream); get_number(keyMapStream);
 | |
|                 numKeyCodes--;
 | |
| 
 | |
|                 if (charGenMask & 0x01) {   // Control-AlphaLock
 | |
|                     get_number(keyMapStream); get_number(keyMapStream);
 | |
|                     numKeyCodes--;
 | |
|                 }
 | |
| 
 | |
|                 if (charGenMask & 0x02) {   // Control-Shift
 | |
|                     get_number(keyMapStream); get_number(keyMapStream);
 | |
|                     numKeyCodes--;
 | |
| 
 | |
|                     if (charGenMask & 0x01) {   // Shift-Control-AlphaLock
 | |
|                         get_number(keyMapStream); get_number(keyMapStream);
 | |
|                         numKeyCodes--;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // Process Alt cases
 | |
|             if (charGenMask & 0x08) {       // Alt
 | |
|                 parse_next_char_code( keyMapStream, k+2 );
 | |
|                 numKeyCodes--;
 | |
| 
 | |
|                 if (charGenMask & 0x01) {   // Alt-AlphaLock
 | |
|                     parse_next_char_code( keyMapStream, k+3 );
 | |
|                     numKeyCodes--;
 | |
|                 }
 | |
| 
 | |
|                 if (charGenMask & 0x02) {   // Alt-Shift
 | |
|                     parse_next_char_code( keyMapStream, k+3 );
 | |
|                     numKeyCodes--;
 | |
| 
 | |
|                     if (charGenMask & 0x01) {   // Alt-Shift-AlphaLock
 | |
|                         get_number(keyMapStream); get_number(keyMapStream);
 | |
|                         numKeyCodes--;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             while (numKeyCodes-- > 0) {
 | |
|                 get_number(keyMapStream); get_number(keyMapStream);
 | |
|             }
 | |
| 
 | |
|             if (k[3] == k[2]) k[3] = NoSymbol;
 | |
|             if (k[2] == k[1]) k[2] = NoSymbol;
 | |
|             if (k[1] == k[0]) k[1] = NoSymbol;
 | |
|             if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Now we have to go back through the list of keycodes that are on the
 | |
|     // numeric keypad and update the X keymap.
 | |
|     keyMapStream->data = numPadStart;
 | |
|     while(numPadKeys-- > 0) {
 | |
|         const short keyCode = get_number(keyMapStream);
 | |
|         k = &info->keyMap[keyCode * GLYPHS_PER_KEY];
 | |
|         for (i = 0; i < NUM_KEYPAD; i++) {
 | |
|             if (*k == normal_to_keypad[i].normalSym) {
 | |
|                 k[0] = normal_to_keypad[i].keypadSym;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // free Darwin keyboard map
 | |
|     destroy_data_stream( keyMapStream );
 | |
|     xfree( keyMap.mapping );
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * DarwinBuildModifierMaps
 | |
|  *      Use the keyMap field of keyboard info structure to populate
 | |
|  *      the modMap and modifierKeycodes fields.
 | |
|  */
 | |
| static void
 | |
| DarwinBuildModifierMaps(
 | |
|     darwinKeyboardInfo *info)
 | |
| {
 | |
|     int i;
 | |
|     KeySym *k;
 | |
| 
 | |
|     memset(info->modMap, NoSymbol, sizeof(info->modMap));
 | |
|     memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes));
 | |
| 
 | |
|     for (i = 0; i < NUM_KEYCODES; i++)
 | |
|     {
 | |
|         k = info->keyMap + i * GLYPHS_PER_KEY;
 | |
| 
 | |
|         switch (k[0]) {
 | |
|             case XK_Shift_L:
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
 | |
|                 info->modMap[MIN_KEYCODE + i] = ShiftMask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Shift_R:
 | |
| #ifdef NX_MODIFIERKEY_RSHIFT
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i;
 | |
| #else
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
 | |
| #endif
 | |
|                 info->modMap[MIN_KEYCODE + i] = ShiftMask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Control_L:
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
 | |
|                 info->modMap[MIN_KEYCODE + i] = ControlMask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Control_R:
 | |
| #ifdef NX_MODIFIERKEY_RCONTROL
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i;
 | |
| #else
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
 | |
| #endif
 | |
|                 info->modMap[MIN_KEYCODE + i] = ControlMask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Caps_Lock:
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
 | |
|                 info->modMap[MIN_KEYCODE + i] = LockMask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Alt_L:
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
 | |
|                 info->modMap[MIN_KEYCODE + i] = Mod1Mask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Alt_R:
 | |
| #ifdef NX_MODIFIERKEY_RALTERNATE
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
 | |
| #else
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
 | |
| #endif
 | |
|                 info->modMap[MIN_KEYCODE + i] = Mod1Mask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Mode_switch:
 | |
|                 info->modMap[MIN_KEYCODE + i] = Mod1Mask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Meta_L:
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
 | |
|                 info->modMap[MIN_KEYCODE + i] = Mod2Mask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Meta_R:
 | |
| #ifdef NX_MODIFIERKEY_RCOMMAND
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i;
 | |
| #else
 | |
|                 info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
 | |
| #endif
 | |
|                 info->modMap[MIN_KEYCODE + i] = Mod2Mask;
 | |
|                 break;
 | |
| 
 | |
|             case XK_Num_Lock:
 | |
|                 info->modMap[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_Mode_switch;
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * DarwinLoadKeyboardMapping
 | |
|  *  Load the keyboard map from a file or system and convert
 | |
|  *  it to an equivalent X keyboard map and modifier map.
 | |
|  */
 | |
| static void
 | |
| DarwinLoadKeyboardMapping(KeySymsRec *keySyms)
 | |
| {
 | |
|     memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
 | |
| 
 | |
|     if (!DarwinParseNXKeyMapping(&keyInfo)) {
 | |
|         if (!DarwinModeReadSystemKeymap(&keyInfo)) {
 | |
|             FatalError("Could not build a valid keymap.");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     DarwinBuildModifierMaps(&keyInfo);
 | |
| 
 | |
| #ifdef DUMP_DARWIN_KEYMAP
 | |
|     ErrorF("Darwin -> X converted keyboard map\n");
 | |
|     for (i = 0, k = info->keyMap; 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        = keyInfo.keyMap;
 | |
|     keySyms->mapWidth   = GLYPHS_PER_KEY;
 | |
|     keySyms->minKeyCode = MIN_KEYCODE;
 | |
|     keySyms->maxKeyCode = MAX_KEYCODE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * DarwinKeyboardInit
 | |
|  *      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;
 | |
| 
 | |
|     // Open a shared connection to the HID System.
 | |
|     // Note that the Event Status Driver is really just a wrapper
 | |
|     // for a kIOHIDParamConnectType connection.
 | |
|     assert( darwinParamConnect = NXOpenEventStatus() );
 | |
| 
 | |
|     DarwinLoadKeyboardMapping(&keySyms);
 | |
| 
 | |
|     /* Initialize the seed, so we don't reload the keymap unnecessarily
 | |
|        (and possibly overwrite xinitrc changes) */
 | |
|     DarwinModeSystemKeymapSeed();
 | |
| 
 | |
|     assert( InitKeyboardDeviceStruct( (DevicePtr)pDev, &keySyms,
 | |
|                                       keyInfo.modMap, DarwinModeBell,
 | |
|                                       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;
 | |
| 
 | |
|     DarwinLoadKeyboardMapping(&keySyms);
 | |
| 
 | |
|     if (SetKeySymsMap(&pDev->key->curKeySyms, &keySyms)) {
 | |
|         /* now try to update modifiers. */
 | |
| 
 | |
|         memmove(pDev->key->modifierMap, keyInfo.modMap, MAP_LENGTH);
 | |
|         InitModMap(pDev->key);
 | |
|     }
 | |
| 
 | |
|     SendMappingNotify(MappingKeyboard, MIN_KEYCODE, NUM_KEYCODES, 0);
 | |
|     SendMappingNotify(MappingModifier, 0, 0, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // Modifier translation functions
 | |
| //
 | |
| // There are three different ways to specify a Mac modifier key:
 | |
| // keycode - specifies hardware key, read from keymapping
 | |
| // key     - NX_MODIFIERKEY_*, really an index
 | |
| // mask    - NX_*MASK, mask for modifier flags in event record
 | |
| // Left and right side have different keycodes but the same key and mask.
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| /*
 | |
|  * DarwinModifierNXKeyToNXKeycode
 | |
|  *      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 keyInfo.modifierKeycodes[key][side];
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * DarwinModifierNXKeycodeToNXKey
 | |
|  *      Returns -1 if keycode+side is not a modifier key
 | |
|  *      outSide may be NULL, else it gets 0 for left and 1 for right.
 | |
|  */
 | |
| int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide)
 | |
| {
 | |
|     int key, side;
 | |
| 
 | |
|     keycode += MIN_KEYCODE;
 | |
|     // search modifierKeycodes for this keycode+side
 | |
|     for (key = 0; key < NX_NUMMODIFIERS; key++) {
 | |
|         for (side = 0; side <= 1; side++) {
 | |
|             if (keyInfo.modifierKeycodes[key][side] == keycode) break;
 | |
|         }
 | |
|     }
 | |
|     if (key == NX_NUMMODIFIERS) return -1;
 | |
|     if (outSide) *outSide = side;
 | |
|     return key;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * DarwinModifierNXMaskToNXKey
 | |
|  *      Returns -1 if mask is not a known modifier mask.
 | |
|  */
 | |
| int DarwinModifierNXMaskToNXKey(int mask)
 | |
| {
 | |
|     switch (mask) {
 | |
|         case NX_ALPHASHIFTMASK:       return NX_MODIFIERKEY_ALPHALOCK;
 | |
|         case NX_SHIFTMASK:            return NX_MODIFIERKEY_SHIFT;
 | |
| #ifdef NX_DEVICELSHIFTKEYMASK
 | |
|         case NX_DEVICELSHIFTKEYMASK:  return NX_MODIFIERKEY_SHIFT;
 | |
|         case NX_DEVICERSHIFTKEYMASK:  return NX_MODIFIERKEY_RSHIFT;
 | |
| #endif
 | |
|         case NX_CONTROLMASK:          return NX_MODIFIERKEY_CONTROL;
 | |
| #ifdef NX_DEVICELCTLKEYMASK
 | |
|         case NX_DEVICELCTLKEYMASK:    return NX_MODIFIERKEY_CONTROL;
 | |
|         case NX_DEVICERCTLKEYMASK:    return NX_MODIFIERKEY_RCONTROL;
 | |
| #endif
 | |
|         case NX_ALTERNATEMASK:        return NX_MODIFIERKEY_ALTERNATE;
 | |
| #ifdef NX_DEVICELALTKEYMASK
 | |
|         case NX_DEVICELALTKEYMASK:    return NX_MODIFIERKEY_ALTERNATE;
 | |
|         case NX_DEVICERALTKEYMASK:    return NX_MODIFIERKEY_RALTERNATE;
 | |
| #endif
 | |
|         case NX_COMMANDMASK:          return NX_MODIFIERKEY_COMMAND;
 | |
| #ifdef NX_DEVICELCMDKEYMASK
 | |
|         case NX_DEVICELCMDKEYMASK:    return NX_MODIFIERKEY_COMMAND;
 | |
|         case NX_DEVICERCMDKEYMASK:    return NX_MODIFIERKEY_RCOMMAND;
 | |
| #endif
 | |
|         case NX_NUMERICPADMASK:       return NX_MODIFIERKEY_NUMERICPAD;
 | |
|         case NX_HELPMASK:             return NX_MODIFIERKEY_HELP;
 | |
|         case NX_SECONDARYFNMASK:      return NX_MODIFIERKEY_SECONDARYFN;
 | |
|     }
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * DarwinModifierNXKeyToNXMask
 | |
|  *      Returns 0 if key is not a known modifier key.
 | |
|  */
 | |
| int DarwinModifierNXKeyToNXMask(int key)
 | |
| {
 | |
|     switch (key) {
 | |
|         case NX_MODIFIERKEY_ALPHALOCK:   return NX_ALPHASHIFTMASK;
 | |
|         case NX_MODIFIERKEY_SHIFT:       return NX_SHIFTMASK;
 | |
| #ifdef NX_MODIFIERKEY_RSHIFT
 | |
|         case NX_MODIFIERKEY_RSHIFT:      return NX_SHIFTMASK;
 | |
| #endif
 | |
|         case NX_MODIFIERKEY_CONTROL:     return NX_CONTROLMASK;
 | |
| #ifdef NX_MODIFIERKEY_RCONTROL
 | |
|         case NX_MODIFIERKEY_RCONTROL:    return NX_CONTROLMASK;
 | |
| #endif
 | |
|         case NX_MODIFIERKEY_ALTERNATE:   return NX_ALTERNATEMASK;
 | |
| #ifdef NX_MODIFIERKEY_RALTERNATE
 | |
|         case NX_MODIFIERKEY_RALTERNATE:  return NX_ALTERNATEMASK;
 | |
| #endif
 | |
|         case NX_MODIFIERKEY_COMMAND:     return NX_COMMANDMASK;
 | |
| #ifdef NX_MODIFIERKEY_RCOMMAND
 | |
|         case NX_MODIFIERKEY_RCOMMAND:    return NX_COMMANDMASK;
 | |
| #endif
 | |
|         case NX_MODIFIERKEY_NUMERICPAD:  return NX_NUMERICPADMASK;
 | |
|         case NX_MODIFIERKEY_HELP:        return NX_HELPMASK;
 | |
|         case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * DarwinModifierStringToNXKey
 | |
|  *      Returns -1 if string is not a known modifier.
 | |
|  */
 | |
| int DarwinModifierStringToNXKey(const char *str)
 | |
| {
 | |
|     if      (!strcasecmp(str, "shift"))   return NX_MODIFIERKEY_SHIFT;
 | |
|     else if (!strcasecmp(str, "control")) return NX_MODIFIERKEY_CONTROL;
 | |
|     else if (!strcasecmp(str, "option"))  return NX_MODIFIERKEY_ALTERNATE;
 | |
|     else if (!strcasecmp(str, "command")) return NX_MODIFIERKEY_COMMAND;
 | |
|     else if (!strcasecmp(str, "fn"))      return NX_MODIFIERKEY_SECONDARYFN;
 | |
|     else return -1;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * LegalModifier
 | |
|  *      This allows the ddx layer to prevent some keys from being remapped
 | |
|  *      as modifier keys.
 | |
|  */
 | |
| Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
 | |
| {
 | |
|     return 1;
 | |
| }
 |