FreeRDP
keyboard_apple.c
1 
21 #include <freerdp/config.h>
22 
23 #include <Carbon/Carbon.h>
24 #include <string.h>
25 
26 #include "liblocale.h"
27 
28 #include <freerdp/locale/locale.h>
29 #include <freerdp/locale/keyboard.h>
30 
31 #include "keyboard_apple.h"
32 
33 struct KEYBOARD_LAYOUT_MAPPING_
34 {
35  const char* inputSourceId; /* Apple input source id (com.apple.keylayout or inputmethod) */
36  DWORD code; /* mapped rdp keyboard layout id */
37 };
38 typedef struct KEYBOARD_LAYOUT_MAPPING_ KEYBOARD_LAYOUT_MAPPING;
39 
40 static const KEYBOARD_LAYOUT_MAPPING KEYBOARD_MAPPING_TABLE[] = {
41  { "com.apple.inputmethod.Kotoeri.Japanese", JAPANESE },
42  { "com.apple.inputmethod.Kotoeri.Japanese.FullWidthRoman", JAPANESE },
43  { "com.apple.inputmethod.Kotoeri.Japanese.HalfWidthKana", JAPANESE },
44  { "com.apple.inputmethod.Kotoeri.Japanese.Katakana", JAPANESE },
45  { "com.apple.inputmethod.Kotoeri.Katakana", JAPANESE },
46  { "com.apple.inputmethod.Kotoeri.Roman", JAPANESE },
47  { "com.apple.inputmethod.kotoeri.Ainu", JAPANESE },
48  { "com.apple.keylayout.2SetHangul", KOREAN },
49  { "com.apple.keylayout.390Hangul", KOREAN },
50  { "com.apple.keylayout.3SetHangul", KOREAN },
51  { "com.apple.keylayout.AfghanDari", KBD_PERSIAN },
52  { "com.apple.keylayout.AfghanPashto", PASHTO },
53  { "com.apple.keylayout.AfghanUzbek", UZBEK_LATIN },
54  { "com.apple.keylayout.Arabic", ARABIC_SAUDI_ARABIA },
55  { "com.apple.keylayout.Arabic-QWERTY", ARABIC_EGYPT },
56  { "com.apple.keylayout.ArabicPC", ARABIC_EGYPT },
57  { "com.apple.keylayout.Armenian-HMQWERTY", ARMENIAN },
58  { "com.apple.keylayout.Armenian-WesternQWERTY", ARMENIAN },
59  { "com.apple.keylayout.Australian", ENGLISH_AUSTRALIAN },
60  { "com.apple.keylayout.Austrian", GERMAN_STANDARD },
61  { "com.apple.keylayout.Azeri", AZERI_LATIN },
62  { "com.apple.keylayout.Bangla", KBD_BANGLA },
63  { "com.apple.keylayout.Bangla-QWERTY", KBD_BANGLA },
64  { "com.apple.keylayout.Belgian", DUTCH_BELGIAN },
65  { "com.apple.keylayout.Brazilian", PORTUGUESE_BRAZILIAN },
66  { "com.apple.keylayout.British", ENGLISH_UNITED_KINGDOM },
67  { "com.apple.keylayout.British-PC", ENGLISH_UNITED_KINGDOM },
68  { "com.apple.keylayout.Bulgarian", BULGARIAN },
69  { "com.apple.keylayout.Bulgarian-Phonetic", KBD_BULGARIAN_PHONETIC },
70  { "com.apple.keylayout.Byelorussian", BELARUSIAN },
71  { "com.apple.keylayout.Canadian", ENGLISH_UNITED_STATES },
72  { "com.apple.keylayout.Canadian-CSA", KBD_CANADIAN_MULTILINGUAL_STANDARD },
73  { "com.apple.keylayout.CangjieKeyboard", CHINESE_TAIWAN },
74  { "com.apple.keylayout.Cherokee-Nation", CHEROKEE },
75  { "com.apple.keylayout.Cherokee-QWERTY", ENGLISH_UNITED_STATES },
76  { "com.apple.keylayout.Colemak", ENGLISH_UNITED_STATES },
77  { "com.apple.keylayout.Croatian", CROATIAN },
78  { "com.apple.keylayout.Croatian-PC", CROATIAN },
79  { "com.apple.keylayout.Czech", CZECH },
80  { "com.apple.keylayout.Czech-QWERTY", KBD_CZECH_QWERTY },
81  { "com.apple.keylayout.DVORAK-QWERTYCMD", KBD_UNITED_STATES_DVORAK },
82  { "com.apple.keylayout.Danish", DANISH },
83  { "com.apple.keylayout.Devanagari", HINDI },
84  { "com.apple.keylayout.Devanagari-QWERTY", HINDI },
85  { "com.apple.keylayout.Dutch", KBD_UNITED_STATES_INTERNATIONAL },
86  { "com.apple.keylayout.Dvorak", KBD_UNITED_STATES_DVORAK },
87  { "com.apple.keylayout.Dvorak-Left", KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND },
88  { "com.apple.keylayout.Dvorak-Right", KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND },
89  { "com.apple.keylayout.Estonian", ESTONIAN },
90  { "com.apple.keylayout.Faroese", FAEROESE },
91  { "com.apple.keylayout.Finnish", FINNISH },
92  { "com.apple.keylayout.FinnishExtended", KBD_SAMI_EXTENDED_FINLAND_SWEDEN },
93  { "com.apple.keylayout.FinnishSami-PC", KBD_FINNISH_WITH_SAMI },
94  { "com.apple.keylayout.French", KBD_BELGIAN_FRENCH },
95  { "com.apple.keylayout.French-PC", FRENCH_STANDARD },
96  { "com.apple.keylayout.French-numerical", KBD_BELGIAN_FRENCH },
97  { "com.apple.keylayout.GJCRomaja", ENGLISH_UNITED_STATES },
98  { "com.apple.keylayout.Georgian-QWERTY", KBD_GEORGIAN_QUERTY },
99  { "com.apple.keylayout.German", GERMAN_STANDARD },
100  { "com.apple.keylayout.Greek", GREEK },
101  { "com.apple.keylayout.GreekPolytonic", KBD_GREEK_POLYTONIC },
102  { "com.apple.keylayout.Gujarati", GUJARATI },
103  { "com.apple.keylayout.Gujarati-QWERTY", GUJARATI },
104  { "com.apple.keylayout.Gurmukhi", PUNJABI },
105  { "com.apple.keylayout.Gurmukhi-QWERTY", PUNJABI },
106  { "com.apple.keylayout.HNCRomaja", ENGLISH_UNITED_STATES },
107  { "com.apple.keylayout.Hawaiian", HAWAIIAN },
108  { "com.apple.keylayout.Hebrew", HEBREW },
109  { "com.apple.keylayout.Hebrew-PC", HEBREW },
110  { "com.apple.keylayout.Hebrew-QWERTY", HEBREW },
111  { "com.apple.keylayout.Hungarian", HUNGARIAN },
112  { "com.apple.keylayout.Hungarian-QWERTY", HUNGARIAN },
113  { "com.apple.keylayout.Icelandic", ICELANDIC },
114  { "com.apple.keylayout.Inuktitut-Nunavut", INUKTITUT },
115  { "com.apple.keylayout.Inuktitut-Nutaaq", INUKTITUT },
116  { "com.apple.keylayout.Inuktitut-QWERTY", INUKTITUT },
117  { "com.apple.keylayout.InuttitutNunavik", INUKTITUT },
118  { "com.apple.keylayout.Irish", ENGLISH_IRELAND },
119  { "com.apple.keylayout.IrishExtended", KBD_IRISH },
120  { "com.apple.keylayout.Italian", ITALIAN_STANDARD },
121  { "com.apple.keylayout.Italian-Pro", ITALIAN_STANDARD },
122  { "com.apple.keylayout.Jawi-QWERTY", ARABIC_SAUDI_ARABIA },
123  { "com.apple.keylayout.Kannada", KANNADA },
124  { "com.apple.keylayout.Kannada-QWERTY", KANNADA },
125  { "com.apple.keylayout.Kazakh", KAZAKH },
126  { "com.apple.keylayout.Khmer", KBD_KHMER },
127  { "com.apple.keylayout.Latvian", LATVIAN },
128  { "com.apple.keylayout.Lithuanian", LITHUANIAN },
129  { "com.apple.keylayout.Macedonian", MACEDONIAN },
130  { "com.apple.keylayout.Malayalam", MALAYALAM },
131  { "com.apple.keylayout.Malayalam-QWERTY", MALAYALAM },
132  { "com.apple.keylayout.Maltese", MALTESE },
133  { "com.apple.keylayout.Maori", MAORI },
134  { "com.apple.keylayout.Myanmar-QWERTY", MYANMAR },
135  { "com.apple.keylayout.Nepali", NEPALI },
136  { "com.apple.keylayout.NorthernSami", SAMI_NORTHERN_NORWAY },
137  { "com.apple.keylayout.Norwegian", NORWEGIAN_BOKMAL },
138  { "com.apple.keylayout.NorwegianExtended", NORWEGIAN_BOKMAL },
139  { "com.apple.keylayout.NorwegianSami-PC", NORWEGIAN_BOKMAL },
140  { "com.apple.keylayout.Oriya", ORIYA },
141  { "com.apple.keylayout.Persian", KBD_PERSIAN },
142  { "com.apple.keylayout.Persian-ISIRI2901", KBD_PERSIAN },
143  { "com.apple.keylayout.Polish", KBD_POLISH_214 },
144  { "com.apple.keylayout.PolishPro", KBD_POLISH_PROGRAMMERS },
145  { "com.apple.keylayout.Portuguese", PORTUGUESE_STANDARD },
146  { "com.apple.keylayout.Romanian", KBD_ROMANIAN },
147  { "com.apple.keylayout.Romanian-Standard", KBD_ROMANIAN_STANDARD },
148  { "com.apple.keylayout.Russian", RUSSIAN },
149  { "com.apple.keylayout.Russian-Phonetic", KBD_RUSSIAN_PHONETIC },
150  { "com.apple.keylayout.RussianWin", RUSSIAN },
151  { "com.apple.keylayout.Sami-PC", KBD_SAMI_EXTENDED_FINLAND_SWEDEN },
152  { "com.apple.keylayout.Serbian", KBD_SERBIAN_CYRILLIC },
153  { "com.apple.keylayout.Serbian-Latin", KBD_SERBIAN_LATIN },
154  { "com.apple.keylayout.Sinhala", SINHALA },
155  { "com.apple.keylayout.Sinhala-QWERTY", SINHALA },
156  { "com.apple.keylayout.Slovak", SLOVAK },
157  { "com.apple.keylayout.Slovak-QWERTY", KBD_SLOVAK_QWERTY },
158  { "com.apple.keylayout.Slovenian", SLOVENIAN },
159  { "com.apple.keylayout.Spanish", SPANISH_TRADITIONAL_SORT },
160  { "com.apple.keylayout.Spanish-ISO", KBD_SPANISH },
161  { "com.apple.keylayout.Swedish", SWEDISH },
162  { "com.apple.keylayout.Swedish-Pro", SWEDISH },
163  { "com.apple.keylayout.SwedishSami-PC", SWEDISH },
164  { "com.apple.keylayout.SwissFrench", FRENCH_SWISS },
165  { "com.apple.keylayout.SwissGerman", GERMAN_SWISS },
166  { "com.apple.keylayout.Telugu", TELUGU },
167  { "com.apple.keylayout.Telugu-QWERTY", TELUGU },
168  { "com.apple.keylayout.Thai", THAI },
169  { "com.apple.keylayout.Thai-PattaChote", KBD_THAI_PATTACHOTE },
170  { "com.apple.keylayout.Tibetan-QWERTY", TIBETAN_PRC },
171  { "com.apple.keylayout.Tibetan-Wylie", TIBETAN_PRC },
172  { "com.apple.keylayout.TibetanOtaniUS", TIBETAN_PRC },
173  { "com.apple.keylayout.Turkish", KBD_TURKISH_F },
174  { "com.apple.keylayout.Turkish-QWERTY", TURKISH },
175  { "com.apple.keylayout.Turkish-QWERTY-PC", TURKISH },
176  { "com.apple.keylayout.US", ENGLISH_UNITED_STATES },
177  { "com.apple.keylayout.USExtended", ENGLISH_UNITED_STATES },
178  { "com.apple.keylayout.USInternational-PC", ENGLISH_UNITED_STATES },
179  { "com.apple.keylayout.Ukrainian", UKRAINIAN },
180  { "com.apple.keylayout.Ukrainian-PC", UKRAINIAN },
181  { "com.apple.keylayout.UnicodeHexInput", ENGLISH_UNITED_STATES },
182  { "com.apple.keylayout.Urdu", URDU },
183  { "com.apple.keylayout.Uyghur", UIGHUR },
184  { "com.apple.keylayout.Vietnamese", VIETNAMESE },
185  { "com.apple.keylayout.Welsh", WELSH }
186 };
187 
188 int freerdp_detect_keyboard_layout_from_cf(DWORD* keyboardLayoutId)
189 {
190  CFIndex length;
191  char* inputSourceId = NULL;
192  CFStringRef inputSourceIdRef;
193  TISInputSourceRef inputSrc = TISCopyCurrentKeyboardLayoutInputSource();
194  if (!inputSrc)
195  {
196  DEBUG_KBD("Failed to get current keyboard layout input source!");
197  return 0;
198  }
199 
200  /* get current input source id */
201  inputSourceIdRef = (CFStringRef)TISGetInputSourceProperty(inputSrc, kTISPropertyInputSourceID);
202  if (!inputSourceIdRef)
203  {
204  DEBUG_KBD("Failed to get input source id!");
205  goto done;
206  }
207 
208  /* convert it to a C-string */
209  length = CFStringGetLength(inputSourceIdRef);
210  length = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
211  inputSourceId = (char*)malloc(length);
212  if (!inputSourceId)
213  {
214  DEBUG_KBD("Failed to allocate string buffer!");
215  goto done;
216  }
217 
218  if (!CFStringGetCString(inputSourceIdRef, inputSourceId, length, kCFStringEncodingUTF8))
219  {
220  DEBUG_KBD("Failed to convert CFString to C-string!");
221  goto done;
222  }
223 
224  /* Search for the id in the mapping table */
225  for (size_t i = 0; i < ARRAYSIZE(KEYBOARD_MAPPING_TABLE); ++i)
226  {
227  if (strcmp(inputSourceId, KEYBOARD_MAPPING_TABLE[i].inputSourceId) == 0)
228  {
229  *keyboardLayoutId = KEYBOARD_MAPPING_TABLE[i].code;
230  break;
231  }
232  }
233 
234 done:
235  free(inputSourceId);
236  CFRelease(inputSrc);
237  if (*keyboardLayoutId > 0)
238  return *keyboardLayoutId;
239 
240  return 0;
241 }