14642e01fSmrg/* 24642e01fSmrg quartzKeyboard.c: Keyboard support for Xquartz 34642e01fSmrg 435c4bbdfSmrg Copyright (c) 2003-2012 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. 3235c4bbdfSmrg */ 334642e01fSmrg 344642e01fSmrg#include "sanitizedCarbon.h" 354642e01fSmrg 364642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 374642e01fSmrg#include <dix-config.h> 384642e01fSmrg#endif 394642e01fSmrg 4035c4bbdfSmrg#define HACK_MISSING 1 4135c4bbdfSmrg#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 506747b715Smrg#include "quartz.h" 514642e01fSmrg#include "darwin.h" 526747b715Smrg#include "darwinEvents.h" 534642e01fSmrg 544642e01fSmrg#include "quartzKeyboard.h" 554642e01fSmrg 566747b715Smrg#include "X11Application.h" 576747b715Smrg 584642e01fSmrg#include <assert.h> 594642e01fSmrg#include <pthread.h> 604642e01fSmrg 614642e01fSmrg#include "xkbsrv.h" 624642e01fSmrg#include "exevents.h" 634642e01fSmrg#include "X11/keysym.h" 644642e01fSmrg#include "keysym2ucs.h" 654642e01fSmrg 666747b715Smrgextern void 676747b715SmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); 686747b715Smrg 694642e01fSmrgenum { 704642e01fSmrg MOD_COMMAND = 256, 714642e01fSmrg MOD_SHIFT = 512, 724642e01fSmrg MOD_OPTION = 2048, 734642e01fSmrg MOD_CONTROL = 4096, 744642e01fSmrg}; 754642e01fSmrg 764642e01fSmrg#define UKEYSYM(u) ((u) | 0x01000000) 774642e01fSmrg 786747b715Smrg#if HACK_MISSING 794642e01fSmrg/* Table of keycode->keysym mappings we use to fallback on for important 804642e01fSmrg keys that are often not in the Unicode mapping. */ 814642e01fSmrg 824642e01fSmrgconst static struct { 834642e01fSmrg unsigned short keycode; 844642e01fSmrg KeySym keysym; 854642e01fSmrg} known_keys[] = { 8635c4bbdfSmrg { 55, XK_Meta_L }, 8735c4bbdfSmrg { 56, XK_Shift_L }, 8835c4bbdfSmrg { 57, XK_Caps_Lock }, 8935c4bbdfSmrg { 58, XK_Alt_L }, 9035c4bbdfSmrg { 59, XK_Control_L }, 9135c4bbdfSmrg 9235c4bbdfSmrg { 60, XK_Shift_R }, 9335c4bbdfSmrg { 61, XK_Alt_R }, 9435c4bbdfSmrg { 62, XK_Control_R }, 9535c4bbdfSmrg { 63, XK_Meta_R }, 9635c4bbdfSmrg 97c8548ba8Smrg { 110, XK_Menu }, 98c8548ba8Smrg 9935c4bbdfSmrg { 122, XK_F1 }, 10035c4bbdfSmrg { 120, XK_F2 }, 10135c4bbdfSmrg { 99, XK_F3 }, 10235c4bbdfSmrg { 118, XK_F4 }, 10335c4bbdfSmrg { 96, XK_F5 }, 10435c4bbdfSmrg { 97, XK_F6 }, 10535c4bbdfSmrg { 98, XK_F7 }, 10635c4bbdfSmrg { 100, XK_F8 }, 10735c4bbdfSmrg { 101, XK_F9 }, 10835c4bbdfSmrg { 109, XK_F10 }, 10935c4bbdfSmrg { 103, XK_F11 }, 11035c4bbdfSmrg { 111, XK_F12 }, 11135c4bbdfSmrg { 105, XK_F13 }, 11235c4bbdfSmrg { 107, XK_F14 }, 11335c4bbdfSmrg { 113, XK_F15 }, 114c8548ba8Smrg { 106, XK_F16 }, 115c8548ba8Smrg { 64, XK_F17 }, 116c8548ba8Smrg { 79, XK_F18 }, 117c8548ba8Smrg { 80, XK_F19 }, 118c8548ba8Smrg { 90, XK_F20 }, 1194642e01fSmrg}; 1206747b715Smrg#endif 1214642e01fSmrg 1226747b715Smrg#if HACK_KEYPAD 1234642e01fSmrg/* Table of keycode->old,new-keysym mappings we use to fixup the numeric 1244642e01fSmrg keypad entries. */ 1254642e01fSmrg 1264642e01fSmrgconst static struct { 1274642e01fSmrg unsigned short keycode; 1284642e01fSmrg KeySym normal, keypad; 1294642e01fSmrg} known_numeric_keys[] = { 13035c4bbdfSmrg { 65, XK_period, XK_KP_Decimal }, 13135c4bbdfSmrg { 67, XK_asterisk, XK_KP_Multiply }, 13235c4bbdfSmrg { 69, XK_plus, XK_KP_Add }, 13335c4bbdfSmrg { 75, XK_slash, XK_KP_Divide }, 13435c4bbdfSmrg { 76, 0x01000003, XK_KP_Enter }, 13535c4bbdfSmrg { 78, XK_minus, XK_KP_Subtract }, 13635c4bbdfSmrg { 81, XK_equal, XK_KP_Equal }, 13735c4bbdfSmrg { 82, XK_0, XK_KP_0 }, 13835c4bbdfSmrg { 83, XK_1, XK_KP_1 }, 13935c4bbdfSmrg { 84, XK_2, XK_KP_2 }, 14035c4bbdfSmrg { 85, XK_3, XK_KP_3 }, 14135c4bbdfSmrg { 86, XK_4, XK_KP_4 }, 14235c4bbdfSmrg { 87, XK_5, XK_KP_5 }, 14335c4bbdfSmrg { 88, XK_6, XK_KP_6 }, 14435c4bbdfSmrg { 89, XK_7, XK_KP_7 }, 14535c4bbdfSmrg { 91, XK_8, XK_KP_8 }, 14635c4bbdfSmrg { 92, XK_9, XK_KP_9 }, 1474642e01fSmrg}; 1486747b715Smrg#endif 1496747b715Smrg 1506747b715Smrg#if HACK_BLACKLIST 1516747b715Smrg/* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow 1526747b715Smrg * http://xquartz.macosforge.org/trac/ticket/295 1536747b715Smrg * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html 1546747b715Smrg * 1556747b715Smrg * legacy Mac keycodes for arrow keys that shift-modify to math symbols 1566747b715Smrg */ 15735c4bbdfSmrgconst static unsigned short keycode_blacklist[] = { 66, 70, 72, 77 }; 1586747b715Smrg#endif 1594642e01fSmrg 1604642e01fSmrg/* Table mapping normal keysyms to their dead equivalents. 1614642e01fSmrg FIXME: all the unicode keysyms (apart from circumflex) were guessed. */ 1624642e01fSmrg 1634642e01fSmrgconst static struct { 1644642e01fSmrg KeySym normal, dead; 1654642e01fSmrg} dead_keys[] = { 16635c4bbdfSmrg { XK_grave, XK_dead_grave }, 16735c4bbdfSmrg { XK_apostrophe, XK_dead_acute }, /* US:"=" on a Czech keyboard */ 16835c4bbdfSmrg { XK_acute, XK_dead_acute }, 16935c4bbdfSmrg { UKEYSYM(0x384), XK_dead_acute }, /* US:";" on a Greek keyboard */ 17035c4bbdfSmrg // {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */ 17135c4bbdfSmrg { XK_asciicircum, XK_dead_circumflex }, 17235c4bbdfSmrg { UKEYSYM(0x2c6), XK_dead_circumflex }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ 17335c4bbdfSmrg { XK_asciitilde, XK_dead_tilde }, 17435c4bbdfSmrg { UKEYSYM(0x2dc), XK_dead_tilde }, /* SMALL TILDE */ 17535c4bbdfSmrg { XK_macron, XK_dead_macron }, 17635c4bbdfSmrg { XK_breve, XK_dead_breve }, 17735c4bbdfSmrg { XK_abovedot, XK_dead_abovedot }, 17835c4bbdfSmrg { XK_diaeresis, XK_dead_diaeresis }, 17935c4bbdfSmrg { UKEYSYM(0x2da), XK_dead_abovering }, /* DOT ABOVE */ 18035c4bbdfSmrg { XK_doubleacute, XK_dead_doubleacute }, 18135c4bbdfSmrg { XK_caron, XK_dead_caron }, 18235c4bbdfSmrg { XK_cedilla, XK_dead_cedilla }, 18335c4bbdfSmrg { XK_ogonek, XK_dead_ogonek }, 18435c4bbdfSmrg { UKEYSYM(0x269), XK_dead_iota }, /* LATIN SMALL LETTER IOTA */ 18535c4bbdfSmrg { UKEYSYM(0x2ec), XK_dead_voiced_sound }, /* MODIFIER LETTER VOICING */ 18635c4bbdfSmrg /* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */ 18735c4bbdfSmrg { UKEYSYM(0x323), XK_dead_belowdot }, /* COMBINING DOT BELOW */ 18835c4bbdfSmrg { UKEYSYM(0x309), XK_dead_hook }, /* COMBINING HOOK ABOVE */ 18935c4bbdfSmrg { UKEYSYM(0x31b), XK_dead_horn }, /* COMBINING HORN */ 1904642e01fSmrg}; 1914642e01fSmrg 1926747b715Smrgtypedef struct darwinKeyboardInfo_struct { 1936747b715Smrg CARD8 modMap[MAP_LENGTH]; 1946747b715Smrg KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY]; 1956747b715Smrg unsigned char modifierKeycodes[32][2]; 1966747b715Smrg} darwinKeyboardInfo; 1976747b715Smrg 1984642e01fSmrgdarwinKeyboardInfo keyInfo; 1994642e01fSmrgpthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; 2004642e01fSmrg 20135c4bbdfSmrgstatic void 20235c4bbdfSmrgDarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) 20335c4bbdfSmrg{ 2044642e01fSmrg // FIXME: to be implemented 2054642e01fSmrg // keyclick, bell volume / pitch, autorepead, LED's 2064642e01fSmrg} 2074642e01fSmrg 2084642e01fSmrg//----------------------------------------------------------------------------- 2094642e01fSmrg// Utility functions to help parse Darwin keymap 2104642e01fSmrg//----------------------------------------------------------------------------- 2114642e01fSmrg 2124642e01fSmrg/* 2134642e01fSmrg * DarwinBuildModifierMaps 2144642e01fSmrg * Use the keyMap field of keyboard info structure to populate 2154642e01fSmrg * the modMap and modifierKeycodes fields. 2164642e01fSmrg */ 21735c4bbdfSmrgstatic void 21835c4bbdfSmrgDarwinBuildModifierMaps(darwinKeyboardInfo *info) 21935c4bbdfSmrg{ 2204642e01fSmrg int i; 2214642e01fSmrg KeySym *k; 2224642e01fSmrg 2234642e01fSmrg memset(info->modMap, NoSymbol, sizeof(info->modMap)); 2244642e01fSmrg memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes)); 2254642e01fSmrg 2264642e01fSmrg for (i = 0; i < NUM_KEYCODES; i++) { 2274642e01fSmrg k = info->keyMap + i * GLYPHS_PER_KEY; 2284642e01fSmrg 2294642e01fSmrg switch (*k) { 23035c4bbdfSmrg case XK_Shift_L: 23135c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; 23235c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = ShiftMask; 23335c4bbdfSmrg break; 2344642e01fSmrg 23535c4bbdfSmrg case XK_Shift_R: 2364642e01fSmrg#ifdef NX_MODIFIERKEY_RSHIFT 23735c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i; 2384642e01fSmrg#else 23935c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i; 2404642e01fSmrg#endif 24135c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = ShiftMask; 24235c4bbdfSmrg break; 2434642e01fSmrg 24435c4bbdfSmrg case XK_Control_L: 24535c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; 24635c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = ControlMask; 24735c4bbdfSmrg break; 2484642e01fSmrg 24935c4bbdfSmrg case XK_Control_R: 2504642e01fSmrg#ifdef NX_MODIFIERKEY_RCONTROL 25135c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i; 2524642e01fSmrg#else 25335c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i; 2544642e01fSmrg#endif 25535c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = ControlMask; 25635c4bbdfSmrg break; 25735c4bbdfSmrg 25835c4bbdfSmrg case XK_Caps_Lock: 25935c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i; 26035c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = LockMask; 26135c4bbdfSmrg break; 26235c4bbdfSmrg 26335c4bbdfSmrg case XK_Alt_L: 26435c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; 26535c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = Mod1Mask; 26635c4bbdfSmrg if (!XQuartzOptionSendsAlt) 26735c4bbdfSmrg *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. 26835c4bbdfSmrg break; 26935c4bbdfSmrg 27035c4bbdfSmrg case XK_Alt_R: 2714642e01fSmrg#ifdef NX_MODIFIERKEY_RALTERNATE 27235c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; 2734642e01fSmrg#else 27435c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; 2754642e01fSmrg#endif 27635c4bbdfSmrg if (!XQuartzOptionSendsAlt) 27735c4bbdfSmrg *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. 27835c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = Mod1Mask; 27935c4bbdfSmrg break; 28035c4bbdfSmrg 28135c4bbdfSmrg case XK_Mode_switch: 28235c4bbdfSmrg ErrorF( 28335c4bbdfSmrg "DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n"); 28435c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; 2856747b715Smrg#ifdef NX_MODIFIERKEY_RALTERNATE 28635c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i; 2876747b715Smrg#endif 28835c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = Mod1Mask; 28935c4bbdfSmrg break; 2904642e01fSmrg 29135c4bbdfSmrg case XK_Meta_L: 29235c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; 29335c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = Mod2Mask; 29435c4bbdfSmrg break; 2954642e01fSmrg 29635c4bbdfSmrg case XK_Meta_R: 2974642e01fSmrg#ifdef NX_MODIFIERKEY_RCOMMAND 29835c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i; 2994642e01fSmrg#else 30035c4bbdfSmrg info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i; 3014642e01fSmrg#endif 30235c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = Mod2Mask; 30335c4bbdfSmrg break; 3044642e01fSmrg 30535c4bbdfSmrg case XK_Num_Lock: 30635c4bbdfSmrg info->modMap[MIN_KEYCODE + i] = Mod3Mask; 30735c4bbdfSmrg break; 3084642e01fSmrg } 3094642e01fSmrg } 3104642e01fSmrg} 3114642e01fSmrg 3124642e01fSmrg/* 3134642e01fSmrg * DarwinKeyboardInit 3144642e01fSmrg * Get the Darwin keyboard map and compute an equivalent 3154642e01fSmrg * X keyboard map and modifier map. Set the new keyboard 3164642e01fSmrg * device structure. 3174642e01fSmrg */ 31835c4bbdfSmrgvoid 31935c4bbdfSmrgDarwinKeyboardInit(DeviceIntPtr pDev) 32035c4bbdfSmrg{ 3214642e01fSmrg // Open a shared connection to the HID System. 3224642e01fSmrg // Note that the Event Status Driver is really just a wrapper 3234642e01fSmrg // for a kIOHIDParamConnectType connection. 3244642e01fSmrg assert(darwinParamConnect = NXOpenEventStatus()); 3254642e01fSmrg 3266747b715Smrg InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl); 3274642e01fSmrg 3286747b715Smrg DarwinKeyboardReloadHandler(); 3294642e01fSmrg 3306747b715Smrg CopyKeyClass(pDev, inputInfo.keyboard); 3316747b715Smrg} 3324642e01fSmrg 3336747b715Smrg/* Set the repeat rates based on global preferences and keycodes for modifiers. 3346747b715Smrg * Precondition: Has the keyInfo_mutex lock. 3356747b715Smrg */ 33635c4bbdfSmrgstatic void 33735c4bbdfSmrgDarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, 33835c4bbdfSmrg int keyRepeatValue) 33935c4bbdfSmrg{ 34035c4bbdfSmrg if (initialKeyRepeatValue == 300000) { // off 3416747b715Smrg /* Turn off repeats globally */ 3424642e01fSmrg XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff); 34335c4bbdfSmrg } 34435c4bbdfSmrg else { 3456747b715Smrg int i; 34635c4bbdfSmrg XkbControlsPtr ctrl; 34735c4bbdfSmrg XkbControlsRec old; 3484642e01fSmrg 3496747b715Smrg /* Turn on repeats globally */ 3504642e01fSmrg XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn); 35135c4bbdfSmrg 3526747b715Smrg /* Setup the bit mask for individual key repeats */ 3536747b715Smrg ctrl = pDev->key->xkbInfo->desc->ctrls; 35435c4bbdfSmrg old = *ctrl; 35535c4bbdfSmrg 3566747b715Smrg ctrl->repeat_delay = initialKeyRepeatValue * 15; 3576747b715Smrg ctrl->repeat_interval = keyRepeatValue * 15; 3586747b715Smrg 3596747b715Smrg /* Turn off key-repeat for modifier keys, on for others */ 3606747b715Smrg /* First set them all on */ 36135c4bbdfSmrg for (i = 0; i < XkbPerKeyBitArraySize; i++) 3626747b715Smrg ctrl->per_key_repeat[i] = -1; 3636747b715Smrg 3646747b715Smrg /* Now turn off the modifiers */ 36535c4bbdfSmrg for (i = 0; i < 32; i++) { 3666747b715Smrg unsigned char keycode; 36735c4bbdfSmrg 3686747b715Smrg keycode = keyInfo.modifierKeycodes[i][0]; 36935c4bbdfSmrg if (keycode) 3706747b715Smrg ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); 3716747b715Smrg 3726747b715Smrg keycode = keyInfo.modifierKeycodes[i][1]; 37335c4bbdfSmrg if (keycode) 3746747b715Smrg ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE); 3756747b715Smrg } 3766747b715Smrg 3776747b715Smrg /* Hurray for data duplication */ 3786747b715Smrg if (pDev->kbdfeed) 37935c4bbdfSmrg memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, 38035c4bbdfSmrg XkbPerKeyBitArraySize); 3814642e01fSmrg 38235c4bbdfSmrg //ErrorF("per_key_repeat =\n"); 3836747b715Smrg //for(i=0; i < XkbPerKeyBitArraySize; i++) 38435c4bbdfSmrg // ErrorF("%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n"); 3856747b715Smrg 3866747b715Smrg /* And now we notify the puppies about the changes */ 3876747b715Smrg XkbDDXChangeControls(pDev, &old, ctrl); 3886747b715Smrg } 3894642e01fSmrg} 3904642e01fSmrg 39135c4bbdfSmrgvoid 39235c4bbdfSmrgDarwinKeyboardReloadHandler(void) 39335c4bbdfSmrg{ 3944642e01fSmrg KeySymsRec keySyms; 3956747b715Smrg CFIndex initialKeyRepeatValue, keyRepeatValue; 3966747b715Smrg BOOL ok; 3976747b715Smrg DeviceIntPtr pDev; 3986747b715Smrg const char *xmodmap = PROJECTROOT "/bin/xmodmap"; 3996747b715Smrg const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap"; 4006747b715Smrg const char *homedir = getenv("HOME"); 4016747b715Smrg char usermodmap[PATH_MAX], cmd[PATH_MAX]; 4024642e01fSmrg 4034642e01fSmrg DEBUG_LOG("DarwinKeyboardReloadHandler\n"); 4044642e01fSmrg 4056747b715Smrg /* Get our key repeat settings from GlobalPreferences */ 4066747b715Smrg (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); 40735c4bbdfSmrg 40835c4bbdfSmrg initialKeyRepeatValue = 40935c4bbdfSmrg CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), 41035c4bbdfSmrg CFSTR(".GlobalPreferences"), &ok); 41135c4bbdfSmrg if (!ok) 4126747b715Smrg initialKeyRepeatValue = 35; 41335c4bbdfSmrg 41435c4bbdfSmrg keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR( 41535c4bbdfSmrg "KeyRepeat"), 41635c4bbdfSmrg CFSTR( 41735c4bbdfSmrg ".GlobalPreferences"), 41835c4bbdfSmrg &ok); 41935c4bbdfSmrg if (!ok) 4206747b715Smrg keyRepeatValue = 6; 42135c4bbdfSmrg 42235c4bbdfSmrg pthread_mutex_lock(&keyInfo_mutex); 42335c4bbdfSmrg { 4246747b715Smrg /* Initialize our keySyms */ 4256747b715Smrg keySyms.map = keyInfo.keyMap; 42635c4bbdfSmrg keySyms.mapWidth = GLYPHS_PER_KEY; 4276747b715Smrg keySyms.minKeyCode = MIN_KEYCODE; 4286747b715Smrg keySyms.maxKeyCode = MAX_KEYCODE; 4296747b715Smrg 43035c4bbdfSmrg // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap 4316747b715Smrg /* Apply the mappings to darwinKeyboard */ 4326747b715Smrg XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode, 4336747b715Smrg keySyms.maxKeyCode - keySyms.minKeyCode + 1, 4346747b715Smrg keyInfo.modMap, serverClient); 43535c4bbdfSmrg DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, 43635c4bbdfSmrg keyRepeatValue); 4376747b715Smrg 4386747b715Smrg /* Apply the mappings to the core keyboard */ 4396747b715Smrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 44035c4bbdfSmrg if ((pDev->coreEvents || 44135c4bbdfSmrg pDev == inputInfo.keyboard) && pDev->key) { 44235c4bbdfSmrg XkbApplyMappingChange( 44335c4bbdfSmrg pDev, &keySyms, keySyms.minKeyCode, 44435c4bbdfSmrg keySyms.maxKeyCode - 44535c4bbdfSmrg keySyms.minKeyCode + 1, 44635c4bbdfSmrg keyInfo.modMap, serverClient); 44735c4bbdfSmrg DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, 44835c4bbdfSmrg keyRepeatValue); 4496747b715Smrg } 4506747b715Smrg } 4516747b715Smrg } pthread_mutex_unlock(&keyInfo_mutex); 4526747b715Smrg 4536747b715Smrg /* Modify with xmodmap */ 4546747b715Smrg if (access(xmodmap, F_OK) == 0) { 4556747b715Smrg /* Check for system .Xmodmap */ 4566747b715Smrg if (access(sysmodmap, F_OK) == 0) { 45735c4bbdfSmrg if (snprintf(cmd, sizeof(cmd), "%s %s", xmodmap, 45835c4bbdfSmrg sysmodmap) < sizeof(cmd)) { 4596747b715Smrg X11ApplicationLaunchClient(cmd); 46035c4bbdfSmrg } 46135c4bbdfSmrg else { 46235c4bbdfSmrg ErrorF( 46335c4bbdfSmrg "X11.app: Unable to create / execute xmodmap command line"); 4646747b715Smrg } 4656747b715Smrg } 4666747b715Smrg 4676747b715Smrg /* Check for user's local .Xmodmap */ 46835c4bbdfSmrg if ((homedir != NULL) && 46935c4bbdfSmrg (snprintf(usermodmap, sizeof(usermodmap), "%s/.Xmodmap", 47035c4bbdfSmrg homedir) < sizeof(usermodmap))) { 4716747b715Smrg if (access(usermodmap, F_OK) == 0) { 47235c4bbdfSmrg if (snprintf(cmd, sizeof(cmd), "%s %s", xmodmap, 47335c4bbdfSmrg usermodmap) < sizeof(cmd)) { 4746747b715Smrg X11ApplicationLaunchClient(cmd); 47535c4bbdfSmrg } 47635c4bbdfSmrg else { 47735c4bbdfSmrg ErrorF( 47835c4bbdfSmrg "X11.app: Unable to create / execute xmodmap command line"); 4796747b715Smrg } 4806747b715Smrg } 48135c4bbdfSmrg } 48235c4bbdfSmrg else { 4836747b715Smrg ErrorF("X11.app: Unable to determine path to user's .Xmodmap"); 4846747b715Smrg } 4856747b715Smrg } 4864642e01fSmrg} 4874642e01fSmrg 4884642e01fSmrg//----------------------------------------------------------------------------- 4894642e01fSmrg// Modifier translation functions 4904642e01fSmrg// 4914642e01fSmrg// There are three different ways to specify a Mac modifier key: 4924642e01fSmrg// keycode - specifies hardware key, read from keymapping 4934642e01fSmrg// key - NX_MODIFIERKEY_*, really an index 4944642e01fSmrg// mask - NX_*MASK, mask for modifier flags in event record 4954642e01fSmrg// Left and right side have different keycodes but the same key and mask. 4964642e01fSmrg//----------------------------------------------------------------------------- 4974642e01fSmrg 4984642e01fSmrg/* 4994642e01fSmrg * DarwinModifierNXKeyToNXKeycode 5004642e01fSmrg * Return the keycode for an NX_MODIFIERKEY_* modifier. 5014642e01fSmrg * side = 0 for left or 1 for right. 5024642e01fSmrg * Returns 0 if key+side is not a known modifier. 5034642e01fSmrg */ 50435c4bbdfSmrgint 50535c4bbdfSmrgDarwinModifierNXKeyToNXKeycode(int key, int side) 50635c4bbdfSmrg{ 5074642e01fSmrg int retval; 5084642e01fSmrg pthread_mutex_lock(&keyInfo_mutex); 5094642e01fSmrg retval = keyInfo.modifierKeycodes[key][side]; 5104642e01fSmrg pthread_mutex_unlock(&keyInfo_mutex); 5114642e01fSmrg 5124642e01fSmrg return retval; 5134642e01fSmrg} 5144642e01fSmrg 5154642e01fSmrg/* 5164642e01fSmrg * DarwinModifierNXKeycodeToNXKey 5174642e01fSmrg * Returns -1 if keycode+side is not a modifier key 5184642e01fSmrg * outSide may be NULL, else it gets 0 for left and 1 for right. 5194642e01fSmrg */ 52035c4bbdfSmrgint 52135c4bbdfSmrgDarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) 52235c4bbdfSmrg{ 5234642e01fSmrg int key, side; 5244642e01fSmrg 5254642e01fSmrg keycode += MIN_KEYCODE; 5266747b715Smrg 5274642e01fSmrg // search modifierKeycodes for this keycode+side 5286747b715Smrg pthread_mutex_lock(&keyInfo_mutex); 5294642e01fSmrg for (key = 0; key < NX_NUMMODIFIERS; key++) { 5304642e01fSmrg for (side = 0; side <= 1; side++) { 5314642e01fSmrg if (keyInfo.modifierKeycodes[key][side] == keycode) break; 5324642e01fSmrg } 5334642e01fSmrg } 5346747b715Smrg pthread_mutex_unlock(&keyInfo_mutex); 5356747b715Smrg 5364642e01fSmrg if (key == NX_NUMMODIFIERS) { 5374642e01fSmrg return -1; 5384642e01fSmrg } 5394642e01fSmrg if (outSide) *outSide = side; 5404642e01fSmrg 5414642e01fSmrg return key; 5424642e01fSmrg} 5434642e01fSmrg 5444642e01fSmrg/* 5454642e01fSmrg * DarwinModifierNXMaskToNXKey 5464642e01fSmrg * Returns -1 if mask is not a known modifier mask. 5474642e01fSmrg */ 54835c4bbdfSmrgint 54935c4bbdfSmrgDarwinModifierNXMaskToNXKey(int mask) 55035c4bbdfSmrg{ 5514642e01fSmrg switch (mask) { 55235c4bbdfSmrg case NX_ALPHASHIFTMASK: 55335c4bbdfSmrg return NX_MODIFIERKEY_ALPHALOCK; 55435c4bbdfSmrg 55535c4bbdfSmrg case NX_SHIFTMASK: 55635c4bbdfSmrg return NX_MODIFIERKEY_SHIFT; 55735c4bbdfSmrg 5584642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 55935c4bbdfSmrg case NX_DEVICELSHIFTKEYMASK: 56035c4bbdfSmrg return NX_MODIFIERKEY_SHIFT; 56135c4bbdfSmrg 56235c4bbdfSmrg case NX_DEVICERSHIFTKEYMASK: 56335c4bbdfSmrg return NX_MODIFIERKEY_RSHIFT; 56435c4bbdfSmrg 5654642e01fSmrg#endif 56635c4bbdfSmrg case NX_CONTROLMASK: 56735c4bbdfSmrg return NX_MODIFIERKEY_CONTROL; 56835c4bbdfSmrg 5694642e01fSmrg#ifdef NX_DEVICELCTLKEYMASK 57035c4bbdfSmrg case NX_DEVICELCTLKEYMASK: 57135c4bbdfSmrg return NX_MODIFIERKEY_CONTROL; 57235c4bbdfSmrg 57335c4bbdfSmrg case NX_DEVICERCTLKEYMASK: 57435c4bbdfSmrg return NX_MODIFIERKEY_RCONTROL; 57535c4bbdfSmrg 5764642e01fSmrg#endif 57735c4bbdfSmrg case NX_ALTERNATEMASK: 57835c4bbdfSmrg return NX_MODIFIERKEY_ALTERNATE; 57935c4bbdfSmrg 5804642e01fSmrg#ifdef NX_DEVICELALTKEYMASK 58135c4bbdfSmrg case NX_DEVICELALTKEYMASK: 58235c4bbdfSmrg return NX_MODIFIERKEY_ALTERNATE; 58335c4bbdfSmrg 58435c4bbdfSmrg case NX_DEVICERALTKEYMASK: 58535c4bbdfSmrg return NX_MODIFIERKEY_RALTERNATE; 58635c4bbdfSmrg 5874642e01fSmrg#endif 58835c4bbdfSmrg case NX_COMMANDMASK: 58935c4bbdfSmrg return NX_MODIFIERKEY_COMMAND; 59035c4bbdfSmrg 5914642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 59235c4bbdfSmrg case NX_DEVICELCMDKEYMASK: 59335c4bbdfSmrg return NX_MODIFIERKEY_COMMAND; 59435c4bbdfSmrg 59535c4bbdfSmrg case NX_DEVICERCMDKEYMASK: 59635c4bbdfSmrg return NX_MODIFIERKEY_RCOMMAND; 59735c4bbdfSmrg 5984642e01fSmrg#endif 59935c4bbdfSmrg case NX_NUMERICPADMASK: 60035c4bbdfSmrg return NX_MODIFIERKEY_NUMERICPAD; 60135c4bbdfSmrg 60235c4bbdfSmrg case NX_HELPMASK: 60335c4bbdfSmrg return NX_MODIFIERKEY_HELP; 60435c4bbdfSmrg 60535c4bbdfSmrg case NX_SECONDARYFNMASK: 60635c4bbdfSmrg return NX_MODIFIERKEY_SECONDARYFN; 6074642e01fSmrg } 6084642e01fSmrg return -1; 6094642e01fSmrg} 6104642e01fSmrg 6114642e01fSmrg/* 6124642e01fSmrg * DarwinModifierNXKeyToNXMask 6134642e01fSmrg * Returns 0 if key is not a known modifier key. 6144642e01fSmrg */ 61535c4bbdfSmrgint 61635c4bbdfSmrgDarwinModifierNXKeyToNXMask(int key) 61735c4bbdfSmrg{ 6184642e01fSmrg switch (key) { 61935c4bbdfSmrg case NX_MODIFIERKEY_ALPHALOCK: 62035c4bbdfSmrg return NX_ALPHASHIFTMASK; 62135c4bbdfSmrg 6224642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 62335c4bbdfSmrg case NX_MODIFIERKEY_SHIFT: 62435c4bbdfSmrg return NX_DEVICELSHIFTKEYMASK; 62535c4bbdfSmrg 62635c4bbdfSmrg case NX_MODIFIERKEY_RSHIFT: 62735c4bbdfSmrg return NX_DEVICERSHIFTKEYMASK; 62835c4bbdfSmrg 62935c4bbdfSmrg case NX_MODIFIERKEY_CONTROL: 63035c4bbdfSmrg return NX_DEVICELCTLKEYMASK; 63135c4bbdfSmrg 63235c4bbdfSmrg case NX_MODIFIERKEY_RCONTROL: 63335c4bbdfSmrg return NX_DEVICERCTLKEYMASK; 63435c4bbdfSmrg 63535c4bbdfSmrg case NX_MODIFIERKEY_ALTERNATE: 63635c4bbdfSmrg return NX_DEVICELALTKEYMASK; 63735c4bbdfSmrg 63835c4bbdfSmrg case NX_MODIFIERKEY_RALTERNATE: 63935c4bbdfSmrg return NX_DEVICERALTKEYMASK; 64035c4bbdfSmrg 64135c4bbdfSmrg case NX_MODIFIERKEY_COMMAND: 64235c4bbdfSmrg return NX_DEVICELCMDKEYMASK; 64335c4bbdfSmrg 64435c4bbdfSmrg case NX_MODIFIERKEY_RCOMMAND: 64535c4bbdfSmrg return NX_DEVICERCMDKEYMASK; 64635c4bbdfSmrg 6474642e01fSmrg#else 64835c4bbdfSmrg case NX_MODIFIERKEY_SHIFT: 64935c4bbdfSmrg return NX_SHIFTMASK; 65035c4bbdfSmrg 65135c4bbdfSmrg case NX_MODIFIERKEY_CONTROL: 65235c4bbdfSmrg return NX_CONTROLMASK; 65335c4bbdfSmrg 65435c4bbdfSmrg case NX_MODIFIERKEY_ALTERNATE: 65535c4bbdfSmrg return NX_ALTERNATEMASK; 65635c4bbdfSmrg 65735c4bbdfSmrg case NX_MODIFIERKEY_COMMAND: 65835c4bbdfSmrg return NX_COMMANDMASK; 65935c4bbdfSmrg 66035c4bbdfSmrg#endif 66135c4bbdfSmrg case NX_MODIFIERKEY_NUMERICPAD: 66235c4bbdfSmrg return NX_NUMERICPADMASK; 66335c4bbdfSmrg 66435c4bbdfSmrg case NX_MODIFIERKEY_HELP: 66535c4bbdfSmrg return NX_HELPMASK; 66635c4bbdfSmrg 66735c4bbdfSmrg case NX_MODIFIERKEY_SECONDARYFN: 66835c4bbdfSmrg return NX_SECONDARYFNMASK; 6694642e01fSmrg } 6704642e01fSmrg return 0; 6714642e01fSmrg} 6724642e01fSmrg 6734642e01fSmrg/* 6744642e01fSmrg * DarwinModifierStringToNXMask 6754642e01fSmrg * Returns 0 if string is not a known modifier. 6764642e01fSmrg */ 67735c4bbdfSmrgint 67835c4bbdfSmrgDarwinModifierStringToNXMask(const char *str, int separatelr) 67935c4bbdfSmrg{ 6804642e01fSmrg#ifdef NX_DEVICELSHIFTKEYMASK 68135c4bbdfSmrg if (separatelr) { 68235c4bbdfSmrg if (!strcasecmp(str, 68335c4bbdfSmrg "shift")) return NX_DEVICELSHIFTKEYMASK | 68435c4bbdfSmrg NX_DEVICERSHIFTKEYMASK; 68535c4bbdfSmrg if (!strcasecmp(str, 68635c4bbdfSmrg "control")) return NX_DEVICELCTLKEYMASK | 68735c4bbdfSmrg NX_DEVICERCTLKEYMASK; 68835c4bbdfSmrg if (!strcasecmp(str, 68935c4bbdfSmrg "option")) return NX_DEVICELALTKEYMASK | 69035c4bbdfSmrg NX_DEVICERALTKEYMASK; 69135c4bbdfSmrg if (!strcasecmp(str, 69235c4bbdfSmrg "alt")) return NX_DEVICELALTKEYMASK | 69335c4bbdfSmrg NX_DEVICERALTKEYMASK; 69435c4bbdfSmrg if (!strcasecmp(str, 69535c4bbdfSmrg "command")) return NX_DEVICELCMDKEYMASK | 69635c4bbdfSmrg NX_DEVICERCMDKEYMASK; 69735c4bbdfSmrg if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK; 69835c4bbdfSmrg if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK; 6994642e01fSmrg if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK; 7004642e01fSmrg if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK; 70135c4bbdfSmrg if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK; 70235c4bbdfSmrg if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK; 70335c4bbdfSmrg if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK; 70435c4bbdfSmrg if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK; 7054642e01fSmrg if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK; 7064642e01fSmrg if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK; 7074642e01fSmrg } 70835c4bbdfSmrg else { 7094642e01fSmrg#endif 71035c4bbdfSmrg if (!strcasecmp(str, "shift")) return NX_SHIFTMASK; 71135c4bbdfSmrg if (!strcasecmp(str, "control")) return NX_CONTROLMASK; 71235c4bbdfSmrg if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK; 71335c4bbdfSmrg if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK; 71435c4bbdfSmrg if (!strcasecmp(str, "command")) return NX_COMMANDMASK; 71535c4bbdfSmrg if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK; 71635c4bbdfSmrg if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK; 71735c4bbdfSmrg if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK; 71835c4bbdfSmrg if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK; 71935c4bbdfSmrg if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK; 72035c4bbdfSmrg if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK; 72135c4bbdfSmrg if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK; 72235c4bbdfSmrg if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK; 72335c4bbdfSmrg if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK; 72435c4bbdfSmrg if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK; 72535c4bbdfSmrg#ifdef NX_DEVICELSHIFTKEYMASK 72635c4bbdfSmrg} 72735c4bbdfSmrg#endif 72835c4bbdfSmrg if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK; 72935c4bbdfSmrg if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK; 73035c4bbdfSmrg if (!strcasecmp(str, "help")) return NX_HELPMASK; 73135c4bbdfSmrg if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK; 7324642e01fSmrg return 0; 7334642e01fSmrg} 7344642e01fSmrg 73535c4bbdfSmrgstatic KeySym 73635c4bbdfSmrgmake_dead_key(KeySym in) 73735c4bbdfSmrg{ 7384642e01fSmrg int i; 7394642e01fSmrg 7401b5d61b8Smrg for (i = 0; i < ARRAY_SIZE(dead_keys); i++) 7414642e01fSmrg if (dead_keys[i].normal == in) return dead_keys[i].dead; 7424642e01fSmrg 7434642e01fSmrg return in; 7444642e01fSmrg} 7454642e01fSmrg 74635c4bbdfSmrgstatic Bool 74735c4bbdfSmrgQuartzReadSystemKeymap(darwinKeyboardInfo *info) 74835c4bbdfSmrg{ 749c8548ba8Smrg __block const void *chr_data = NULL; 7504642e01fSmrg int num_keycodes = NUM_KEYCODES; 751c8548ba8Smrg __block UInt32 keyboard_type; 7524642e01fSmrg int i, j; 7534642e01fSmrg OSStatus err; 7544642e01fSmrg KeySym *k; 7554642e01fSmrg 756c8548ba8Smrg dispatch_block_t getKeyboardData = ^{ 757c8548ba8Smrg keyboard_type = LMGetKbdType(); 75835c4bbdfSmrg 759c8548ba8Smrg TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); 7604642e01fSmrg 761c8548ba8Smrg if (currentKeyLayoutRef) { 762c8548ba8Smrg CFDataRef currentKeyLayoutDataRef = (CFDataRef)TISGetInputSourceProperty(currentKeyLayoutRef, 763c8548ba8Smrg kTISPropertyUnicodeKeyLayoutData); 764c8548ba8Smrg if (currentKeyLayoutDataRef) 765c8548ba8Smrg chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); 7664642e01fSmrg 767c8548ba8Smrg CFRelease(currentKeyLayoutRef); 7684642e01fSmrg } 769c8548ba8Smrg }; 7704642e01fSmrg 771c8548ba8Smrg /* This is an ugly ant-pattern, but it is more expedient to address the problem right now. */ 772c8548ba8Smrg if (pthread_main_np()) { 773c8548ba8Smrg getKeyboardData(); 774c8548ba8Smrg } else { 775c8548ba8Smrg dispatch_sync(dispatch_get_main_queue(), getKeyboardData); 7764642e01fSmrg } 77735c4bbdfSmrg 7784642e01fSmrg if (chr_data == NULL) { 77935c4bbdfSmrg ErrorF("Couldn't get uchr or kchr resource\n"); 78035c4bbdfSmrg return FALSE; 7814642e01fSmrg } 78235c4bbdfSmrg 7834642e01fSmrg /* Scan the keycode range for the Unicode character that each 7844642e01fSmrg key produces in the four shift states. Then convert that to 7854642e01fSmrg an X11 keysym (which may just the bit that says "this is 7864642e01fSmrg Unicode" if it can't find the real symbol.) */ 78735c4bbdfSmrg 7884642e01fSmrg /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate 7894642e01fSmrg must be used instead. */ 7904642e01fSmrg 7914642e01fSmrg for (i = 0; i < num_keycodes; i++) { 79235c4bbdfSmrg static const int mods[4] = { 79335c4bbdfSmrg 0, MOD_SHIFT, MOD_OPTION, 79435c4bbdfSmrg MOD_OPTION | MOD_SHIFT 79535c4bbdfSmrg }; 7964642e01fSmrg 7974642e01fSmrg k = info->keyMap + i * GLYPHS_PER_KEY; 7984642e01fSmrg 7994642e01fSmrg for (j = 0; j < 4; j++) { 80035c4bbdfSmrg UniChar s[8]; 80135c4bbdfSmrg UniCharCount len; 80235c4bbdfSmrg UInt32 dead_key_state = 0, extra_dead = 0; 80335c4bbdfSmrg 80435c4bbdfSmrg err = UCKeyTranslate(chr_data, i, kUCKeyActionDown, 80535c4bbdfSmrg mods[j] >> 8, keyboard_type, 0, 80635c4bbdfSmrg &dead_key_state, 8, &len, s); 80735c4bbdfSmrg if (err != noErr) continue; 80835c4bbdfSmrg 80935c4bbdfSmrg if (len == 0 && dead_key_state != 0) { 81035c4bbdfSmrg /* Found a dead key. Work out which one it is, but 81135c4bbdfSmrg remembering that it's dead. */ 81235c4bbdfSmrg err = UCKeyTranslate(chr_data, i, kUCKeyActionDown, 81335c4bbdfSmrg mods[j] >> 8, keyboard_type, 81435c4bbdfSmrg kUCKeyTranslateNoDeadKeysMask, 81535c4bbdfSmrg &extra_dead, 8, &len, s); 8164642e01fSmrg if (err != noErr) continue; 81735c4bbdfSmrg } 8184642e01fSmrg 81935c4bbdfSmrg /* Not sure why 0x0010 is there. 82035c4bbdfSmrg * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ... 82135c4bbdfSmrg */ 82235c4bbdfSmrg if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) { 82335c4bbdfSmrg k[j] = ucs2keysym(s[0]); 82435c4bbdfSmrg if (dead_key_state != 0) k[j] = make_dead_key(k[j]); 82535c4bbdfSmrg } 8264642e01fSmrg } 8276747b715Smrg 8284642e01fSmrg if (k[3] == k[2]) k[3] = NoSymbol; 8294642e01fSmrg if (k[1] == k[0]) k[1] = NoSymbol; 8304642e01fSmrg if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; 8316747b715Smrg if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol; 8324642e01fSmrg } 8334642e01fSmrg 8346747b715Smrg#if HACK_MISSING 8354642e01fSmrg /* Fix up some things that are normally missing.. */ 83635c4bbdfSmrg 8371b5d61b8Smrg for (i = 0; i < ARRAY_SIZE(known_keys); i++) { 8386747b715Smrg k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY; 83935c4bbdfSmrg 84035c4bbdfSmrg if (k[0] == NoSymbol && k[1] == NoSymbol 8416747b715Smrg && k[2] == NoSymbol && k[3] == NoSymbol) 8426747b715Smrg k[0] = known_keys[i].keysym; 8434642e01fSmrg } 8446747b715Smrg#endif 84535c4bbdfSmrg 8466747b715Smrg#if HACK_KEYPAD 8474642e01fSmrg /* And some more things. We find the right symbols for the numeric 84835c4bbdfSmrg keypad, but not the KP_ keysyms. So try to convert known keycodes. */ 8491b5d61b8Smrg for (i = 0; i < ARRAY_SIZE(known_numeric_keys); i++) { 8506747b715Smrg k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY; 85135c4bbdfSmrg 8526747b715Smrg if (k[0] == known_numeric_keys[i].normal) 8536747b715Smrg k[0] = known_numeric_keys[i].keypad; 8544642e01fSmrg } 8556747b715Smrg#endif 85635c4bbdfSmrg 8576747b715Smrg#if HACK_BLACKLIST 8581b5d61b8Smrg for (i = 0; i < ARRAY_SIZE(keycode_blacklist); i++) { 8596747b715Smrg k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY; 8606747b715Smrg k[0] = k[1] = k[2] = k[3] = NoSymbol; 8616747b715Smrg } 8626747b715Smrg#endif 8636747b715Smrg 8646747b715Smrg DarwinBuildModifierMaps(info); 8654642e01fSmrg 8664642e01fSmrg return TRUE; 8674642e01fSmrg} 8686747b715Smrg 86935c4bbdfSmrgBool 87035c4bbdfSmrgQuartsResyncKeymap(Bool sendDDXEvent) 87135c4bbdfSmrg{ 8726747b715Smrg Bool retval; 8736747b715Smrg /* Update keyInfo */ 8746747b715Smrg pthread_mutex_lock(&keyInfo_mutex); 8756747b715Smrg memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); 8766747b715Smrg retval = QuartzReadSystemKeymap(&keyInfo); 8776747b715Smrg pthread_mutex_unlock(&keyInfo_mutex); 8786747b715Smrg 8796747b715Smrg /* Tell server thread to deal with new keyInfo */ 88035c4bbdfSmrg if (sendDDXEvent) 8816747b715Smrg DarwinSendDDXEvent(kXquartzReloadKeymap, 0); 8826747b715Smrg 8836747b715Smrg return retval; 8846747b715Smrg} 885