# HG changeset patch # User Steven Tamm # Date 1131726824 0 # Node ID d85a089fce111b36b09b93572335e7110c34bee2 # Parent 98ff41842c947a3cca5bcfe1e8d82e18c014c7cd macterm.c (backtranslate_modified_keycode): New function to mask modifiers off of keycodes for use in modifier mapping. (mac_determine_quit_char_modifiers): Remove mac-reverse-ctrl-meta and replace it with more flexible system mapping mac modifier keys to emacs modifier keys. (convert_fn_keycode): Map Fn-keys to their original keycode using a table (english keyboard only). (syms_of_macterm): Define mac-control-modifier, mac-command-modifier, mac-function-modifier. Define meta and ctrl for use as modifiers. diff -r 98ff41842c94 -r d85a089fce11 src/ChangeLog --- a/src/ChangeLog Fri Nov 11 15:45:44 2005 +0000 +++ b/src/ChangeLog Fri Nov 11 16:33:44 2005 +0000 @@ -1,3 +1,16 @@ +2005-11-11 David Reitter + + * macterm.c (backtranslate_modified_keycode): New function to + mask modifiers off of keycodes for use in modifier mapping. + (mac_determine_quit_char_modifiers): Remove + mac-reverse-ctrl-meta and replace it with more flexible system + mapping mac modifier keys to emacs modifier keys. + (convert_fn_keycode): Map Fn-keys to their original keycode + using a table (english keyboard only). + (syms_of_macterm): Define mac-control-modifier, + mac-command-modifier, mac-function-modifier. + Define meta and ctrl for use as modifiers. + 2005-11-11 Kim F. Storm * .gdbinit (pitx): Fix output format if n_overlay_strings > 0. diff -r 98ff41842c94 -r d85a089fce11 src/macterm.c --- a/src/macterm.c Fri Nov 11 15:45:44 2005 +0000 +++ b/src/macterm.c Fri Nov 11 16:33:44 2005 +0000 @@ -86,15 +86,7 @@ #include "intervals.h" #include "atimer.h" #include "keymap.h" - -/* Set of macros that handle mapping of Mac modifier keys to emacs. */ -#define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \ - (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey)) -#define macShiftKey (shiftKey) -#define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \ - (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \ - : controlKey) -#define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey) + /* Non-nil means Emacs uses toolkit scroll bars. */ @@ -207,7 +199,8 @@ /* The keysyms to use for the various modifiers. */ -static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value; +static Lisp_Object Qalt, Qhyper, Qsuper, Qctrl, + Qmeta, Qmodifier_value; extern int inhibit_window_system; @@ -7920,14 +7913,18 @@ /* Contains the string "reverse", which is a constant for mouse button emu.*/ Lisp_Object Qreverse; -/* True if using command key as meta key. */ -Lisp_Object Vmac_command_key_is_meta; - -/* Modifier associated with the option key, or nil for normal behavior. */ + +/* Modifier associated with the control key, or nil to ignore. */ +Lisp_Object Vmac_control_modifier; + +/* Modifier associated with the option key, or nil to ignore. */ Lisp_Object Vmac_option_modifier; -/* True if the ctrl and meta keys should be reversed. */ -Lisp_Object Vmac_reverse_ctrl_meta; +/* Modifier associated with the command key, or nil to ignore. */ +Lisp_Object Vmac_command_modifier; + +/* Modifier associated with the function key, or nil to ignore. */ +Lisp_Object Vmac_function_modifier; /* True if the option and command modifiers should be used to emulate a three button mouse */ @@ -8001,20 +7998,44 @@ #endif { unsigned int result = 0; - if (mods & macShiftKey) + if (mods & shiftKey) result |= shift_modifier; - if (mods & macCtrlKey) - result |= ctrl_modifier; - if (mods & macMetaKey) - result |= meta_modifier; - if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey)) - result |= alt_modifier; + + + + /* Deactivated to simplify configuration: + if Vmac_option_modifier is non-NIL, we fully process the Option + key. Otherwise, we only process it if an additional Ctrl or Command + is pressed. That way the system may convert the character to a + composed one. + if ((mods & optionKey) && + (( !NILP(Vmac_option_modifier) || + ((mods & cmdKey) || (mods & controlKey))))) */ + if (!NILP (Vmac_option_modifier) && (mods & optionKey)) { - Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value); - if (!NILP(val)) - result |= XUINT(val); + Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); } - + if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) { + Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); + } + if (!NILP (Vmac_control_modifier) && (mods & controlKey)) { + Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); + } + +#ifdef MAC_OSX + if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) { + Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value); + if (INTEGERP(val)) + result |= XUINT(val); + } +#endif + return result; } @@ -8035,7 +8056,7 @@ #if USE_CARBON_EVENTS /* Obtains the event modifiers from the event ref and then calls mac_to_emacs_modifiers. */ -static int +static UInt32 mac_event_to_emacs_modifiers (EventRef eventRef) { UInt32 mods = 0; @@ -9385,13 +9406,129 @@ /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0 }; -static int + +static int keycode_to_xkeysym (int keyCode, int *xKeySym) { *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f]; return *xKeySym != 0; } +static unsigned char fn_keycode_to_xkeysym_table[] = { + /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + /*0x30*/ 0, 0, 0, 0, + /*0x34*/ 0, 0, 0, 0, + /*0x38*/ 0, 0, 0, 0, + /*0x3C*/ 0, 0, 0, 0, + + /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/, + /*0x44*/ 0, '/' /*kp-+*/, 0, 0, + /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/, + /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0, + + /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/, + /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/, + /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/, + /*0x5C*/ '9' /*kp-9*/, 0, 0, 0, + + /*0x60*/ 0, 0, 0, 0, + /*0x64*/ 0, 0, 0, 0, + /*0x68*/ 0, 0, 0, 0, + /*0x6C*/ 0, 0, 0, 0, + + /*0x70*/ 0, 0, 0, 0, + /*0x74*/ 0, 0, 0, 0, + /*0x78*/ 0, 0, 0, 0, + /*0x7C*/ 0, 0, 0, 0 +}; +static int +convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode) +{ +#ifdef MAC_OSX + /* Use the special map to translate keys when function modifier is + to be caught. KeyTranslate can't be used in that case. + We can't detect the function key using the input_event.modifiers, + because this uses the high word of an UInt32. Therefore, + we'll just read it out of the original eventRef. + */ + + + /* TODO / known issues + + - Fn-Shift-j is regonized as Fn-j and not Fn-J. + The above table always translates to lower characters. We need to use + the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*. + + - The table is meant for English language keyboards, and it will work + for many others with the exception of key combinations like Fn-ö on + a German keyboard, which is currently mapped to Fn-;. + How to solve this without keeping separate tables for all keyboards + around? KeyTranslate isn't of much help here, as it only takes a 16-bit + value for keycode with the modifiers in he high byte, i.e. no room for the + Fn modifier. That's why we need the table. + + */ + + UInt32 mods = 0; + if (!NILP(Vmac_function_modifier)) + { + GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL, + sizeof (UInt32), NULL, &mods); + if (mods & kEventKeyModifierFnMask) + { *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f]; + + return (*newCode != 0); + } + } +#endif + return false; +} + +static int +backtranslate_modified_keycode(int mods, int keycode, int def) +{ + if (mods & + (controlKey | + (NILP (Vmac_option_modifier) ? 0 : optionKey) | + cmdKey)) + { + /* This code comes from Keyboard Resource, + Appendix C of IM - Text. This is necessary + since shift is ignored in KCHR table + translation when option or command is pressed. + It also does not translate correctly + control-shift chars like C-% so mask off shift + here also. + + Not done for combinations with the option key (alt) + unless it is to be caught by Emacs: this is + to preserve key combinations translated by the OS + such as Alt-3. + */ + /* mask off option and command */ + int new_modifiers = mods & 0xe600; + /* set high byte of keycode to modifier high byte*/ + int new_keycode = keycode | new_modifiers; + Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); + unsigned long some_state = 0; + return (int) KeyTranslate (kchr_ptr, new_keycode, + &some_state) & 0xff; + /* TO DO: Recognize two separate resulting characters, "for + example, when the user presses Option-E followed by N, you + can map this through the KeyTranslate function using the + U.S. 'KCHR' resource to produce ´n, which KeyTranslate + returns as two characters in the bytes labeled Character code + 1 and Character code 2." (from Carbon API doc) */ + + } + else + return def; +} + + #if !USE_CARBON_EVENTS static RgnHandle mouse_region = NULL; @@ -9936,8 +10073,7 @@ || !(er.modifiers & cmdKey)) && (!NILP (Vmac_pass_control_to_system) || !(er.modifiers & controlKey)) - && (!NILP (Vmac_command_key_is_meta) - && NILP (Vmac_option_modifier) + && (NILP (Vmac_option_modifier) || !(er.modifiers & optionKey))) if (SendEventToEventTarget (eventRef, toolbox_dispatcher) != eventNotHandledErr) @@ -9981,49 +10117,36 @@ dpyinfo->mouse_face_hidden = 1; } - if (keycode_to_xkeysym (keycode, &xkeysym)) - { - inev.code = 0xff00 | xkeysym; - inev.kind = NON_ASCII_KEYSTROKE_EVENT; - } - else + /* translate the keycode back to determine the original key */ + /* Convert key code if function key is pressed. + Otherwise, if non-ASCII-event, take care of that + without re-translating the key code. */ +#if USE_CARBON_EVENTS + if (convert_fn_keycode (eventRef, keycode, &xkeysym)) { - if (er.modifiers & (controlKey | - (NILP (Vmac_command_key_is_meta) ? optionKey - : cmdKey))) - { - /* This code comes from Keyboard Resource, - Appendix C of IM - Text. This is necessary - since shift is ignored in KCHR table - translation when option or command is pressed. - It also does not translate correctly - control-shift chars like C-% so mask off shift - here also */ - int new_modifiers = er.modifiers & 0xe600; - /* mask off option and command */ - int new_keycode = keycode | new_modifiers; - Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); - unsigned long some_state = 0; - inev.code = KeyTranslate (kchr_ptr, new_keycode, - &some_state) & 0xff; - } - else if (!NILP (Vmac_option_modifier) - && (er.modifiers & optionKey)) - { - /* When using the option key as an emacs modifier, - convert the pressed key code back to one - without the Mac option modifier applied. */ - int new_modifiers = er.modifiers & ~optionKey; - int new_keycode = keycode | new_modifiers; - Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); - unsigned long some_state = 0; - inev.code = KeyTranslate (kchr_ptr, new_keycode, - &some_state) & 0xff; - } - else - inev.code = er.message & charCodeMask; + inev.code = xkeysym; + /* this doesn't work - tried to add shift modifiers */ + inev.code = + backtranslate_modified_keycode(er.modifiers & (~0x2200), + xkeysym | 0x80, xkeysym); inev.kind = ASCII_KEYSTROKE_EVENT; - } + } + else +#endif + if (keycode_to_xkeysym (keycode, &xkeysym)) + { + inev.code = 0xff00 | xkeysym; + inev.kind = NON_ASCII_KEYSTROKE_EVENT; + } + else + { + + inev.code = + backtranslate_modified_keycode(er.modifiers, keycode, + er.message & charCodeMask); + inev.kind = ASCII_KEYSTROKE_EVENT; + + } } #if USE_CARBON_EVENTS @@ -10463,10 +10586,9 @@ /* Map modifiers */ mac_quit_char_modifiers = 0; - if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey; - if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey; - if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey; - if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey; + if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= controlKey; + if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey; + if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= optionKey; } static void @@ -10623,6 +10745,10 @@ #endif Qmodifier_value = intern ("modifier-value"); + Qctrl = intern ("ctrl"); + Fput (Qctrl, Qmodifier_value, make_number (ctrl_modifier)); + Qmeta = intern ("meta"); + Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); Qalt = intern ("alt"); Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); Qhyper = intern ("hyper"); @@ -10674,22 +10800,37 @@ staticpro (&last_mouse_motion_frame); last_mouse_motion_frame = Qnil; - - DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta, - doc: /* Non-nil means that the command key is used as the Emacs meta key. -Otherwise the option key is used. */); - Vmac_command_key_is_meta = Qt; + + + +/* Variables to configure modifier key assignment. */ + + DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier, + doc: /* Modifier key assumed when the Mac control key is pressed. +The value can be `alt', `ctrl', `hyper', or `super' for the respective +modifier. The default is `ctrl'. */); + Vmac_control_modifier = Qctrl; DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier, - doc: /* Modifier to use for the Mac alt/option key. The value can -be alt, hyper, or super for the respective modifier. If the value is -nil then the key will act as the normal Mac option modifier. */); + doc: /* Modifier key assumed when the Mac alt/option key is pressed. +The value can be `alt', `ctrl', `hyper', or `super' for the respective +modifier. If the value is nil then the key will act as the normal +Mac control modifier, and the option key can be used to compose +characters depending on the chosen Mac keyboard setting. */); Vmac_option_modifier = Qnil; - DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta, - doc: /* Non-nil means that the control and meta keys are reversed. This is -useful for non-standard keyboard layouts. */); - Vmac_reverse_ctrl_meta = Qnil; + DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier, + doc: /* Modifier key assumed when the Mac command key is pressed. +The value can be `alt', `ctrl', `hyper', or `super' for the respective +modifier. The default is `meta'. */); + Vmac_command_modifier = Qmeta; + + DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier, + doc: /* Modifier key assumed when the Mac function key is pressed. +The value can be `alt', `ctrl', `hyper', or `super' for the respective +modifier. Note that remapping the function key may lead to unexpected +results for some keys on non-US/GB keyboards. */); + Vmac_function_modifier = Qnil; DEFVAR_LISP ("mac-emulate-three-button-mouse", &Vmac_emulate_three_button_mouse,