aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Third2018-02-14 20:28:46 +0000
committerAlan Third2018-02-17 12:34:50 +0000
commit5b464a9ceab6aa48138d0353669b426ff69e5365 (patch)
tree5119e77a4f76885f732ce06594d76cf3ba150781 /src
parent4429f97b58653540985387caa554fc0f25f90000 (diff)
downloademacs-5b464a9ceab6aa48138d0353669b426ff69e5365.tar.gz
emacs-5b464a9ceab6aa48138d0353669b426ff69e5365.zip
Fix modifier key handling on macOS
* configure.ac: Use the Carbon framework on macOS. * src/nsterm.m (ns_get_shifted_character) [NS_IMPL_COCOA]: New function. (EmacsView::keyDown) [NS_IMPL_COCOA]: Use ns_get_shifted_character when we have shift style modifiers.
Diffstat (limited to 'src')
-rw-r--r--src/nsterm.m100
1 files changed, 89 insertions, 11 deletions
diff --git a/src/nsterm.m b/src/nsterm.m
index 627a61cac62..1919c6defaf 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -67,6 +67,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
67 67
68#ifdef NS_IMPL_COCOA 68#ifdef NS_IMPL_COCOA
69#include "macfont.h" 69#include "macfont.h"
70#include <Carbon/Carbon.h>
70#endif 71#endif
71 72
72static EmacsMenu *dockMenu; 73static EmacsMenu *dockMenu;
@@ -2679,7 +2680,78 @@ x_get_keysym_name (int keysym)
2679 return value; 2680 return value;
2680} 2681}
2681 2682
2683#ifdef NS_IMPL_COCOA
2684static UniChar
2685ns_get_shifted_character (NSEvent *event)
2686/* Look up the character corresponding to the key pressed on the
2687 current keyboard layout and the currently configured shift-like
2688 modifiers. This ignores the control-like modifiers that cause
2689 [event characters] to give us the wrong result.
2690
2691 Although UCKeyTranslate doesn't require the Carbon framework, some
2692 of the surrounding paraphernalia does, so this function makes
2693 Carbon a requirement. */
2694{
2695 static UInt32 dead_key_state;
2696
2697 /* UCKeyTranslate may return up to 255 characters. If the buffer
2698 isn't large enough then it produces an error. What kind of
2699 keyboard inputs 255 characters in a single keypress? */
2700 UniChar buf[255];
2701 UniCharCount max_string_length = 255;
2702 UniCharCount actual_string_length = 0;
2703 OSStatus result;
2704
2705 CFDataRef layout_ref = (CFDataRef) TISGetInputSourceProperty
2706 (TISCopyCurrentKeyboardLayoutInputSource (), kTISPropertyUnicodeKeyLayoutData);
2707 UCKeyboardLayout* layout = (UCKeyboardLayout*) CFDataGetBytePtr (layout_ref);
2708
2709 UInt32 flags = [event modifierFlags];
2710 UInt32 modifiers = (flags & NSEventModifierFlagShift) ? shiftKey : 0;
2711
2712 NSTRACE ("ns_get_shifted_character");
2713
2714 if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask
2715 && (EQ (ns_right_alternate_modifier, Qnone)
2716 || (EQ (ns_right_alternate_modifier, Qleft)
2717 && EQ (ns_alternate_modifier, Qnone))))
2718 modifiers |= rightOptionKey;
2719
2720 if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
2721 && EQ (ns_alternate_modifier, Qnone))
2722 modifiers |= optionKey;
2723
2724 if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask
2725 && (EQ (ns_right_command_modifier, Qnone)
2726 || (EQ (ns_right_command_modifier, Qleft)
2727 && EQ (ns_command_modifier, Qnone))))
2728 /* Carbon doesn't differentiate between left and right command
2729 keys. */
2730 modifiers |= cmdKey;
2731
2732 if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
2733 && EQ (ns_command_modifier, Qnone))
2734 modifiers |= cmdKey;
2735
2736 result = UCKeyTranslate (layout, [event keyCode], kUCKeyActionDown,
2737 (modifiers >> 8) & 0xFF, LMGetKbdType (),
2738 kUCKeyTranslateNoDeadKeysBit, &dead_key_state,
2739 max_string_length, &actual_string_length, buf);
2740
2741 if (result != 0)
2742 {
2743 NSLog(@"Failed to translate character '%@' with modifiers %x",
2744 [event characters], modifiers);
2745 return 0;
2746 }
2747
2748 /* FIXME: What do we do if more than one code unit is returned? */
2749 if (actual_string_length > 0)
2750 return buf[0];
2682 2751
2752 return 0;
2753}
2754#endif /* NS_IMPL_COCOA */
2683 2755
2684/* ========================================================================== 2756/* ==========================================================================
2685 2757
@@ -6148,8 +6220,6 @@ not_in_argv (NSString *arg)
6148 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ? 6220 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
6149 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0]; 6221 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
6150 6222
6151 /* (Carbon way: [theEvent keyCode]) */
6152
6153 /* is it a "function key"? */ 6223 /* is it a "function key"? */
6154 /* Note: Sometimes a plain key will have the NSEventModifierFlagNumericPad 6224 /* Note: Sometimes a plain key will have the NSEventModifierFlagNumericPad
6155 flag set (this is probably a bug in the OS). 6225 flag set (this is probably a bug in the OS).
@@ -6191,8 +6261,8 @@ not_in_argv (NSString *arg)
6191 charactersIgnoringModifiers method). An annoyance happens if 6261 charactersIgnoringModifiers method). An annoyance happens if
6192 we have both shift-like and control-like modifiers because 6262 we have both shift-like and control-like modifiers because
6193 the NSEvent API doesn’t let us ignore only some modifiers. 6263 the NSEvent API doesn’t let us ignore only some modifiers.
6194 Therefore we ignore all shift-like modifiers in that 6264 In that case we use UCKeyTranslate (ns_get_shifted_character)
6195 case. */ 6265 to look up the correct character. */
6196 6266
6197 /* EV_MODIFIERS2 uses parse_solitary_modifier on all known 6267 /* EV_MODIFIERS2 uses parse_solitary_modifier on all known
6198 modifier keys, which returns 0 for shift-like modifiers. 6268 modifier keys, which returns 0 for shift-like modifiers.
@@ -6218,7 +6288,6 @@ not_in_argv (NSString *arg)
6218 if (fnKeysym || (emacs_event->modifiers 6288 if (fnKeysym || (emacs_event->modifiers
6219 && (emacs_event->modifiers != shift_modifier) 6289 && (emacs_event->modifiers != shift_modifier)
6220 && [[theEvent charactersIgnoringModifiers] length] > 0)) 6290 && [[theEvent charactersIgnoringModifiers] length] > 0))
6221/*[[theEvent characters] length] */
6222 { 6291 {
6223 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; 6292 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
6224 /* FIXME: What are the next four lines supposed to do? */ 6293 /* FIXME: What are the next four lines supposed to do? */
@@ -6227,12 +6296,21 @@ not_in_argv (NSString *arg)
6227 else if (code == 0x7f) 6296 else if (code == 0x7f)
6228 code |= (1<<28)|(3<<16); 6297 code |= (1<<28)|(3<<16);
6229 else if (!fnKeysym) 6298 else if (!fnKeysym)
6230 /* FIXME: This seems wrong, characters in the range 6299 {
6231 [0x80, 0xFF] are not ASCII characters. Can’t we just 6300#ifdef NS_IMPL_COCOA
6232 use MULTIBYTE_CHAR_KEYSTROKE_EVENT here for all kinds 6301 /* We potentially have both shift- and control-like
6233 of characters? */ 6302 modifiers in use, so find the correct character
6234 emacs_event->kind = code > 0xFF 6303 ignoring any control-like ones. */
6235 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; 6304 code = ns_get_shifted_character (theEvent);
6305#endif
6306
6307 /* FIXME: This seems wrong, characters in the range
6308 [0x80, 0xFF] are not ASCII characters. Can’t we just
6309 use MULTIBYTE_CHAR_KEYSTROKE_EVENT here for all kinds
6310 of characters? */
6311 emacs_event->kind = code > 0xFF
6312 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
6313 }
6236 6314
6237 emacs_event->code = code; 6315 emacs_event->code = code;
6238 EV_TRAILER (theEvent); 6316 EV_TRAILER (theEvent);