#ifdef NS_IMPL_COCOA
#include "macfont.h"
+#include <Carbon/Carbon.h>
#endif
static EmacsMenu *dockMenu;
return value;
}
+#ifdef NS_IMPL_COCOA
+static UniChar
+ns_get_shifted_character (NSEvent *event)
+/* Look up the character corresponding to the key pressed on the
+ current keyboard layout and the currently configured shift-like
+ modifiers. This ignores the control-like modifiers that cause
+ [event characters] to give us the wrong result.
+
+ Although UCKeyTranslate doesn't require the Carbon framework, some
+ of the surrounding paraphernalia does, so this function makes
+ Carbon a requirement. */
+{
+ static UInt32 dead_key_state;
+
+ /* UCKeyTranslate may return up to 255 characters. If the buffer
+ isn't large enough then it produces an error. What kind of
+ keyboard inputs 255 characters in a single keypress? */
+ UniChar buf[255];
+ UniCharCount max_string_length = 255;
+ UniCharCount actual_string_length = 0;
+ OSStatus result;
+
+ CFDataRef layout_ref = (CFDataRef) TISGetInputSourceProperty
+ (TISCopyCurrentKeyboardLayoutInputSource (), kTISPropertyUnicodeKeyLayoutData);
+ UCKeyboardLayout* layout = (UCKeyboardLayout*) CFDataGetBytePtr (layout_ref);
+
+ UInt32 flags = [event modifierFlags];
+ UInt32 modifiers = (flags & NSEventModifierFlagShift) ? shiftKey : 0;
+
+ NSTRACE ("ns_get_shifted_character");
+
+ if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask
+ && (EQ (ns_right_alternate_modifier, Qnone)
+ || (EQ (ns_right_alternate_modifier, Qleft)
+ && EQ (ns_alternate_modifier, Qnone))))
+ modifiers |= rightOptionKey;
+
+ if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
+ && EQ (ns_alternate_modifier, Qnone))
+ modifiers |= optionKey;
+
+ if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask
+ && (EQ (ns_right_command_modifier, Qnone)
+ || (EQ (ns_right_command_modifier, Qleft)
+ && EQ (ns_command_modifier, Qnone))))
+ /* Carbon doesn't differentiate between left and right command
+ keys. */
+ modifiers |= cmdKey;
+
+ if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
+ && EQ (ns_command_modifier, Qnone))
+ modifiers |= cmdKey;
+
+ result = UCKeyTranslate (layout, [event keyCode], kUCKeyActionDown,
+ (modifiers >> 8) & 0xFF, LMGetKbdType (),
+ kUCKeyTranslateNoDeadKeysBit, &dead_key_state,
+ max_string_length, &actual_string_length, buf);
+
+ if (result != 0)
+ {
+ NSLog(@"Failed to translate character '%@' with modifiers %x",
+ [event characters], modifiers);
+ return 0;
+ }
+
+ /* FIXME: What do we do if more than one code unit is returned? */
+ if (actual_string_length > 0)
+ return buf[0];
+ return 0;
+}
+#endif /* NS_IMPL_COCOA */
/* ==========================================================================
code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
- /* (Carbon way: [theEvent keyCode]) */
-
/* is it a "function key"? */
/* Note: Sometimes a plain key will have the NSEventModifierFlagNumericPad
flag set (this is probably a bug in the OS).
charactersIgnoringModifiers method). An annoyance happens if
we have both shift-like and control-like modifiers because
the NSEvent API doesn’t let us ignore only some modifiers.
- Therefore we ignore all shift-like modifiers in that
- case. */
+ In that case we use UCKeyTranslate (ns_get_shifted_character)
+ to look up the correct character. */
/* EV_MODIFIERS2 uses parse_solitary_modifier on all known
modifier keys, which returns 0 for shift-like modifiers.
if (fnKeysym || (emacs_event->modifiers
&& (emacs_event->modifiers != shift_modifier)
&& [[theEvent charactersIgnoringModifiers] length] > 0))
-/*[[theEvent characters] length] */
{
emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
/* FIXME: What are the next four lines supposed to do? */
else if (code == 0x7f)
code |= (1<<28)|(3<<16);
else if (!fnKeysym)
- /* FIXME: This seems wrong, characters in the range
- [0x80, 0xFF] are not ASCII characters. Can’t we just
- use MULTIBYTE_CHAR_KEYSTROKE_EVENT here for all kinds
- of characters? */
- emacs_event->kind = code > 0xFF
- ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
+ {
+#ifdef NS_IMPL_COCOA
+ /* We potentially have both shift- and control-like
+ modifiers in use, so find the correct character
+ ignoring any control-like ones. */
+ code = ns_get_shifted_character (theEvent);
+#endif
+
+ /* FIXME: This seems wrong, characters in the range
+ [0x80, 0xFF] are not ASCII characters. Can’t we just
+ use MULTIBYTE_CHAR_KEYSTROKE_EVENT here for all kinds
+ of characters? */
+ emacs_event->kind = code > 0xFF
+ ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
+ }
emacs_event->code = code;
EV_TRAILER (theEvent);