quartzKeyboard.c revision 6747b715
14642e01fSmrg/* 24642e01fSmrg quartzKeyboard.c: Keyboard support for Xquartz 34642e01fSmrg 44642e01fSmrg Copyright (c) 2003-2008 Apple Inc. 54642e01fSmrg Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved. 64642e01fSmrg Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved. 74642e01fSmrg 84642e01fSmrg Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com> 94642e01fSmrg All rights reserved. 104642e01fSmrg 114642e01fSmrg Redistribution and use in source and binary forms, with or without 124642e01fSmrg modification, are permitted provided that the following conditions are met: 134642e01fSmrg 144642e01fSmrg 1. Redistributions of source code must retain the above copyright 154642e01fSmrg notice, this list of conditions and the following disclaimer. 164642e01fSmrg 2. Redistributions in binary form must reproduce the above copyright 174642e01fSmrg notice, this list of conditions and the following disclaimer in the 184642e01fSmrg documentation and/or other materials provided with the distribution. 194642e01fSmrg 3. The name of the author may not be used to endorse or promote products 204642e01fSmrg derived from this software without specific prior written permission. 214642e01fSmrg 224642e01fSmrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 234642e01fSmrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 244642e01fSmrg OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 254642e01fSmrg NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 264642e01fSmrg SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 274642e01fSmrg TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 284642e01fSmrg PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 294642e01fSmrg LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 304642e01fSmrg NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 314642e01fSmrg SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 324642e01fSmrg*/ 334642e01fSmrg 344642e01fSmrg#include "sanitizedCarbon.h" 354642e01fSmrg 364642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 374642e01fSmrg#include <dix-config.h> 384642e01fSmrg#endif 394642e01fSmrg 404642e01fSmrg#define HACK_MISSING 1 414642e01fSmrg#define HACK_KEYPAD 1 426747b715Smrg#define HACK_BLACKLIST 1 434642e01fSmrg 446747b715Smrg#include <unistd.h> 454642e01fSmrg#include <stdio.h> 464642e01fSmrg#include <stdlib.h> 474642e01fSmrg#include <errno.h> 484642e01fSmrg#include <sys/stat.h> 494642e01fSmrg#include <AvailabilityMacros.h> 504642e01fSmrg 516747b715Smrg#include "quartz.h" 524642e01fSmrg#include "darwin.h" 536747b715Smrg#include "darwinEvents.h" 544642e01fSmrg 554642e01fSmrg#include "quartzKeyboard.h" 564642e01fSmrg#include "quartzAudio.h" 574642e01fSmrg 586747b715Smrg#include "X11Application.h" 596747b715Smrg 604642e01fSmrg#include "threadSafety.h" 614642e01fSmrg 624642e01fSmrg#ifdef NDEBUG 634642e01fSmrg#undef NDEBUG 644642e01fSmrg#include <assert.h> 654642e01fSmrg#define NDEBUG 1 664642e01fSmrg#else 674642e01fSmrg#include <assert.h> 684642e01fSmrg#endif 694642e01fSmrg#include <pthread.h> 704642e01fSmrg 714642e01fSmrg#include "xkbsrv.h" 724642e01fSmrg#include "exevents.h" 734642e01fSmrg#include "X11/keysym.h" 744642e01fSmrg#include "keysym2ucs.h" 754642e01fSmrg 766747b715Smrgextern void 776747b715SmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); 786747b715Smrg 794642e01fSmrgenum { 804642e01fSmrg MOD_COMMAND = 256, 814642e01fSmrg MOD_SHIFT = 512, 824642e01fSmrg MOD_OPTION = 2048, 834642e01fSmrg MOD_CONTROL = 4096, 844642e01fSmrg}; 854642e01fSmrg 864642e01fSmrg#define UKEYSYM(u) ((u) | 0x01000000) 874642e01fSmrg 886747b715Smrg#if HACK_MISSING 894642e01fSmrg/* Table of keycode->keysym mappings we use to fallback on for important 904642e01fSmrg keys that are often not in the Unicode mapping. */ 914642e01fSmrg 924642e01fSmrgconst static struct { 934642e01fSmrg unsigned short keycode; 944642e01fSmrg KeySym keysym; 954642e01fSmrg} known_keys[] = { 964642e01fSmrg {55, XK_Meta_L}, 974642e01fSmrg {56, XK_Shift_L}, 984642e01fSmrg {57, XK_Caps_Lock}, 994642e01fSmrg {58, XK_Alt_L}, 1004642e01fSmrg {59, XK_Control_L}, 1014642e01fSmrg 1024642e01fSmrg {60, XK_Shift_R}, 1034642e01fSmrg {61, XK_Alt_R}, 1044642e01fSmrg {62, XK_Control_R}, 1054642e01fSmrg {63, XK_Meta_R}, 1064642e01fSmrg 1074642e01fSmrg {122, XK_F1}, 1084642e01fSmrg {120, XK_F2}, 1094642e01fSmrg {99, XK_F3}, 1104642e01fSmrg {118, XK_F4}, 1114642e01fSmrg {96, XK_F5}, 1124642e01fSmrg {97, XK_F6}, 1134642e01fSmrg {98, XK_F7}, 1144642e01fSmrg {100, XK_F8}, 1154642e01fSmrg {101, XK_F9}, 1164642e01fSmrg {109, XK_F10}, 1174642e01fSmrg {103, XK_F11}, 1184642e01fSmrg {111, XK_F12}, 1194642e01fSmrg {105, XK_F13}, 1204642e01fSmrg {107, XK_F14}, 1214642e01fSmrg {113, XK_F15}, 1224642e01fSmrg}; 1236747b715Smrg#endif 1244642e01fSmrg 1256747b715Smrg#if HACK_KEYPAD 1264642e01fSmrg/* Table of keycode->old,new-keysym mappings we use to fixup the numeric 1274642e01fSmrg keypad entries. */ 1284642e01fSmrg 1294642e01fSmrgconst static struct { 1304642e01fSmrg unsigned short keycode; 1314642e01fSmrg KeySym normal, keypad; 1324642e01fSmrg} known_numeric_keys[] = { 1334642e01fSmrg {65, XK_period, XK_KP_Decimal}, 1344642e01fSmrg {67, XK_asterisk, XK_KP_Multiply}, 1354642e01fSmrg {69, XK_plus, XK_KP_Add}, 1364642e01fSmrg {75, XK_slash, XK_KP_Divide}, 1374642e01fSmrg {76, 0x01000003, XK_KP_Enter}, 1384642e01fSmrg {78, XK_minus, XK_KP_Subtract}, 1394642e01fSmrg {81, XK_equal, XK_KP_Equal}, 1404642e01fSmrg {82, XK_0, XK_KP_0}, 1414642e01fSmrg {83, XK_1, XK_KP_1}, 1424642e01fSmrg {84, XK_2, XK_KP_2}, 1434642e01fSmrg {85, XK_3, XK_KP_3}, 1444642e01fSmrg {86, XK_4, XK_KP_4}, 1454642e01fSmrg {87, XK_5, XK_KP_5}, 1464642e01fSmrg {88, XK_6, XK_KP_6}, 1474642e01fSmrg {89, XK_7, XK_KP_7}, 1484642e01fSmrg {91, XK_8, XK_KP_8}, 1494642e01fSmrg {92, XK_9, XK_KP_9}, 1504642e01fSmrg}; 1516747b715Smrg#endif 1526747b715Smrg 1536747b715Smrg#if HACK_BLACKLIST 1546747b715Smrg/* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow 1556747b715Smrg * http://xquartz.macosforge.org/trac/ticket/295 1566747b715Smrg * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html 1576747b715Smrg * 1586747b715Smrg * legacy Mac keycodes for arrow keys that shift-modify to math symbols 1596747b715Smrg */ 1606747b715Smrgconst static unsigned short keycode_blacklist[] = {66, 70, 72, 77}; 1616747b715Smrg#endif 1624642e01fSmrg 1634642e01fSmrg/* Table mapping normal keysyms to their dead equivalents. 1644642e01fSmrg FIXME: all the unicode keysyms (apart from circumflex) were guessed. */ 1654642e01fSmrg 1664642e01fSmrgconst static struct { 1674642e01fSmrg KeySym normal, dead; 1684642e01fSmrg} dead_keys[] = { 1694642e01fSmrg {XK_grave, XK_dead_grave}, 1704642e01fSmrg {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */ 1714642e01fSmrg {XK_acute, XK_dead_acute}, 1724642e01fSmrg {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */ 1736747b715Smrg// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */ 1744642e01fSmrg {XK_asciicircum, XK_dead_circumflex}, 1754642e01fSmrg {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ 1764642e01fSmrg {XK_asciitilde, XK_dead_tilde}, 1774642e01fSmrg {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */ 1784642e01fSmrg {XK_macron, XK_dead_macron}, 1794642e01fSmrg {XK_breve, XK_dead_breve}, 1804642e01fSmrg {XK_abovedot, XK_dead_abovedot}, 1814642e01fSmrg {XK_diaeresis, XK_dead_diaeresis}, 1824642e01fSmrg {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */ 1834642e01fSmrg {XK_doubleacute, XK_dead_doubleacute}, 1844642e01fSmrg {XK_caron, XK_dead_caron}, 1854642e01fSmrg {XK_cedilla, XK_dead_cedilla}, 1864642e01fSmrg {XK_ogonek, XK_dead_ogonek}, 1874642e01fSmrg {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */ 1884642e01fSmrg {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */ 1894642e01fSmrg/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */ 1904642e01fSmrg {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */ 1914642e01fSmrg {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */ 1924642e01fSmrg {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */ 1934642e01fSmrg}; 1944642e01fSmrg 1956747b715Smrgtypedef struct darwinKeyboardInfo_struct { 1966747b715Smrg CARD8 modMap[MAP_LENGTH]; 1976747b715Smrg KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY]; 1986747b715Smrg unsigned char modifierKeycodes[32][2]; 1996747b715Smrg} darwinKeyboardInfo; 2006747b715Smrg 2014642e01fSmrgdarwinKeyboardInfo keyInfo; 2024642e01fSmrgpthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; 2034642e01fSmrg 2044642e01fSmrgstatic void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) { 2054642e01fSmrg // FIXME: to be implemented 2064642e01fSmrg // keyclick, bell volume / pitch, autorepead, LED's 2074642e01fSmrg} 2084642e01fSmrg 2094642e01fSmrg//----------------------------------------------------------------------------- 2104642e01fSmrg// Utility functions to help parse Darwin keymap 2114642e01fSmrg//----------------------------------------------------------------------------- 2124642e01fSmrg 2134642e01fSmrg/* 2144642e01fSmrg * DarwinBuildModifierMaps 2154642e01fSmrg * Use the keyMap field of keyboard info structure to populate 2164642e01fSmrg * the modMap and modifierKeycodes fields. 2174642e01fSmrg */ 2184642e01fSmrgstatic void DarwinBuildModifierMaps(darwinKeyboardInfo *info) { 2194642e01fSmrg int i; 2204642e01fSmrg KeySym *k; 2214642e01fSmrg 2224642e01fSmrg memset(info->modMap, NoSymbol, sizeof(info->modMap)); 2234642e01fSmrg memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes)); 2244642e01fSmrg 2254642e01fSmrg for (i = 0; i < NUM_KEYCODES; i++) { 2264642e01fSmrg k = info->keyMap + i * GLYPHS_PER_KEY; 2274642e01fSmrg 2284642e01fSmrg switch (*k) { 2294642e01fSmrg case XK_Shift_L: 2304642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; 2314642e01fSmrg info->modMap[MIN_KEYCODE + i] = ShiftMask; 2324642e01fSmrg break; 2334642e01fSmrg 2344642e01fSmrg case XK_Shift_R: 2354642e01fSmrg#ifdef NX_MODIFIERKEY_RSHIFT 2364642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i; 2374642e01fSmrg#else 2384642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; 2394642e01fSmrg#endif 2404642e01fSmrg info->modMap[MIN_KEYCODE + i] = ShiftMask; 2414642e01fSmrg break; 2424642e01fSmrg 2434642e01fSmrg case XK_Control_L: 2444642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; 2454642e01fSmrg info->modMap[MIN_KEYCODE + i] = ControlMask; 2464642e01fSmrg break; 2474642e01fSmrg 2484642e01fSmrg case XK_Control_R: 2494642e01fSmrg#ifdef NX_MODIFIERKEY_RCONTROL 2504642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i; 2514642e01fSmrg#else 2524642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; 2534642e01fSmrg#endif 2544642e01fSmrg info->modMap[MIN_KEYCODE + i] = ControlMask; 2554642e01fSmrg break; 2564642e01fSmrg 2574642e01fSmrg case XK_Caps_Lock: 2584642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i; 2594642e01fSmrg info->modMap[MIN_KEYCODE + i] = LockMask; 2604642e01fSmrg break; 2614642e01fSmrg 2624642e01fSmrg case XK_Alt_L: 2634642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; 2644642e01fSmrg info->modMap[MIN_KEYCODE + i] = Mod1Mask; 2656747b715Smrg if(!XQuartzOptionSendsAlt) 2666747b715Smrg *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. 2674642e01fSmrg break; 2684642e01fSmrg 2694642e01fSmrg case XK_Alt_R: 2704642e01fSmrg#ifdef NX_MODIFIERKEY_RALTERNATE 2714642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; 2724642e01fSmrg#else 2734642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; 2744642e01fSmrg#endif 2756747b715Smrg if(!XQuartzOptionSendsAlt) 2766747b715Smrg *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. 2774642e01fSmrg info->modMap[MIN_KEYCODE + i] = Mod1Mask; 2784642e01fSmrg break; 2794642e01fSmrg 2804642e01fSmrg case XK_Mode_switch: 2816747b715Smrg ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n"); 2826747b715Smrg info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; 2836747b715Smrg#ifdef NX_MODIFIERKEY_RALTERNATE 2846747b715Smrg info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; 2856747b715Smrg#endif 2864642e01fSmrg info->modMap[MIN_KEYCODE + i] = Mod1Mask; 2874642e01fSmrg break; 2884642e01fSmrg 2894642e01fSmrg case XK_Meta_L: 2904642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; 2914642e01fSmrg info->modMap[MIN_KEYCODE + i] = Mod2Mask; 2924642e01fSmrg break; 2934642e01fSmrg 2944642e01fSmrg case XK_Meta_R: 2954642e01fSmrg#ifdef NX_MODIFIERKEY_RCOMMAND 2964642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i; 2974642e01fSmrg#else 2984642e01fSmrg info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; 2994642e01fSmrg#endif 3004642e01fSmrg info->modMap[MIN_KEYCODE + i] = Mod2Mask; 3014642e01fSmrg break; 3024642e01fSmrg 3034642e01fSmrg case XK_Num_Lock: 3044642e01fSmrg info->modMap[MIN_KEYCODE + i] = Mod3Mask; 3054642e01fSmrg break; 3064642e01fSmrg } 3074642e01fSmrg } 3084642e01fSmrg} 3094642e01fSmrg 3104642e01fSmrg/* 3114642e01fSmrg * DarwinKeyboardInit 3124642e01fSmrg * Get the Darwin keyboard map and compute an equivalent 3134642e01fSmrg * X keyboard map and modifier map. Set the new keyboard 3144642e01fSmrg * device structure. 3154642e01fSmrg */ 3164642e01fSmrgvoid DarwinKeyboardInit(DeviceIntPtr pDev) { 3174642e01fSmrg // Open a shared connection to the HID System. 3184642e01fSmrg // Note that the Event Status Driver is really just a wrapper 3194642e01fSmrg // for a kIOHIDParamConnectType connection. 3204642e01fSmrg assert(darwinParamConnect = NXOpenEventStatus()); 3214642e01fSmrg 3226747b715Smrg InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl); 3234642e01fSmrg 3246747b715Smrg DarwinKeyboardReloadHandler(); 3254642e01fSmrg 3266747b715Smrg CopyKeyClass(pDev, inputInfo.keyboard); 3276747b715Smrg} 3284642e01fSmrg 3296747b715Smrg/* Set the repeat rates based on global preferences and keycodes for modifiers. 3306747b715Smrg * Precondition: Has the keyInfo_mutex lock. 3316747b715Smrg */ 3326747b715Smrgstatic void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) { 3336747b715Smrg if(initialKeyRepeatValue == 300000) { // off 3346747b715Smrg /* Turn off repeats globally */ 3354642e01fSmrg XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff); 3364642e01fSmrg } else { 3376747b715Smrg int i; 3386747b715Smrg XkbControlsPtr ctrl; 3396747b715Smrg XkbControlsRec old; 3404642e01fSmrg 3416747b715Smrg /* Turn on repeats globally */ 3424642e01fSmrg XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn); 3436747b715Smrg 3446747b715Smrg /* Setup the bit mask for individual key repeats */ 3456747b715Smrg ctrl = pDev->key->xkbInfo->desc->ctrls; 3466747b715Smrg old= *ctrl; 3476747b715Smrg 3486747b715Smrg ctrl->repeat_delay = initialKeyRepeatValue * 15; 3496747b715Smrg ctrl->repeat_interval = keyRepeatValue * 15; 3506747b715Smrg 3516747b715Smrg /* Turn off key-repeat for modifier keys, on for others */ 3526747b715Smrg /* First set them all on */ 3536747b715Smrg for(i=0; i < XkbPerKeyBitArraySize; i++) 3546747b715Smrg ctrl->per_key_repeat[i] = -1; 3556747b715Smrg 3566747b715Smrg /* Now turn off the modifiers */ 3576747b715Smrg for(i=0; i < 32; i++) { 3586747b715Smrg unsigned char keycode; 3596747b715Smrg 3606747b715Smrg keycode = keyInfo.modifierKeycodes[i][0]; 3616747b715Smrg if(keycode) 3626747b715Smrg ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); 3636747b715Smrg 3646747b715Smrg keycode = keyInfo.modifierKeycodes[i][1]; 3656747b715Smrg if(keycode) 3666747b715Smrg ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); 3676747b715Smrg } 3686747b715Smrg 3696747b715Smrg /* Hurray for data duplication */ 3706747b715Smrg if (pDev->kbdfeed) 3716747b715Smrg memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize); 3724642e01fSmrg 3736747b715Smrg //fprintf(stderr, "per_key_repeat =\n"); 3746747b715Smrg //for(i=0; i < XkbPerKeyBitArraySize; i++) 3756747b715Smrg // fprintf(stderr, "%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n"); 3766747b715Smrg 3776747b715Smrg /* And now we notify the puppies about the changes */ 3786747b715Smrg XkbDDXChangeControls(pDev, &old, ctrl); 3796747b715Smrg } 3804642e01fSmrg} 3814642e01fSmrg 3826747b715Smrgvoid DarwinKeyboardReloadHandler(void) { 3834642e01fSmrg KeySymsRec keySyms; 3846747b715Smrg CFIndex initialKeyRepeatValue, keyRepeatValue; 3856747b715Smrg BOOL ok; 3866747b715Smrg DeviceIntPtr pDev; 3876747b715Smrg const char *xmodmap = PROJECTROOT "/bin/xmodmap"; 3886747b715Smrg const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap"; 3896747b715Smrg const char *homedir = getenv("HOME"); 3906747b715Smrg char usermodmap[PATH_MAX], cmd[PATH_MAX]; 3914642e01fSmrg 3924642e01fSmrg DEBUG_LOG("DarwinKeyboardReloadHandler\n"); 3934642e01fSmrg 3946747b715Smrg /* Get our key repeat settings from GlobalPreferences */ 3956747b715Smrg (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); 3966747b715Smrg 3976747b715Smrg initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok); 3986747b715Smrg if(!ok) 3996747b715Smrg initialKeyRepeatValue = 35; 4006747b715Smrg 4016747b715Smrg keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok); 4026747b715Smrg if(!ok) 4036747b715Smrg keyRepeatValue = 6; 4046747b715Smrg 4056747b715Smrg pthread_mutex_lock(&keyInfo_mutex); { 4066747b715Smrg /* Initialize our keySyms */ 4076747b715Smrg keySyms.map = keyInfo.keyMap; 4086747b715Smrg keySyms.mapWidth = GLYPHS_PER_KEY; 4096747b715Smrg keySyms.minKeyCode = MIN_KEYCODE; 4106747b715Smrg keySyms.maxKeyCode = MAX_KEYCODE; 4116747b715Smrg 4126747b715Smrg // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap 4136747b715Smrg /* Apply the mappings to darwinKeyboard */ 4146747b715Smrg XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode, 4156747b715Smrg keySyms.maxKeyCode - keySyms.minKeyCode + 1, 4166747b715Smrg keyInfo.modMap, serverClient); 4176747b715Smrg DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue); 4186747b715Smrg 4196747b715Smrg /* Apply the mappings to the core keyboard */ 4206747b715Smrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 4216747b715Smrg if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { 4226747b715Smrg XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode, 4236747b715Smrg keySyms.maxKeyCode - keySyms.minKeyCode + 1, 4246747b715Smrg keyInfo.modMap, serverClient); 4256747b715Smrg DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue); 4266747b715Smrg } 4276747b715Smrg } 4286747b715Smrg } pthread_mutex_unlock(&keyInfo_mutex); 4296747b715Smrg 4306747b715Smrg /* Modify with xmodmap */ 4316747b715Smrg if (access(xmodmap, F_OK) == 0) { 4326747b715Smrg /* Check for system .Xmodmap */ 4336747b715Smrg if (access(sysmodmap, F_OK) == 0) { 4346747b715Smrg if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap) < sizeof(cmd)) { 4356747b715Smrg X11ApplicationLaunchClient(cmd); 4366747b715Smrg } else { 4376747b715Smrg ErrorF("X11.app: Unable to create / execute xmodmap command line"); 4386747b715Smrg } 4396747b715Smrg } 4406747b715Smrg 4416747b715Smrg /* Check for user's local .Xmodmap */ 4426747b715Smrg if ((homedir != NULL) && (snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir) < sizeof(usermodmap))) { 4436747b715Smrg if (access(usermodmap, F_OK) == 0) { 4446747b715Smrg if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap) < sizeof(cmd)) { 4456747b715Smrg X11ApplicationLaunchClient(cmd); 4466747b715Smrg } else { 4476747b715Smrg ErrorF("X11.app: Unable to create / execute xmodmap command line"); 4486747b715Smrg } 4496747b715Smrg } 4506747b715Smrg } else { 4516747b715Smrg ErrorF("X11.app: Unable to determine path to user's .Xmodmap"); 4526747b715Smrg } 4536747b715Smrg } 4544642e01fSmrg} 4554642e01fSmrg 4564642e01fSmrg//----------------------------------------------------------------------------- 4574642e01fSmrg// Modifier translation functions 4584642e01fSmrg// 4594642e01fSmrg// There are three different ways to specify a Mac modifier key: 4604642e01fSmrg// keycode - specifies hardware key, read from keymapping 4614642e01fSmrg// key - NX_MODIFIERKEY_*, really an index 4624642e01fSmrg// mask - NX_*MASK, mask for modifier flags in event record 4634642e01fSmrg// Left and right side have different keycodes but the same key and mask. 4644642e01fSmrg//----------------------------------------------------------------------------- 4654642e01fSmrg 4664642e01fSmrg/* 4674642e01fSmrg * DarwinModifierNXKeyToNXKeycode 4684642e01fSmrg * Return the keycode for an NX_MODIFIERKEY_* modifier. 4694642e01fSmrg * side = 0 for left or 1 for right. 4704642e01fSmrg * Returns 0 if key+side is not a known modifier. 4714642e01fSmrg */ 4724642e01fSmrgint DarwinModifierNXKeyToNXKeycode(int key, int side) { 4734642e01fSmrg int retval; 4744642e01fSmrg pthread_mutex_lock(&keyInfo_mutex); 4754642e01fSmrg retval = keyInfo.modifierKeycodes[key][side]; 4764642e01fSmrg pthread_mutex_unlock(&keyInfo_mutex); 4774642e01fSmrg 4784642e01fSmrg return retval; 4794642e01fSmrg} 4804642e01fSmrg 4814642e01fSmrg/* 4824642e01fSmrg * DarwinModifierNXKeycodeToNXKey 4834642e01fSmrg * Returns -1 if keycode+side is not a modifier key 4844642e01fSmrg * outSide may be NULL, else it gets 0 for left and 1 for right. 4854642e01fSmrg */ 4864642e01fSmrgint DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) { 4874642e01fSmrg int key, side; 4884642e01fSmrg 4894642e01fSmrg keycode += MIN_KEYCODE; 4906747b715Smrg 4914642e01fSmrg // search modifierKeycodes for this keycode+side 4926747b715Smrg pthread_mutex_lock(&keyInfo_mutex); 4934642e01fSmrg for (key = 0; key < NX_NUMMODIFIERS; key++) { 4944642e01fSmrg for (side = 0; side <= 1; side++) { 4954642e01fSmrg if (keyInfo.modifierKeycodes[key][side] == keycode) break; 4964642e01fSmrg } 4974642e01fSmrg } 4986747b715Smrg pthread_mutex_unlock(&keyInfo_mutex); 4996747b715Smrg 5004642e01fSmrg if (key == NX_NUMMODIFIERS) { 5014642e01fSmrg return -1; 5024642e01fSmrg } 5034642e01fSmrg if (outSide) *outSide = side; 5044642e01fSmrg 5054642e01fSmrg return key; 5064642e01fSmrg} 5074642e01fSmrg 5084642e01fSmrg/* 5094642e01fSmrg * DarwinModifierNXMaskToNXKey 5104642e01fSmrg * Returns -1 if mask is not a known modifier mask. 5114642e01fSmrg */ 5124642e01fSmrgint DarwinModifierNXMaskToNXKey(int mask) { 5134642e01fSmrg switch (mask) { 5144642e01fSmrg case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK; 5154642e01fSmrg case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT; 5164642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 5174642e01fSmrg case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT; 5184642e01fSmrg case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT; 5194642e01fSmrg#endif 5204642e01fSmrg case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL; 5214642e01fSmrg#ifdef NX_DEVICELCTLKEYMASK 5224642e01fSmrg case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL; 5234642e01fSmrg case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL; 5244642e01fSmrg#endif 5254642e01fSmrg case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE; 5264642e01fSmrg#ifdef NX_DEVICELALTKEYMASK 5274642e01fSmrg case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE; 5284642e01fSmrg case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE; 5294642e01fSmrg#endif 5304642e01fSmrg case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND; 5314642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 5324642e01fSmrg case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND; 5334642e01fSmrg case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND; 5344642e01fSmrg#endif 5354642e01fSmrg case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD; 5364642e01fSmrg case NX_HELPMASK: return NX_MODIFIERKEY_HELP; 5374642e01fSmrg case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN; 5384642e01fSmrg } 5394642e01fSmrg return -1; 5404642e01fSmrg} 5414642e01fSmrg 5424642e01fSmrg/* 5434642e01fSmrg * DarwinModifierNXKeyToNXMask 5444642e01fSmrg * Returns 0 if key is not a known modifier key. 5454642e01fSmrg */ 5464642e01fSmrgint DarwinModifierNXKeyToNXMask(int key) { 5474642e01fSmrg switch (key) { 5484642e01fSmrg case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK; 5494642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 5504642e01fSmrg case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK; 5514642e01fSmrg case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK; 5524642e01fSmrg case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK; 5534642e01fSmrg case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK; 5544642e01fSmrg case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK; 5554642e01fSmrg case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK; 5564642e01fSmrg case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK; 5574642e01fSmrg case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK; 5584642e01fSmrg#else 5594642e01fSmrg case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK; 5604642e01fSmrg case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK; 5614642e01fSmrg case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK; 5624642e01fSmrg case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK; 5634642e01fSmrg#endif 5644642e01fSmrg case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK; 5654642e01fSmrg case NX_MODIFIERKEY_HELP: return NX_HELPMASK; 5664642e01fSmrg case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK; 5674642e01fSmrg } 5684642e01fSmrg return 0; 5694642e01fSmrg} 5704642e01fSmrg 5714642e01fSmrg/* 5724642e01fSmrg * DarwinModifierStringToNXMask 5734642e01fSmrg * Returns 0 if string is not a known modifier. 5744642e01fSmrg */ 5754642e01fSmrgint DarwinModifierStringToNXMask(const char *str, int separatelr) { 5764642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 5774642e01fSmrg if(separatelr) { 5784642e01fSmrg if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK; 5794642e01fSmrg if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK; 5804642e01fSmrg if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; 5814642e01fSmrg if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; 5824642e01fSmrg if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; 5834642e01fSmrg if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK; 5844642e01fSmrg if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK; 5854642e01fSmrg if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK; 5864642e01fSmrg if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK; 5874642e01fSmrg if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK; 5884642e01fSmrg if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK; 5894642e01fSmrg if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK; 5904642e01fSmrg if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK; 5914642e01fSmrg if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK; 5924642e01fSmrg if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK; 5934642e01fSmrg } else { 5944642e01fSmrg#endif 5954642e01fSmrg if (!strcasecmp(str, "shift")) return NX_SHIFTMASK; 5964642e01fSmrg if (!strcasecmp(str, "control")) return NX_CONTROLMASK; 5974642e01fSmrg if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK; 5984642e01fSmrg if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK; 5994642e01fSmrg if (!strcasecmp(str, "command")) return NX_COMMANDMASK; 6004642e01fSmrg if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK; 6014642e01fSmrg if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK; 6024642e01fSmrg if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK; 6034642e01fSmrg if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK; 6044642e01fSmrg if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK; 6054642e01fSmrg if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK; 6064642e01fSmrg if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK; 6074642e01fSmrg if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK; 6084642e01fSmrg if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK; 6094642e01fSmrg if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK; 6104642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 6114642e01fSmrg } 6124642e01fSmrg#endif 6134642e01fSmrg if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK; 6144642e01fSmrg if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK; 6154642e01fSmrg if (!strcasecmp(str, "help")) return NX_HELPMASK; 6164642e01fSmrg if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK; 6174642e01fSmrg return 0; 6184642e01fSmrg} 6194642e01fSmrg 6204642e01fSmrg/* 6214642e01fSmrg * LegalModifier 6224642e01fSmrg * This allows the ddx layer to prevent some keys from being remapped 6234642e01fSmrg * as modifier keys. 6244642e01fSmrg */ 6254642e01fSmrgBool LegalModifier(unsigned int key, DeviceIntPtr pDev) 6264642e01fSmrg{ 6274642e01fSmrg return 1; 6284642e01fSmrg} 6294642e01fSmrg 6304642e01fSmrgstatic inline UniChar macroman2ucs(unsigned char c) { 6314642e01fSmrg /* Precalculated table mapping MacRoman-128 to Unicode. Generated 6324642e01fSmrg by creating single element CFStringRefs then extracting the 6334642e01fSmrg first character. */ 6344642e01fSmrg 6354642e01fSmrg static const unsigned short table[128] = { 6364642e01fSmrg 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1, 6374642e01fSmrg 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8, 6384642e01fSmrg 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3, 6394642e01fSmrg 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc, 6404642e01fSmrg 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf, 6414642e01fSmrg 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8, 6424642e01fSmrg 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211, 6434642e01fSmrg 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8, 6444642e01fSmrg 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab, 6454642e01fSmrg 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153, 6464642e01fSmrg 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca, 6474642e01fSmrg 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02, 6484642e01fSmrg 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1, 6494642e01fSmrg 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4, 6504642e01fSmrg 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc, 6514642e01fSmrg 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7, 6524642e01fSmrg }; 6534642e01fSmrg 6544642e01fSmrg if (c < 128) return c; 6554642e01fSmrg else return table[c - 128]; 6564642e01fSmrg} 6574642e01fSmrg 6584642e01fSmrgstatic KeySym make_dead_key(KeySym in) { 6594642e01fSmrg int i; 6604642e01fSmrg 6614642e01fSmrg for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++) 6624642e01fSmrg if (dead_keys[i].normal == in) return dead_keys[i].dead; 6634642e01fSmrg 6644642e01fSmrg return in; 6654642e01fSmrg} 6664642e01fSmrg 6676747b715Smrgstatic Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { 6684642e01fSmrg#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 6694642e01fSmrg KeyboardLayoutRef key_layout; 6704642e01fSmrg int is_uchr = 1; 6714642e01fSmrg#endif 6724642e01fSmrg const void *chr_data = NULL; 6734642e01fSmrg int num_keycodes = NUM_KEYCODES; 6744642e01fSmrg UInt32 keyboard_type = LMGetKbdType(); 6754642e01fSmrg int i, j; 6764642e01fSmrg OSStatus err; 6774642e01fSmrg KeySym *k; 6784642e01fSmrg CFDataRef currentKeyLayoutDataRef = NULL; 6794642e01fSmrg 6804642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 6814642e01fSmrg TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); 6824642e01fSmrg 6834642e01fSmrg if (currentKeyLayoutRef) { 6844642e01fSmrg currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData); 6854642e01fSmrg if (currentKeyLayoutDataRef) 6864642e01fSmrg chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); 6874642e01fSmrg } 6884642e01fSmrg#endif 6894642e01fSmrg 6904642e01fSmrg#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 6914642e01fSmrg if (chr_data == NULL) { 6924642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 6934642e01fSmrg ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n"); 6944642e01fSmrg ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n", 6954642e01fSmrg (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data); 6964642e01fSmrg#endif 6974642e01fSmrg 6984642e01fSmrg KLGetCurrentKeyboardLayout (&key_layout); 6994642e01fSmrg KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data); 7004642e01fSmrg 7014642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 7024642e01fSmrg if(chr_data != NULL) { 7034642e01fSmrg ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); 7044642e01fSmrg } 7054642e01fSmrg#endif 7064642e01fSmrg } 7074642e01fSmrg 7084642e01fSmrg if (chr_data == NULL) { 7094642e01fSmrg ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n"); 7104642e01fSmrg ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n"); 7114642e01fSmrg KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data); 7124642e01fSmrg is_uchr = 0; 7134642e01fSmrg num_keycodes = 128; 7144642e01fSmrg 7154642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 7164642e01fSmrg if(chr_data != NULL) { 7174642e01fSmrg ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); 7184642e01fSmrg } 7194642e01fSmrg#endif 7204642e01fSmrg } 7214642e01fSmrg#endif 7224642e01fSmrg 7234642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 7244642e01fSmrg if(currentKeyLayoutRef) 7254642e01fSmrg CFRelease(currentKeyLayoutRef); 7264642e01fSmrg#endif 7274642e01fSmrg 7284642e01fSmrg if (chr_data == NULL) { 7294642e01fSmrg ErrorF ( "Couldn't get uchr or kchr resource\n"); 7304642e01fSmrg return FALSE; 7314642e01fSmrg } 7324642e01fSmrg 7334642e01fSmrg /* Scan the keycode range for the Unicode character that each 7344642e01fSmrg key produces in the four shift states. Then convert that to 7354642e01fSmrg an X11 keysym (which may just the bit that says "this is 7364642e01fSmrg Unicode" if it can't find the real symbol.) */ 7374642e01fSmrg 7384642e01fSmrg /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate 7394642e01fSmrg must be used instead. */ 7404642e01fSmrg 7414642e01fSmrg for (i = 0; i < num_keycodes; i++) { 7424642e01fSmrg static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION, 7434642e01fSmrg MOD_OPTION | MOD_SHIFT}; 7444642e01fSmrg 7454642e01fSmrg k = info->keyMap + i * GLYPHS_PER_KEY; 7464642e01fSmrg 7474642e01fSmrg for (j = 0; j < 4; j++) { 7484642e01fSmrg#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 7494642e01fSmrg if (is_uchr) { 7504642e01fSmrg#endif 7514642e01fSmrg UniChar s[8]; 7524642e01fSmrg UniCharCount len; 7534642e01fSmrg UInt32 dead_key_state = 0, extra_dead = 0; 7544642e01fSmrg 7554642e01fSmrg err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, 7564642e01fSmrg mods[j] >> 8, keyboard_type, 0, 7574642e01fSmrg &dead_key_state, 8, &len, s); 7584642e01fSmrg if (err != noErr) continue; 7594642e01fSmrg 7604642e01fSmrg if (len == 0 && dead_key_state != 0) { 7614642e01fSmrg /* Found a dead key. Work out which one it is, but 7624642e01fSmrg remembering that it's dead. */ 7634642e01fSmrg err = UCKeyTranslate (chr_data, i, kUCKeyActionDown, 7644642e01fSmrg mods[j] >> 8, keyboard_type, 7654642e01fSmrg kUCKeyTranslateNoDeadKeysMask, 7664642e01fSmrg &extra_dead, 8, &len, s); 7674642e01fSmrg if (err != noErr) continue; 7684642e01fSmrg } 7694642e01fSmrg 7706747b715Smrg /* Not sure why 0x0010 is there. 7716747b715Smrg * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ... 7726747b715Smrg */ 7736747b715Smrg if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) { 7744642e01fSmrg k[j] = ucs2keysym (s[0]); 7754642e01fSmrg if (dead_key_state != 0) k[j] = make_dead_key (k[j]); 7764642e01fSmrg } 7774642e01fSmrg#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 7784642e01fSmrg } else { // kchr 7794642e01fSmrg UInt32 c, state = 0, state2 = 0; 7804642e01fSmrg UInt16 code; 7814642e01fSmrg 7824642e01fSmrg code = i | mods[j]; 7834642e01fSmrg c = KeyTranslate (chr_data, code, &state); 7844642e01fSmrg 7854642e01fSmrg /* Dead keys are only processed on key-down, so ask 7864642e01fSmrg to translate those events. When we find a dead key, 7874642e01fSmrg translating the matching key up event will give 7884642e01fSmrg us the actual dead character. */ 7894642e01fSmrg 7904642e01fSmrg if (state != 0) 7914642e01fSmrg c = KeyTranslate (chr_data, code | 128, &state2); 7924642e01fSmrg 7934642e01fSmrg /* Characters seem to be in MacRoman encoding. */ 7944642e01fSmrg 7954642e01fSmrg if (c != 0 && c != 0x0010) { 7964642e01fSmrg k[j] = ucs2keysym (macroman2ucs (c & 255)); 7974642e01fSmrg 7984642e01fSmrg if (state != 0) k[j] = make_dead_key (k[j]); 7994642e01fSmrg } 8004642e01fSmrg } 8014642e01fSmrg#endif 8024642e01fSmrg } 8036747b715Smrg 8044642e01fSmrg if (k[3] == k[2]) k[3] = NoSymbol; 8054642e01fSmrg if (k[1] == k[0]) k[1] = NoSymbol; 8064642e01fSmrg if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; 8076747b715Smrg if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol; 8084642e01fSmrg } 8094642e01fSmrg 8106747b715Smrg#if HACK_MISSING 8114642e01fSmrg /* Fix up some things that are normally missing.. */ 8126747b715Smrg 8136747b715Smrg for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) { 8146747b715Smrg k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY; 8156747b715Smrg 8166747b715Smrg if ( k[0] == NoSymbol && k[1] == NoSymbol 8176747b715Smrg && k[2] == NoSymbol && k[3] == NoSymbol) 8186747b715Smrg k[0] = known_keys[i].keysym; 8194642e01fSmrg } 8206747b715Smrg#endif 8216747b715Smrg 8226747b715Smrg#if HACK_KEYPAD 8234642e01fSmrg /* And some more things. We find the right symbols for the numeric 8246747b715Smrg keypad, but not the KP_ keysyms. So try to convert known keycodes. */ 8256747b715Smrg for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) { 8266747b715Smrg k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY; 8276747b715Smrg 8286747b715Smrg if (k[0] == known_numeric_keys[i].normal) 8296747b715Smrg k[0] = known_numeric_keys[i].keypad; 8304642e01fSmrg } 8316747b715Smrg#endif 8326747b715Smrg 8336747b715Smrg#if HACK_BLACKLIST 8346747b715Smrg for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) { 8356747b715Smrg k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY; 8366747b715Smrg k[0] = k[1] = k[2] = k[3] = NoSymbol; 8376747b715Smrg } 8386747b715Smrg#endif 8396747b715Smrg 8406747b715Smrg DarwinBuildModifierMaps(info); 8414642e01fSmrg 8424642e01fSmrg return TRUE; 8434642e01fSmrg} 8446747b715Smrg 8456747b715SmrgBool QuartsResyncKeymap(Bool sendDDXEvent) { 8466747b715Smrg Bool retval; 8476747b715Smrg /* Update keyInfo */ 8486747b715Smrg pthread_mutex_lock(&keyInfo_mutex); 8496747b715Smrg memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); 8506747b715Smrg retval = QuartzReadSystemKeymap(&keyInfo); 8516747b715Smrg pthread_mutex_unlock(&keyInfo_mutex); 8526747b715Smrg 8536747b715Smrg /* Tell server thread to deal with new keyInfo */ 8546747b715Smrg if(sendDDXEvent) 8556747b715Smrg DarwinSendDDXEvent(kXquartzReloadKeymap, 0); 8566747b715Smrg 8576747b715Smrg return retval; 8586747b715Smrg} 859