OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <AppKit/NSEvent.h> | 5 #include <AppKit/NSEvent.h> |
6 #include <Carbon/Carbon.h> | 6 #include <Carbon/Carbon.h> |
7 | 7 |
8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" | 8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, | 166 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, |
167 command_key, shift_key, | 167 command_key, shift_key, |
168 cntrl_key, opt_key, vkey_code, | 168 cntrl_key, opt_key, vkey_code, |
169 key_char); | 169 key_char); |
170 } | 170 } |
171 | 171 |
172 unichar KeyCharacterForEvent(NSEvent* event) { | 172 unichar KeyCharacterForEvent(NSEvent* event) { |
173 NSString* eventString = [event charactersIgnoringModifiers]; | 173 NSString* eventString = [event charactersIgnoringModifiers]; |
174 NSString* characters = [event characters]; | 174 NSString* characters = [event characters]; |
175 | 175 |
176 // Character pairs that undergo BiDi mirrored. | |
177 // There are actually many more such pairs, but these are the ones that | |
178 // are likely to show up in keyboard shortcuts. | |
179 const struct { | |
180 unichar a; | |
181 unichar b; | |
182 } kMirroredBiDiChars[] = { | |
183 {'{', '}'}, | |
184 {'[', ']'}, | |
185 {'(', ')'}, | |
186 }; | |
187 | |
188 if ([eventString length] != 1) | 176 if ([eventString length] != 1) |
189 return 0; | 177 return 0; |
190 | 178 |
191 if ([characters length] != 1) | 179 if ([characters length] != 1) |
192 return [eventString characterAtIndex:0]; | 180 return [eventString characterAtIndex:0]; |
193 | 181 |
| 182 // Some characters are BiDi mirrored. The mirroring is different |
| 183 // for different OS versions. Instead of having a mirror table, map |
| 184 // raw/processed pairs to desired outputs. |
| 185 const struct { |
| 186 unichar rawChar; |
| 187 unichar unmodChar; |
| 188 unichar targetChar; |
| 189 } kCharMapping[] = { |
| 190 // OSX 10.8 mirrors certain chars. |
| 191 {'{', '}', '{'}, |
| 192 {'}', '{', '}'}, |
| 193 {'(', ')', '('}, |
| 194 {')', '(', ')'}, |
| 195 |
| 196 // OSX 10.9 has the unshifted raw char. |
| 197 {'[', '}', '{'}, |
| 198 {']', '{', '}'}, |
| 199 {'9', ')', '('}, |
| 200 {'0', '(', ')'}, |
| 201 |
| 202 // These are the same either way. |
| 203 {'[', ']', '['}, |
| 204 {']', '[', ']'}, |
| 205 }; |
| 206 |
194 unichar noModifiersChar = [eventString characterAtIndex:0]; | 207 unichar noModifiersChar = [eventString characterAtIndex:0]; |
195 unichar rawChar = [characters characterAtIndex:0]; | 208 unichar rawChar = [characters characterAtIndex:0]; |
196 // When both |characters| and |charactersIgnoringModifiers| are ascii, | 209 |
197 // return the first character of |characters|, if... | 210 // Only apply transformation table for ascii. |
198 if (isascii(noModifiersChar) && isascii(rawChar)) { | 211 if (isascii(noModifiersChar) && isascii(rawChar)) { |
199 // |characters| is an alphabet (mainly for dvorak-qwerty layout), or | 212 // Alphabetic characters aren't mirrored, go with the raw character. |
| 213 // [A previous partial comment said something about Dvorak?] |
200 if (isalpha(rawChar)) | 214 if (isalpha(rawChar)) |
201 return rawChar; | 215 return rawChar; |
202 | 216 |
203 // http://crbug.com/42517 | 217 // http://crbug.com/42517 |
| 218 // http://crbug.com/315379 |
204 // In RTL keyboard layouts, Cocoa mirrors characters in the string | 219 // In RTL keyboard layouts, Cocoa mirrors characters in the string |
205 // returned by [event charactersIgnoringModifiers]. In this case, return | 220 // returned by [event charactersIgnoringModifiers]. In this case, return |
206 // the raw (unmirrored) char. | 221 // the raw (unmirrored) char. |
207 // FIXME: If there is a need to add any more characters to the | 222 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCharMapping); ++i) { |
208 // kMirroredBiDiChars table, then it's probably better to use ICU's | 223 if (rawChar == kCharMapping[i].rawChar && |
209 // u_charMirror() function to perform this test. | 224 noModifiersChar == kCharMapping[i].unmodChar) { |
210 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kMirroredBiDiChars); ++i) { | 225 return kCharMapping[i].targetChar; |
211 const unichar& a = kMirroredBiDiChars[i].a; | 226 } |
212 const unichar& b = kMirroredBiDiChars[i].b; | |
213 if ((rawChar == a && noModifiersChar == b) || | |
214 (rawChar == b && noModifiersChar == a)) | |
215 return rawChar; | |
216 } | 227 } |
217 | 228 |
218 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). | 229 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). |
219 if ([event modifierFlags] & NSAlternateKeyMask) | 230 if ([event modifierFlags] & NSAlternateKeyMask) |
220 return [characters characterAtIndex:0]; | 231 return rawChar; |
221 } | 232 } |
222 | 233 |
223 return [eventString characterAtIndex:0]; | 234 return noModifiersChar; |
224 } | 235 } |
OLD | NEW |