]> git.eshelyaron.com Git - emacs.git/commitdiff
macterm.c (backtranslate_modified_keycode): New function to
authorSteven Tamm <steventamm@mac.com>
Fri, 11 Nov 2005 16:33:44 +0000 (16:33 +0000)
committerSteven Tamm <steventamm@mac.com>
Fri, 11 Nov 2005 16:33:44 +0000 (16:33 +0000)
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.

src/ChangeLog
src/macterm.c

index 80df9d42123ca8976243cff32fe57c3ff7ab40f1..7fab16badf77807c8321d00f2bc36e2522aef105 100644 (file)
@@ -1,3 +1,16 @@
+2005-11-11  David Reitter <david.reitter@gmail.com>
+
+       * 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  <storm@cua.dk>
 
        * .gdbinit (pitx): Fix output format if n_overlay_strings > 0.
index cc5625bd324209d1049e2007d5ebbb20ecd4053c..95d6dfa9fff9f63b12b4c930363ff6a678131aef 100644 (file)
@@ -86,15 +86,7 @@ Boston, MA 02110-1301, USA.  */
 #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)
 \f
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
@@ -207,7 +199,8 @@ extern EMACS_INT extra_keyboard_modifiers;
 
 /* 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 @@ x_find_ccl_program (fontp)
 /* 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 @@ mac_to_emacs_modifiers (EventModifiers mods)
 #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 @@ mac_get_emulated_btn ( UInt32 modifiers )
 #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 @@ static unsigned char keycode_to_xkeysym_table[] = {
   /*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 @@ XTread_socket (sd, expected, hold_quit)
                 || !(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 @@ XTread_socket (sd, expected, hold_quit)
                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 @@ mac_determine_quit_char_modifiers()
 
   /* 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 @@ syms_of_macterm ()
 #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 @@ syms_of_macterm ()
 
   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,