1 /*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2016 Symless Ltd.
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file LICENSE that should have accompanied this file.
8 *
9 * This package is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "platform/IOSXKeyResource.h"
19
20 #include <Carbon/Carbon.h>
21
22 KeyID
getKeyID(UInt8 c)23 IOSXKeyResource::getKeyID(UInt8 c)
24 {
25 if (c == 0) {
26 return kKeyNone;
27 }
28 else if (c >= 32 && c < 127) {
29 // ASCII
30 return static_cast<KeyID>(c);
31 }
32 else {
33 // handle special keys
34 switch (c) {
35 case 0x01:
36 return kKeyHome;
37
38 case 0x02:
39 return kKeyKP_Enter;
40
41 case 0x03:
42 return kKeyKP_Enter;
43
44 case 0x04:
45 return kKeyEnd;
46
47 case 0x05:
48 return kKeyHelp;
49
50 case 0x08:
51 return kKeyBackSpace;
52
53 case 0x09:
54 return kKeyTab;
55
56 case 0x0b:
57 return kKeyPageUp;
58
59 case 0x0c:
60 return kKeyPageDown;
61
62 case 0x0d:
63 return kKeyReturn;
64
65 case 0x10:
66 // OS X maps all the function keys (F1, etc) to this one key.
67 // we can't determine the right key here so we have to do it
68 // some other way.
69 return kKeyNone;
70
71 case 0x1b:
72 return kKeyEscape;
73
74 case 0x1c:
75 return kKeyLeft;
76
77 case 0x1d:
78 return kKeyRight;
79
80 case 0x1e:
81 return kKeyUp;
82
83 case 0x1f:
84 return kKeyDown;
85
86 case 0x7f:
87 return kKeyDelete;
88
89 case 0x06:
90 case 0x07:
91 case 0x0a:
92 case 0x0e:
93 case 0x0f:
94 case 0x11:
95 case 0x12:
96 case 0x13:
97 case 0x14:
98 case 0x15:
99 case 0x16:
100 case 0x17:
101 case 0x18:
102 case 0x19:
103 case 0x1a:
104 // discard other control characters
105 return kKeyNone;
106
107 default:
108 // not special or unknown
109 break;
110 }
111
112 // create string with character
113 char str[2];
114 str[0] = static_cast<char>(c);
115 str[1] = 0;
116
117 // get current keyboard script
118 TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource();
119 CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages);
120 CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding(
121 (CFStringRef)CFArrayGetValueAtIndex(langs, 0));
122 // convert to unicode
123 CFStringRef cfString =
124 CFStringCreateWithCStringNoCopy(
125 kCFAllocatorDefault, str, encoding, kCFAllocatorNull);
126
127 // sometimes CFStringCreate...() returns NULL (e.g. Apple Korean
128 // encoding with char value 214). if it did then make no key,
129 // otherwise CFStringCreateMutableCopy() will crash.
130 if (cfString == NULL) {
131 return kKeyNone;
132 }
133
134 // convert to precomposed
135 CFMutableStringRef mcfString =
136 CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfString);
137 CFRelease(cfString);
138 CFStringNormalize(mcfString, kCFStringNormalizationFormC);
139
140 // check result
141 int unicodeLength = CFStringGetLength(mcfString);
142 if (unicodeLength == 0) {
143 CFRelease(mcfString);
144 return kKeyNone;
145 }
146 if (unicodeLength > 1) {
147 // FIXME -- more than one character, we should handle this
148 CFRelease(mcfString);
149 return kKeyNone;
150 }
151
152 // get unicode character
153 UniChar uc = CFStringGetCharacterAtIndex(mcfString, 0);
154 CFRelease(mcfString);
155
156 // convert to KeyID
157 return static_cast<KeyID>(uc);
158 }
159 }
160
161 KeyID
unicharToKeyID(UniChar c)162 IOSXKeyResource::unicharToKeyID(UniChar c)
163 {
164 switch (c) {
165 case 3:
166 return kKeyKP_Enter;
167
168 case 8:
169 return kKeyBackSpace;
170
171 case 9:
172 return kKeyTab;
173
174 case 13:
175 return kKeyReturn;
176
177 case 27:
178 return kKeyEscape;
179
180 case 127:
181 return kKeyDelete;
182
183 default:
184 if (c < 32) {
185 return kKeyNone;
186 }
187 return static_cast<KeyID>(c);
188 }
189 }
190