xref: /OK3568_Linux_fs/external/xserver/hw/xquartz/quartzKeyboard.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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