1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun quartzKeyboard.c: Keyboard support for Xquartz
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun Copyright (c) 2003-2012 Apple Inc.
5*4882a593Smuzhiyun Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved.
6*4882a593Smuzhiyun Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
9*4882a593Smuzhiyun All rights reserved.
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun Redistribution and use in source and binary forms, with or without
12*4882a593Smuzhiyun modification, are permitted provided that the following conditions are met:
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun 1. Redistributions of source code must retain the above copyright
15*4882a593Smuzhiyun notice, this list of conditions and the following disclaimer.
16*4882a593Smuzhiyun 2. Redistributions in binary form must reproduce the above copyright
17*4882a593Smuzhiyun notice, this list of conditions and the following disclaimer in the
18*4882a593Smuzhiyun documentation and/or other materials provided with the distribution.
19*4882a593Smuzhiyun 3. The name of the author may not be used to endorse or promote products
20*4882a593Smuzhiyun derived from this software without specific prior written permission.
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23*4882a593Smuzhiyun IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24*4882a593Smuzhiyun OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
25*4882a593Smuzhiyun NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*4882a593Smuzhiyun SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27*4882a593Smuzhiyun TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28*4882a593Smuzhiyun PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29*4882a593Smuzhiyun LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30*4882a593Smuzhiyun NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31*4882a593Smuzhiyun SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include "sanitizedCarbon.h"
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
37*4882a593Smuzhiyun #include <dix-config.h>
38*4882a593Smuzhiyun #endif
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define HACK_MISSING 1
41*4882a593Smuzhiyun #define HACK_KEYPAD 1
42*4882a593Smuzhiyun #define HACK_BLACKLIST 1
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #include <unistd.h>
45*4882a593Smuzhiyun #include <stdio.h>
46*4882a593Smuzhiyun #include <stdlib.h>
47*4882a593Smuzhiyun #include <errno.h>
48*4882a593Smuzhiyun #include <sys/stat.h>
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #include "quartz.h"
51*4882a593Smuzhiyun #include "darwin.h"
52*4882a593Smuzhiyun #include "darwinEvents.h"
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #include "quartzKeyboard.h"
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #include "X11Application.h"
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #include <assert.h>
59*4882a593Smuzhiyun #include <pthread.h>
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #include "xkbsrv.h"
62*4882a593Smuzhiyun #include "exevents.h"
63*4882a593Smuzhiyun #include "X11/keysym.h"
64*4882a593Smuzhiyun #include "keysym2ucs.h"
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun extern void
67*4882a593Smuzhiyun CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun enum {
70*4882a593Smuzhiyun MOD_COMMAND = 256,
71*4882a593Smuzhiyun MOD_SHIFT = 512,
72*4882a593Smuzhiyun MOD_OPTION = 2048,
73*4882a593Smuzhiyun MOD_CONTROL = 4096,
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun #define UKEYSYM(u) ((u) | 0x01000000)
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun #if HACK_MISSING
79*4882a593Smuzhiyun /* Table of keycode->keysym mappings we use to fallback on for important
80*4882a593Smuzhiyun keys that are often not in the Unicode mapping. */
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun const static struct {
83*4882a593Smuzhiyun unsigned short keycode;
84*4882a593Smuzhiyun KeySym keysym;
85*4882a593Smuzhiyun } known_keys[] = {
86*4882a593Smuzhiyun { 55, XK_Meta_L },
87*4882a593Smuzhiyun { 56, XK_Shift_L },
88*4882a593Smuzhiyun { 57, XK_Caps_Lock },
89*4882a593Smuzhiyun { 58, XK_Alt_L },
90*4882a593Smuzhiyun { 59, XK_Control_L },
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun { 60, XK_Shift_R },
93*4882a593Smuzhiyun { 61, XK_Alt_R },
94*4882a593Smuzhiyun { 62, XK_Control_R },
95*4882a593Smuzhiyun { 63, XK_Meta_R },
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun { 110, XK_Menu },
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun { 122, XK_F1 },
100*4882a593Smuzhiyun { 120, XK_F2 },
101*4882a593Smuzhiyun { 99, XK_F3 },
102*4882a593Smuzhiyun { 118, XK_F4 },
103*4882a593Smuzhiyun { 96, XK_F5 },
104*4882a593Smuzhiyun { 97, XK_F6 },
105*4882a593Smuzhiyun { 98, XK_F7 },
106*4882a593Smuzhiyun { 100, XK_F8 },
107*4882a593Smuzhiyun { 101, XK_F9 },
108*4882a593Smuzhiyun { 109, XK_F10 },
109*4882a593Smuzhiyun { 103, XK_F11 },
110*4882a593Smuzhiyun { 111, XK_F12 },
111*4882a593Smuzhiyun { 105, XK_F13 },
112*4882a593Smuzhiyun { 107, XK_F14 },
113*4882a593Smuzhiyun { 113, XK_F15 },
114*4882a593Smuzhiyun { 106, XK_F16 },
115*4882a593Smuzhiyun { 64, XK_F17 },
116*4882a593Smuzhiyun { 79, XK_F18 },
117*4882a593Smuzhiyun { 80, XK_F19 },
118*4882a593Smuzhiyun { 90, XK_F20 },
119*4882a593Smuzhiyun };
120*4882a593Smuzhiyun #endif
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun #if HACK_KEYPAD
123*4882a593Smuzhiyun /* Table of keycode->old,new-keysym mappings we use to fixup the numeric
124*4882a593Smuzhiyun keypad entries. */
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun const static struct {
127*4882a593Smuzhiyun unsigned short keycode;
128*4882a593Smuzhiyun KeySym normal, keypad;
129*4882a593Smuzhiyun } known_numeric_keys[] = {
130*4882a593Smuzhiyun { 65, XK_period, XK_KP_Decimal },
131*4882a593Smuzhiyun { 67, XK_asterisk, XK_KP_Multiply },
132*4882a593Smuzhiyun { 69, XK_plus, XK_KP_Add },
133*4882a593Smuzhiyun { 75, XK_slash, XK_KP_Divide },
134*4882a593Smuzhiyun { 76, 0x01000003, XK_KP_Enter },
135*4882a593Smuzhiyun { 78, XK_minus, XK_KP_Subtract },
136*4882a593Smuzhiyun { 81, XK_equal, XK_KP_Equal },
137*4882a593Smuzhiyun { 82, XK_0, XK_KP_0 },
138*4882a593Smuzhiyun { 83, XK_1, XK_KP_1 },
139*4882a593Smuzhiyun { 84, XK_2, XK_KP_2 },
140*4882a593Smuzhiyun { 85, XK_3, XK_KP_3 },
141*4882a593Smuzhiyun { 86, XK_4, XK_KP_4 },
142*4882a593Smuzhiyun { 87, XK_5, XK_KP_5 },
143*4882a593Smuzhiyun { 88, XK_6, XK_KP_6 },
144*4882a593Smuzhiyun { 89, XK_7, XK_KP_7 },
145*4882a593Smuzhiyun { 91, XK_8, XK_KP_8 },
146*4882a593Smuzhiyun { 92, XK_9, XK_KP_9 },
147*4882a593Smuzhiyun };
148*4882a593Smuzhiyun #endif
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #if HACK_BLACKLIST
151*4882a593Smuzhiyun /* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow
152*4882a593Smuzhiyun * http://xquartz.macosforge.org/trac/ticket/295
153*4882a593Smuzhiyun * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html
154*4882a593Smuzhiyun *
155*4882a593Smuzhiyun * legacy Mac keycodes for arrow keys that shift-modify to math symbols
156*4882a593Smuzhiyun */
157*4882a593Smuzhiyun const static unsigned short keycode_blacklist[] = { 66, 70, 72, 77 };
158*4882a593Smuzhiyun #endif
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* Table mapping normal keysyms to their dead equivalents.
161*4882a593Smuzhiyun FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun const static struct {
164*4882a593Smuzhiyun KeySym normal, dead;
165*4882a593Smuzhiyun } dead_keys[] = {
166*4882a593Smuzhiyun { XK_grave, XK_dead_grave },
167*4882a593Smuzhiyun { XK_apostrophe, XK_dead_acute }, /* US:"=" on a Czech keyboard */
168*4882a593Smuzhiyun { XK_acute, XK_dead_acute },
169*4882a593Smuzhiyun { UKEYSYM(0x384), XK_dead_acute }, /* US:";" on a Greek keyboard */
170*4882a593Smuzhiyun // {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */
171*4882a593Smuzhiyun { XK_asciicircum, XK_dead_circumflex },
172*4882a593Smuzhiyun { UKEYSYM(0x2c6), XK_dead_circumflex }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
173*4882a593Smuzhiyun { XK_asciitilde, XK_dead_tilde },
174*4882a593Smuzhiyun { UKEYSYM(0x2dc), XK_dead_tilde }, /* SMALL TILDE */
175*4882a593Smuzhiyun { XK_macron, XK_dead_macron },
176*4882a593Smuzhiyun { XK_breve, XK_dead_breve },
177*4882a593Smuzhiyun { XK_abovedot, XK_dead_abovedot },
178*4882a593Smuzhiyun { XK_diaeresis, XK_dead_diaeresis },
179*4882a593Smuzhiyun { UKEYSYM(0x2da), XK_dead_abovering }, /* DOT ABOVE */
180*4882a593Smuzhiyun { XK_doubleacute, XK_dead_doubleacute },
181*4882a593Smuzhiyun { XK_caron, XK_dead_caron },
182*4882a593Smuzhiyun { XK_cedilla, XK_dead_cedilla },
183*4882a593Smuzhiyun { XK_ogonek, XK_dead_ogonek },
184*4882a593Smuzhiyun { UKEYSYM(0x269), XK_dead_iota }, /* LATIN SMALL LETTER IOTA */
185*4882a593Smuzhiyun { UKEYSYM(0x2ec), XK_dead_voiced_sound }, /* MODIFIER LETTER VOICING */
186*4882a593Smuzhiyun /* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
187*4882a593Smuzhiyun { UKEYSYM(0x323), XK_dead_belowdot }, /* COMBINING DOT BELOW */
188*4882a593Smuzhiyun { UKEYSYM(0x309), XK_dead_hook }, /* COMBINING HOOK ABOVE */
189*4882a593Smuzhiyun { UKEYSYM(0x31b), XK_dead_horn }, /* COMBINING HORN */
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun typedef struct darwinKeyboardInfo_struct {
193*4882a593Smuzhiyun CARD8 modMap[MAP_LENGTH];
194*4882a593Smuzhiyun KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY];
195*4882a593Smuzhiyun unsigned char modifierKeycodes[32][2];
196*4882a593Smuzhiyun } darwinKeyboardInfo;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun darwinKeyboardInfo keyInfo;
199*4882a593Smuzhiyun pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun static void
DarwinChangeKeyboardControl(DeviceIntPtr device,KeybdCtrl * ctrl)202*4882a593Smuzhiyun DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun // FIXME: to be implemented
205*4882a593Smuzhiyun // keyclick, bell volume / pitch, autorepead, LED's
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun //-----------------------------------------------------------------------------
209*4882a593Smuzhiyun // Utility functions to help parse Darwin keymap
210*4882a593Smuzhiyun //-----------------------------------------------------------------------------
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun /*
213*4882a593Smuzhiyun * DarwinBuildModifierMaps
214*4882a593Smuzhiyun * Use the keyMap field of keyboard info structure to populate
215*4882a593Smuzhiyun * the modMap and modifierKeycodes fields.
216*4882a593Smuzhiyun */
217*4882a593Smuzhiyun static void
DarwinBuildModifierMaps(darwinKeyboardInfo * info)218*4882a593Smuzhiyun DarwinBuildModifierMaps(darwinKeyboardInfo *info)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun int i;
221*4882a593Smuzhiyun KeySym *k;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun memset(info->modMap, NoSymbol, sizeof(info->modMap));
224*4882a593Smuzhiyun memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes));
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun for (i = 0; i < NUM_KEYCODES; i++) {
227*4882a593Smuzhiyun k = info->keyMap + i * GLYPHS_PER_KEY;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun switch (*k) {
230*4882a593Smuzhiyun case XK_Shift_L:
231*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
232*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = ShiftMask;
233*4882a593Smuzhiyun break;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun case XK_Shift_R:
236*4882a593Smuzhiyun #ifdef NX_MODIFIERKEY_RSHIFT
237*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i;
238*4882a593Smuzhiyun #else
239*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
240*4882a593Smuzhiyun #endif
241*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = ShiftMask;
242*4882a593Smuzhiyun break;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun case XK_Control_L:
245*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
246*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = ControlMask;
247*4882a593Smuzhiyun break;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun case XK_Control_R:
250*4882a593Smuzhiyun #ifdef NX_MODIFIERKEY_RCONTROL
251*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i;
252*4882a593Smuzhiyun #else
253*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
254*4882a593Smuzhiyun #endif
255*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = ControlMask;
256*4882a593Smuzhiyun break;
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun case XK_Caps_Lock:
259*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
260*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = LockMask;
261*4882a593Smuzhiyun break;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun case XK_Alt_L:
264*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
265*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = Mod1Mask;
266*4882a593Smuzhiyun if (!XQuartzOptionSendsAlt)
267*4882a593Smuzhiyun *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
268*4882a593Smuzhiyun break;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun case XK_Alt_R:
271*4882a593Smuzhiyun #ifdef NX_MODIFIERKEY_RALTERNATE
272*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
273*4882a593Smuzhiyun #else
274*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
275*4882a593Smuzhiyun #endif
276*4882a593Smuzhiyun if (!XQuartzOptionSendsAlt)
277*4882a593Smuzhiyun *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
278*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = Mod1Mask;
279*4882a593Smuzhiyun break;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun case XK_Mode_switch:
282*4882a593Smuzhiyun ErrorF(
283*4882a593Smuzhiyun "DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n");
284*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
285*4882a593Smuzhiyun #ifdef NX_MODIFIERKEY_RALTERNATE
286*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
287*4882a593Smuzhiyun #endif
288*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = Mod1Mask;
289*4882a593Smuzhiyun break;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun case XK_Meta_L:
292*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
293*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = Mod2Mask;
294*4882a593Smuzhiyun break;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun case XK_Meta_R:
297*4882a593Smuzhiyun #ifdef NX_MODIFIERKEY_RCOMMAND
298*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i;
299*4882a593Smuzhiyun #else
300*4882a593Smuzhiyun info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
301*4882a593Smuzhiyun #endif
302*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = Mod2Mask;
303*4882a593Smuzhiyun break;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun case XK_Num_Lock:
306*4882a593Smuzhiyun info->modMap[MIN_KEYCODE + i] = Mod3Mask;
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /*
313*4882a593Smuzhiyun * DarwinKeyboardInit
314*4882a593Smuzhiyun * Get the Darwin keyboard map and compute an equivalent
315*4882a593Smuzhiyun * X keyboard map and modifier map. Set the new keyboard
316*4882a593Smuzhiyun * device structure.
317*4882a593Smuzhiyun */
318*4882a593Smuzhiyun void
DarwinKeyboardInit(DeviceIntPtr pDev)319*4882a593Smuzhiyun DarwinKeyboardInit(DeviceIntPtr pDev)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun // Open a shared connection to the HID System.
322*4882a593Smuzhiyun // Note that the Event Status Driver is really just a wrapper
323*4882a593Smuzhiyun // for a kIOHIDParamConnectType connection.
324*4882a593Smuzhiyun assert(darwinParamConnect = NXOpenEventStatus());
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun DarwinKeyboardReloadHandler();
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun CopyKeyClass(pDev, inputInfo.keyboard);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /* Set the repeat rates based on global preferences and keycodes for modifiers.
334*4882a593Smuzhiyun * Precondition: Has the keyInfo_mutex lock.
335*4882a593Smuzhiyun */
336*4882a593Smuzhiyun static void
DarwinKeyboardSetRepeat(DeviceIntPtr pDev,int initialKeyRepeatValue,int keyRepeatValue)337*4882a593Smuzhiyun DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue,
338*4882a593Smuzhiyun int keyRepeatValue)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun if (initialKeyRepeatValue == 300000) { // off
341*4882a593Smuzhiyun /* Turn off repeats globally */
342*4882a593Smuzhiyun XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun else {
345*4882a593Smuzhiyun int i;
346*4882a593Smuzhiyun XkbControlsPtr ctrl;
347*4882a593Smuzhiyun XkbControlsRec old;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /* Turn on repeats globally */
350*4882a593Smuzhiyun XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn);
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun /* Setup the bit mask for individual key repeats */
353*4882a593Smuzhiyun ctrl = pDev->key->xkbInfo->desc->ctrls;
354*4882a593Smuzhiyun old = *ctrl;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun ctrl->repeat_delay = initialKeyRepeatValue * 15;
357*4882a593Smuzhiyun ctrl->repeat_interval = keyRepeatValue * 15;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /* Turn off key-repeat for modifier keys, on for others */
360*4882a593Smuzhiyun /* First set them all on */
361*4882a593Smuzhiyun for (i = 0; i < XkbPerKeyBitArraySize; i++)
362*4882a593Smuzhiyun ctrl->per_key_repeat[i] = -1;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Now turn off the modifiers */
365*4882a593Smuzhiyun for (i = 0; i < 32; i++) {
366*4882a593Smuzhiyun unsigned char keycode;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun keycode = keyInfo.modifierKeycodes[i][0];
369*4882a593Smuzhiyun if (keycode)
370*4882a593Smuzhiyun ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun keycode = keyInfo.modifierKeycodes[i][1];
373*4882a593Smuzhiyun if (keycode)
374*4882a593Smuzhiyun ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /* Hurray for data duplication */
378*4882a593Smuzhiyun if (pDev->kbdfeed)
379*4882a593Smuzhiyun memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat,
380*4882a593Smuzhiyun XkbPerKeyBitArraySize);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun //ErrorF("per_key_repeat =\n");
383*4882a593Smuzhiyun //for(i=0; i < XkbPerKeyBitArraySize; i++)
384*4882a593Smuzhiyun // ErrorF("%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n");
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /* And now we notify the puppies about the changes */
387*4882a593Smuzhiyun XkbDDXChangeControls(pDev, &old, ctrl);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun void
DarwinKeyboardReloadHandler(void)392*4882a593Smuzhiyun DarwinKeyboardReloadHandler(void)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun KeySymsRec keySyms;
395*4882a593Smuzhiyun CFIndex initialKeyRepeatValue, keyRepeatValue;
396*4882a593Smuzhiyun BOOL ok;
397*4882a593Smuzhiyun DeviceIntPtr pDev;
398*4882a593Smuzhiyun const char *xmodmap = PROJECTROOT "/bin/xmodmap";
399*4882a593Smuzhiyun const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap";
400*4882a593Smuzhiyun const char *homedir = getenv("HOME");
401*4882a593Smuzhiyun char usermodmap[PATH_MAX], cmd[PATH_MAX];
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun DEBUG_LOG("DarwinKeyboardReloadHandler\n");
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /* Get our key repeat settings from GlobalPreferences */
406*4882a593Smuzhiyun (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun initialKeyRepeatValue =
409*4882a593Smuzhiyun CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"),
410*4882a593Smuzhiyun CFSTR(".GlobalPreferences"), &ok);
411*4882a593Smuzhiyun if (!ok)
412*4882a593Smuzhiyun initialKeyRepeatValue = 35;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR(
415*4882a593Smuzhiyun "KeyRepeat"),
416*4882a593Smuzhiyun CFSTR(
417*4882a593Smuzhiyun ".GlobalPreferences"),
418*4882a593Smuzhiyun &ok);
419*4882a593Smuzhiyun if (!ok)
420*4882a593Smuzhiyun keyRepeatValue = 6;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun pthread_mutex_lock(&keyInfo_mutex);
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun /* Initialize our keySyms */
425*4882a593Smuzhiyun keySyms.map = keyInfo.keyMap;
426*4882a593Smuzhiyun keySyms.mapWidth = GLYPHS_PER_KEY;
427*4882a593Smuzhiyun keySyms.minKeyCode = MIN_KEYCODE;
428*4882a593Smuzhiyun keySyms.maxKeyCode = MAX_KEYCODE;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap
431*4882a593Smuzhiyun /* Apply the mappings to darwinKeyboard */
432*4882a593Smuzhiyun XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode,
433*4882a593Smuzhiyun keySyms.maxKeyCode - keySyms.minKeyCode + 1,
434*4882a593Smuzhiyun keyInfo.modMap, serverClient);
435*4882a593Smuzhiyun DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue,
436*4882a593Smuzhiyun keyRepeatValue);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /* Apply the mappings to the core keyboard */
439*4882a593Smuzhiyun for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
440*4882a593Smuzhiyun if ((pDev->coreEvents ||
441*4882a593Smuzhiyun pDev == inputInfo.keyboard) && pDev->key) {
442*4882a593Smuzhiyun XkbApplyMappingChange(
443*4882a593Smuzhiyun pDev, &keySyms, keySyms.minKeyCode,
444*4882a593Smuzhiyun keySyms.maxKeyCode -
445*4882a593Smuzhiyun keySyms.minKeyCode + 1,
446*4882a593Smuzhiyun keyInfo.modMap, serverClient);
447*4882a593Smuzhiyun DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue,
448*4882a593Smuzhiyun keyRepeatValue);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun } pthread_mutex_unlock(&keyInfo_mutex);
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun /* Modify with xmodmap */
454*4882a593Smuzhiyun if (access(xmodmap, F_OK) == 0) {
455*4882a593Smuzhiyun /* Check for system .Xmodmap */
456*4882a593Smuzhiyun if (access(sysmodmap, F_OK) == 0) {
457*4882a593Smuzhiyun if (snprintf(cmd, sizeof(cmd), "%s %s", xmodmap,
458*4882a593Smuzhiyun sysmodmap) < sizeof(cmd)) {
459*4882a593Smuzhiyun X11ApplicationLaunchClient(cmd);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun else {
462*4882a593Smuzhiyun ErrorF(
463*4882a593Smuzhiyun "X11.app: Unable to create / execute xmodmap command line");
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun /* Check for user's local .Xmodmap */
468*4882a593Smuzhiyun if ((homedir != NULL) &&
469*4882a593Smuzhiyun (snprintf(usermodmap, sizeof(usermodmap), "%s/.Xmodmap",
470*4882a593Smuzhiyun homedir) < sizeof(usermodmap))) {
471*4882a593Smuzhiyun if (access(usermodmap, F_OK) == 0) {
472*4882a593Smuzhiyun if (snprintf(cmd, sizeof(cmd), "%s %s", xmodmap,
473*4882a593Smuzhiyun usermodmap) < sizeof(cmd)) {
474*4882a593Smuzhiyun X11ApplicationLaunchClient(cmd);
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun else {
477*4882a593Smuzhiyun ErrorF(
478*4882a593Smuzhiyun "X11.app: Unable to create / execute xmodmap command line");
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun else {
483*4882a593Smuzhiyun ErrorF("X11.app: Unable to determine path to user's .Xmodmap");
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun //-----------------------------------------------------------------------------
489*4882a593Smuzhiyun // Modifier translation functions
490*4882a593Smuzhiyun //
491*4882a593Smuzhiyun // There are three different ways to specify a Mac modifier key:
492*4882a593Smuzhiyun // keycode - specifies hardware key, read from keymapping
493*4882a593Smuzhiyun // key - NX_MODIFIERKEY_*, really an index
494*4882a593Smuzhiyun // mask - NX_*MASK, mask for modifier flags in event record
495*4882a593Smuzhiyun // Left and right side have different keycodes but the same key and mask.
496*4882a593Smuzhiyun //-----------------------------------------------------------------------------
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /*
499*4882a593Smuzhiyun * DarwinModifierNXKeyToNXKeycode
500*4882a593Smuzhiyun * Return the keycode for an NX_MODIFIERKEY_* modifier.
501*4882a593Smuzhiyun * side = 0 for left or 1 for right.
502*4882a593Smuzhiyun * Returns 0 if key+side is not a known modifier.
503*4882a593Smuzhiyun */
504*4882a593Smuzhiyun int
DarwinModifierNXKeyToNXKeycode(int key,int side)505*4882a593Smuzhiyun DarwinModifierNXKeyToNXKeycode(int key, int side)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun int retval;
508*4882a593Smuzhiyun pthread_mutex_lock(&keyInfo_mutex);
509*4882a593Smuzhiyun retval = keyInfo.modifierKeycodes[key][side];
510*4882a593Smuzhiyun pthread_mutex_unlock(&keyInfo_mutex);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return retval;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /*
516*4882a593Smuzhiyun * DarwinModifierNXKeycodeToNXKey
517*4882a593Smuzhiyun * Returns -1 if keycode+side is not a modifier key
518*4882a593Smuzhiyun * outSide may be NULL, else it gets 0 for left and 1 for right.
519*4882a593Smuzhiyun */
520*4882a593Smuzhiyun int
DarwinModifierNXKeycodeToNXKey(unsigned char keycode,int * outSide)521*4882a593Smuzhiyun DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun int key, side;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun keycode += MIN_KEYCODE;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun // search modifierKeycodes for this keycode+side
528*4882a593Smuzhiyun pthread_mutex_lock(&keyInfo_mutex);
529*4882a593Smuzhiyun for (key = 0; key < NX_NUMMODIFIERS; key++) {
530*4882a593Smuzhiyun for (side = 0; side <= 1; side++) {
531*4882a593Smuzhiyun if (keyInfo.modifierKeycodes[key][side] == keycode) break;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun pthread_mutex_unlock(&keyInfo_mutex);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (key == NX_NUMMODIFIERS) {
537*4882a593Smuzhiyun return -1;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun if (outSide) *outSide = side;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun return key;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun /*
545*4882a593Smuzhiyun * DarwinModifierNXMaskToNXKey
546*4882a593Smuzhiyun * Returns -1 if mask is not a known modifier mask.
547*4882a593Smuzhiyun */
548*4882a593Smuzhiyun int
DarwinModifierNXMaskToNXKey(int mask)549*4882a593Smuzhiyun DarwinModifierNXMaskToNXKey(int mask)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun switch (mask) {
552*4882a593Smuzhiyun case NX_ALPHASHIFTMASK:
553*4882a593Smuzhiyun return NX_MODIFIERKEY_ALPHALOCK;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun case NX_SHIFTMASK:
556*4882a593Smuzhiyun return NX_MODIFIERKEY_SHIFT;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun #ifdef NX_DEVICELSHIFTKEYMASK
559*4882a593Smuzhiyun case NX_DEVICELSHIFTKEYMASK:
560*4882a593Smuzhiyun return NX_MODIFIERKEY_SHIFT;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun case NX_DEVICERSHIFTKEYMASK:
563*4882a593Smuzhiyun return NX_MODIFIERKEY_RSHIFT;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun #endif
566*4882a593Smuzhiyun case NX_CONTROLMASK:
567*4882a593Smuzhiyun return NX_MODIFIERKEY_CONTROL;
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun #ifdef NX_DEVICELCTLKEYMASK
570*4882a593Smuzhiyun case NX_DEVICELCTLKEYMASK:
571*4882a593Smuzhiyun return NX_MODIFIERKEY_CONTROL;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun case NX_DEVICERCTLKEYMASK:
574*4882a593Smuzhiyun return NX_MODIFIERKEY_RCONTROL;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun #endif
577*4882a593Smuzhiyun case NX_ALTERNATEMASK:
578*4882a593Smuzhiyun return NX_MODIFIERKEY_ALTERNATE;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun #ifdef NX_DEVICELALTKEYMASK
581*4882a593Smuzhiyun case NX_DEVICELALTKEYMASK:
582*4882a593Smuzhiyun return NX_MODIFIERKEY_ALTERNATE;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun case NX_DEVICERALTKEYMASK:
585*4882a593Smuzhiyun return NX_MODIFIERKEY_RALTERNATE;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun #endif
588*4882a593Smuzhiyun case NX_COMMANDMASK:
589*4882a593Smuzhiyun return NX_MODIFIERKEY_COMMAND;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun #ifdef NX_DEVICELCMDKEYMASK
592*4882a593Smuzhiyun case NX_DEVICELCMDKEYMASK:
593*4882a593Smuzhiyun return NX_MODIFIERKEY_COMMAND;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun case NX_DEVICERCMDKEYMASK:
596*4882a593Smuzhiyun return NX_MODIFIERKEY_RCOMMAND;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun #endif
599*4882a593Smuzhiyun case NX_NUMERICPADMASK:
600*4882a593Smuzhiyun return NX_MODIFIERKEY_NUMERICPAD;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun case NX_HELPMASK:
603*4882a593Smuzhiyun return NX_MODIFIERKEY_HELP;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun case NX_SECONDARYFNMASK:
606*4882a593Smuzhiyun return NX_MODIFIERKEY_SECONDARYFN;
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun return -1;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun /*
612*4882a593Smuzhiyun * DarwinModifierNXKeyToNXMask
613*4882a593Smuzhiyun * Returns 0 if key is not a known modifier key.
614*4882a593Smuzhiyun */
615*4882a593Smuzhiyun int
DarwinModifierNXKeyToNXMask(int key)616*4882a593Smuzhiyun DarwinModifierNXKeyToNXMask(int key)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun switch (key) {
619*4882a593Smuzhiyun case NX_MODIFIERKEY_ALPHALOCK:
620*4882a593Smuzhiyun return NX_ALPHASHIFTMASK;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun #ifdef NX_DEVICELSHIFTKEYMASK
623*4882a593Smuzhiyun case NX_MODIFIERKEY_SHIFT:
624*4882a593Smuzhiyun return NX_DEVICELSHIFTKEYMASK;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun case NX_MODIFIERKEY_RSHIFT:
627*4882a593Smuzhiyun return NX_DEVICERSHIFTKEYMASK;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun case NX_MODIFIERKEY_CONTROL:
630*4882a593Smuzhiyun return NX_DEVICELCTLKEYMASK;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun case NX_MODIFIERKEY_RCONTROL:
633*4882a593Smuzhiyun return NX_DEVICERCTLKEYMASK;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun case NX_MODIFIERKEY_ALTERNATE:
636*4882a593Smuzhiyun return NX_DEVICELALTKEYMASK;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun case NX_MODIFIERKEY_RALTERNATE:
639*4882a593Smuzhiyun return NX_DEVICERALTKEYMASK;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun case NX_MODIFIERKEY_COMMAND:
642*4882a593Smuzhiyun return NX_DEVICELCMDKEYMASK;
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun case NX_MODIFIERKEY_RCOMMAND:
645*4882a593Smuzhiyun return NX_DEVICERCMDKEYMASK;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun #else
648*4882a593Smuzhiyun case NX_MODIFIERKEY_SHIFT:
649*4882a593Smuzhiyun return NX_SHIFTMASK;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun case NX_MODIFIERKEY_CONTROL:
652*4882a593Smuzhiyun return NX_CONTROLMASK;
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun case NX_MODIFIERKEY_ALTERNATE:
655*4882a593Smuzhiyun return NX_ALTERNATEMASK;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun case NX_MODIFIERKEY_COMMAND:
658*4882a593Smuzhiyun return NX_COMMANDMASK;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun #endif
661*4882a593Smuzhiyun case NX_MODIFIERKEY_NUMERICPAD:
662*4882a593Smuzhiyun return NX_NUMERICPADMASK;
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun case NX_MODIFIERKEY_HELP:
665*4882a593Smuzhiyun return NX_HELPMASK;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun case NX_MODIFIERKEY_SECONDARYFN:
668*4882a593Smuzhiyun return NX_SECONDARYFNMASK;
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun return 0;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun /*
674*4882a593Smuzhiyun * DarwinModifierStringToNXMask
675*4882a593Smuzhiyun * Returns 0 if string is not a known modifier.
676*4882a593Smuzhiyun */
677*4882a593Smuzhiyun int
DarwinModifierStringToNXMask(const char * str,int separatelr)678*4882a593Smuzhiyun DarwinModifierStringToNXMask(const char *str, int separatelr)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun #ifdef NX_DEVICELSHIFTKEYMASK
681*4882a593Smuzhiyun if (separatelr) {
682*4882a593Smuzhiyun if (!strcasecmp(str,
683*4882a593Smuzhiyun "shift")) return NX_DEVICELSHIFTKEYMASK |
684*4882a593Smuzhiyun NX_DEVICERSHIFTKEYMASK;
685*4882a593Smuzhiyun if (!strcasecmp(str,
686*4882a593Smuzhiyun "control")) return NX_DEVICELCTLKEYMASK |
687*4882a593Smuzhiyun NX_DEVICERCTLKEYMASK;
688*4882a593Smuzhiyun if (!strcasecmp(str,
689*4882a593Smuzhiyun "option")) return NX_DEVICELALTKEYMASK |
690*4882a593Smuzhiyun NX_DEVICERALTKEYMASK;
691*4882a593Smuzhiyun if (!strcasecmp(str,
692*4882a593Smuzhiyun "alt")) return NX_DEVICELALTKEYMASK |
693*4882a593Smuzhiyun NX_DEVICERALTKEYMASK;
694*4882a593Smuzhiyun if (!strcasecmp(str,
695*4882a593Smuzhiyun "command")) return NX_DEVICELCMDKEYMASK |
696*4882a593Smuzhiyun NX_DEVICERCMDKEYMASK;
697*4882a593Smuzhiyun if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK;
698*4882a593Smuzhiyun if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK;
699*4882a593Smuzhiyun if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK;
700*4882a593Smuzhiyun if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK;
701*4882a593Smuzhiyun if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK;
702*4882a593Smuzhiyun if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK;
703*4882a593Smuzhiyun if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK;
704*4882a593Smuzhiyun if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK;
705*4882a593Smuzhiyun if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK;
706*4882a593Smuzhiyun if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun else {
709*4882a593Smuzhiyun #endif
710*4882a593Smuzhiyun if (!strcasecmp(str, "shift")) return NX_SHIFTMASK;
711*4882a593Smuzhiyun if (!strcasecmp(str, "control")) return NX_CONTROLMASK;
712*4882a593Smuzhiyun if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK;
713*4882a593Smuzhiyun if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK;
714*4882a593Smuzhiyun if (!strcasecmp(str, "command")) return NX_COMMANDMASK;
715*4882a593Smuzhiyun if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK;
716*4882a593Smuzhiyun if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK;
717*4882a593Smuzhiyun if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK;
718*4882a593Smuzhiyun if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK;
719*4882a593Smuzhiyun if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK;
720*4882a593Smuzhiyun if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK;
721*4882a593Smuzhiyun if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK;
722*4882a593Smuzhiyun if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK;
723*4882a593Smuzhiyun if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK;
724*4882a593Smuzhiyun if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK;
725*4882a593Smuzhiyun #ifdef NX_DEVICELSHIFTKEYMASK
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun #endif
728*4882a593Smuzhiyun if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK;
729*4882a593Smuzhiyun if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK;
730*4882a593Smuzhiyun if (!strcasecmp(str, "help")) return NX_HELPMASK;
731*4882a593Smuzhiyun if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK;
732*4882a593Smuzhiyun return 0;
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun /*
736*4882a593Smuzhiyun * LegalModifier
737*4882a593Smuzhiyun * This allows the ddx layer to prevent some keys from being remapped
738*4882a593Smuzhiyun * as modifier keys.
739*4882a593Smuzhiyun */
740*4882a593Smuzhiyun Bool
LegalModifier(unsigned int key,DeviceIntPtr pDev)741*4882a593Smuzhiyun LegalModifier(unsigned int key, DeviceIntPtr pDev)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun return 1;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun static KeySym
make_dead_key(KeySym in)747*4882a593Smuzhiyun make_dead_key(KeySym in)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun int i;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(dead_keys); i++)
752*4882a593Smuzhiyun if (dead_keys[i].normal == in) return dead_keys[i].dead;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun return in;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun static Bool
QuartzReadSystemKeymap(darwinKeyboardInfo * info)758*4882a593Smuzhiyun QuartzReadSystemKeymap(darwinKeyboardInfo *info)
759*4882a593Smuzhiyun {
760*4882a593Smuzhiyun __block const void *chr_data = NULL;
761*4882a593Smuzhiyun int num_keycodes = NUM_KEYCODES;
762*4882a593Smuzhiyun __block UInt32 keyboard_type;
763*4882a593Smuzhiyun int i, j;
764*4882a593Smuzhiyun OSStatus err;
765*4882a593Smuzhiyun KeySym *k;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun dispatch_block_t getKeyboardData = ^{
768*4882a593Smuzhiyun keyboard_type = LMGetKbdType();
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource();
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun if (currentKeyLayoutRef) {
773*4882a593Smuzhiyun CFDataRef currentKeyLayoutDataRef = (CFDataRef)TISGetInputSourceProperty(currentKeyLayoutRef,
774*4882a593Smuzhiyun kTISPropertyUnicodeKeyLayoutData);
775*4882a593Smuzhiyun if (currentKeyLayoutDataRef)
776*4882a593Smuzhiyun chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef);
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun CFRelease(currentKeyLayoutRef);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun };
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun /* This is an ugly ant-pattern, but it is more expedient to address the problem right now. */
783*4882a593Smuzhiyun if (pthread_main_np()) {
784*4882a593Smuzhiyun getKeyboardData();
785*4882a593Smuzhiyun } else {
786*4882a593Smuzhiyun dispatch_sync(dispatch_get_main_queue(), getKeyboardData);
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun if (chr_data == NULL) {
790*4882a593Smuzhiyun ErrorF("Couldn't get uchr or kchr resource\n");
791*4882a593Smuzhiyun return FALSE;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun /* Scan the keycode range for the Unicode character that each
795*4882a593Smuzhiyun key produces in the four shift states. Then convert that to
796*4882a593Smuzhiyun an X11 keysym (which may just the bit that says "this is
797*4882a593Smuzhiyun Unicode" if it can't find the real symbol.) */
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate
800*4882a593Smuzhiyun must be used instead. */
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun for (i = 0; i < num_keycodes; i++) {
803*4882a593Smuzhiyun static const int mods[4] = {
804*4882a593Smuzhiyun 0, MOD_SHIFT, MOD_OPTION,
805*4882a593Smuzhiyun MOD_OPTION | MOD_SHIFT
806*4882a593Smuzhiyun };
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun k = info->keyMap + i * GLYPHS_PER_KEY;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun for (j = 0; j < 4; j++) {
811*4882a593Smuzhiyun UniChar s[8];
812*4882a593Smuzhiyun UniCharCount len;
813*4882a593Smuzhiyun UInt32 dead_key_state = 0, extra_dead = 0;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun err = UCKeyTranslate(chr_data, i, kUCKeyActionDown,
816*4882a593Smuzhiyun mods[j] >> 8, keyboard_type, 0,
817*4882a593Smuzhiyun &dead_key_state, 8, &len, s);
818*4882a593Smuzhiyun if (err != noErr) continue;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if (len == 0 && dead_key_state != 0) {
821*4882a593Smuzhiyun /* Found a dead key. Work out which one it is, but
822*4882a593Smuzhiyun remembering that it's dead. */
823*4882a593Smuzhiyun err = UCKeyTranslate(chr_data, i, kUCKeyActionDown,
824*4882a593Smuzhiyun mods[j] >> 8, keyboard_type,
825*4882a593Smuzhiyun kUCKeyTranslateNoDeadKeysMask,
826*4882a593Smuzhiyun &extra_dead, 8, &len, s);
827*4882a593Smuzhiyun if (err != noErr) continue;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun /* Not sure why 0x0010 is there.
831*4882a593Smuzhiyun * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ...
832*4882a593Smuzhiyun */
833*4882a593Smuzhiyun if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) {
834*4882a593Smuzhiyun k[j] = ucs2keysym(s[0]);
835*4882a593Smuzhiyun if (dead_key_state != 0) k[j] = make_dead_key(k[j]);
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun if (k[3] == k[2]) k[3] = NoSymbol;
840*4882a593Smuzhiyun if (k[1] == k[0]) k[1] = NoSymbol;
841*4882a593Smuzhiyun if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
842*4882a593Smuzhiyun if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun #if HACK_MISSING
846*4882a593Smuzhiyun /* Fix up some things that are normally missing.. */
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(known_keys); i++) {
849*4882a593Smuzhiyun k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY;
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (k[0] == NoSymbol && k[1] == NoSymbol
852*4882a593Smuzhiyun && k[2] == NoSymbol && k[3] == NoSymbol)
853*4882a593Smuzhiyun k[0] = known_keys[i].keysym;
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun #endif
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun #if HACK_KEYPAD
858*4882a593Smuzhiyun /* And some more things. We find the right symbols for the numeric
859*4882a593Smuzhiyun keypad, but not the KP_ keysyms. So try to convert known keycodes. */
860*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(known_numeric_keys); i++) {
861*4882a593Smuzhiyun k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
862*4882a593Smuzhiyun
863*4882a593Smuzhiyun if (k[0] == known_numeric_keys[i].normal)
864*4882a593Smuzhiyun k[0] = known_numeric_keys[i].keypad;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun #endif
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun #if HACK_BLACKLIST
869*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(keycode_blacklist); i++) {
870*4882a593Smuzhiyun k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY;
871*4882a593Smuzhiyun k[0] = k[1] = k[2] = k[3] = NoSymbol;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun #endif
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun DarwinBuildModifierMaps(info);
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun return TRUE;
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun Bool
QuartsResyncKeymap(Bool sendDDXEvent)881*4882a593Smuzhiyun QuartsResyncKeymap(Bool sendDDXEvent)
882*4882a593Smuzhiyun {
883*4882a593Smuzhiyun Bool retval;
884*4882a593Smuzhiyun /* Update keyInfo */
885*4882a593Smuzhiyun pthread_mutex_lock(&keyInfo_mutex);
886*4882a593Smuzhiyun memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
887*4882a593Smuzhiyun retval = QuartzReadSystemKeymap(&keyInfo);
888*4882a593Smuzhiyun pthread_mutex_unlock(&keyInfo_mutex);
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun /* Tell server thread to deal with new keyInfo */
891*4882a593Smuzhiyun if (sendDDXEvent)
892*4882a593Smuzhiyun DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun return retval;
895*4882a593Smuzhiyun }
896