all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
Subject: Re: Free modifier key assignment (OS X)
Date: Sat, 20 May 2006 17:26:09 +0900	[thread overview]
Message-ID: <wlmzddje5a.wl%mituharu@math.s.chiba-u.ac.jp> (raw)
In-Reply-To: <wlzmpxa95z.wl%mituharu@math.s.chiba-u.ac.jp>

I tried to tackle some issues about mapping the laptop `fn' key to an
Emacs modifier. (This functionality was originally provided by David
Reitter.)

  /* 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.

  */

I think the first one is solved by the patch below, but I can't test
the second one.  Could non-US keyboard users test if the patch below
works for you?  Fn-ö may be recognized as H-\232 instead of H-ö on a
German keyboard even if you set (setq mac-function-modifier 'hyper),
but this is another issue
(http://lists.gnu.org/archive/html/emacs-pretest-bug/2006-05/msg00033.html).

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp

Index: src/macterm.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/macterm.c,v
retrieving revision 1.172
diff -c -r1.172 macterm.c
*** src/macterm.c	20 May 2006 07:15:22 -0000	1.172
--- src/macterm.c	20 May 2006 07:57:56 -0000
***************
*** 9629,9635 ****
    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,
--- 9629,9635 ----
    return *xKeySym != 0;
  }
  
! static unsigned char fn_keycode_to_keycode_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,
***************
*** 9639,9662 ****
    /*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
--- 9639,9662 ----
    /*0x38*/ 0, 0, 0, 0,
    /*0x3C*/ 0, 0, 0, 0,
  
!   /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/,
!   /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/,
!   /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
!   /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-- -> ';'*/, 0,
! 
!   /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
!   /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
!   /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
!   /*0x5C*/ 0x19 /*kp-9 -> '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, 0x7b /*home -> left*/,
!   /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0, 0x7c /*end -> right*/,
!   /*0x78*/ 0, 0x7d /*pgdown -> down*/, 0, 0,
    /*0x7C*/ 0, 0, 0, 0
  };
  static int
***************
*** 9673,9682 ****
  
    /* 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-;.
--- 9673,9679 ----
  
    /* TODO / known issues
  
!   !!!! NEED TO CHECK IF IT REALLY DOESN'T WORK WITH NON-US KEYBOARDS. !!!!!
    - 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-;.
***************
*** 9693,9699 ****
        err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
  			       NULL, sizeof (UInt32), NULL, &mods);
        if (err == noErr && mods & kEventKeyModifierFnMask)
! 	{  *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
  
  	  return (*newCode != 0);
  	}
--- 9690,9696 ----
        err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
  			       NULL, sizeof (UInt32), NULL, &mods);
        if (err == noErr && mods & kEventKeyModifierFnMask)
! 	{  *newCode = fn_keycode_to_keycode_table [keyCode & 0x7f];
  
  	  return (*newCode != 0);
  	}
***************
*** 9702,9751 ****
    return false;
  }
  
- static int
- backtranslate_modified_keycode(int mods, int keycode, int def)
- {
-   EventModifiers mapped_modifiers =
-     (NILP (Vmac_control_modifier) ? 0 : controlKey)
-     | (NILP (Vmac_option_modifier) ? 0 : optionKey)
-     | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
- 
-   if (mods & mapped_modifiers)
-     {
-       /* 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 modifier keys that are mapped to some Emacs
- 	 modifiers.  */
-       int new_modifiers = mods & ~mapped_modifiers;
-       /* 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;
--- 9699,9704 ----
***************
*** 10338,10343 ****
--- 10291,10299 ----
  	  {
  	    int keycode = (er.message & keyCodeMask) >> 8;
  	    int xkeysym;
+ 	    static SInt16 last_key_script = -1;
+ 	    SInt16 current_key_script;
+ 	    UInt32 modifiers = er.modifiers, mapped_modifiers;
  
  #if USE_CARBON_EVENTS && defined (MAC_OSX)
  	    /* When using Carbon Events, we need to pass raw keyboard
***************
*** 10358,10392 ****
  	    if (er.what == keyUp)
  	      break;
  
- #if 0
- 	    if (dpyinfo->x_focus_frame == NULL)
- 	      {
- 		/* Beep if keyboard input occurs when all the frames
- 		   are invisible.  */
- 		SysBeep (1);
- 		break;
- 	      }
- #endif
- 
- 	    {
- 	      static SInt16 last_key_script = -1;
- 	      SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
- 
- 	      if (last_key_script != current_key_script)
- 		{
- 		  struct input_event event;
- 
- 		  EVENT_INIT (event);
- 		  event.kind = LANGUAGE_CHANGE_EVENT;
- 		  event.arg = Qnil;
- 		  event.code = current_key_script;
- 		  event.timestamp = timestamp;
- 		  kbd_buffer_store_event (&event);
- 		  count++;
- 		}
- 	      last_key_script = current_key_script;
- 	    }
- 
  	    ObscureCursor ();
  
  	    f = mac_focus_frame (dpyinfo);
--- 10314,10319 ----
***************
*** 10398,10442 ****
  		dpyinfo->mouse_face_hidden = 1;
  	      }
  
! 	    /* 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))
  	      {
! 		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
! 	  inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
  #else
! 	  inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
  #endif
! 	  inev.modifiers |= (extra_keyboard_modifiers
! 			     & (meta_modifier | alt_modifier
! 				| hyper_modifier | super_modifier));
! 	  XSETFRAME (inev.frame_or_window, f);
  	  break;
  
  	case kHighLevelEvent:
--- 10325,10484 ----
  		dpyinfo->mouse_face_hidden = 1;
  	      }
  
! 	    current_key_script = GetScriptManagerVariable (smKeyScript);
! 	    if (last_key_script != current_key_script)
  	      {
! 		struct input_event event;
! 
! 		EVENT_INIT (event);
! 		event.kind = LANGUAGE_CHANGE_EVENT;
! 		event.arg = Qnil;
! 		event.code = current_key_script;
! 		event.timestamp = timestamp;
! 		kbd_buffer_store_event (&event);
! 		count++;
! 		last_key_script = current_key_script;
  	      }
  
  #if USE_CARBON_EVENTS
! 	    inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
  #else
! 	    inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
! #endif
! 	    inev.modifiers |= (extra_keyboard_modifiers
! 			       & (meta_modifier | alt_modifier
! 				  | hyper_modifier | super_modifier));
! 
! 	    XSETFRAME (inev.frame_or_window, f);
! 
! #if USE_CARBON_EVENTS
! 	    {
! 	      int tmp_code;
! 
! 	      if (convert_fn_keycode (eventRef, keycode, &tmp_code))
! 		keycode = tmp_code;
! 	    }
  #endif
! 	    if (keycode_to_xkeysym (keycode, &xkeysym))
! 	      {
! 		inev.kind = NON_ASCII_KEYSTROKE_EVENT;
! 		inev.code = 0xff00 | xkeysym;
! 		break;
! 	      }
! 
! #if USE_CARBON_EVENTS
! 	    GetEventParameter (eventRef, kEventParamKeyModifiers,
! 			       typeUInt32, NULL,
! 			       sizeof (UInt32), NULL, &modifiers);
! #endif
! 
! 	    mapped_modifiers =
! 	      (NILP (Vmac_control_modifier) ? 0 : controlKey)
! 	      | (NILP (Vmac_option_modifier) ? 0 : optionKey)
! 	      | (NILP (Vmac_command_modifier) ? 0 : cmdKey)
! #ifdef MAC_OSX
! 	      | (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask)
! #endif
! 	      ;
! 
! 	    if (!(modifiers & mapped_modifiers))
! 	      {
! 		inev.kind = ASCII_KEYSTROKE_EVENT;
! 		inev.code = er.message & charCodeMask;
! 	      }
! 	    else
! 	      {
! 		/* translate the keycode back to determine the
! 		   original key */
! #ifdef MAC_OSX
! 		static SInt16 last_key_layout_id = 0;
! 		static Handle uchr_handle = (Handle)-1;
! 		SInt16 current_key_layout_id =
! 		  GetScriptVariable (current_key_script, smScriptKeys);
! 
! 		if (uchr_handle == (Handle)-1
! 		    || last_key_layout_id != current_key_layout_id)
! 		  {
! 		    uchr_handle = GetResource ('uchr', current_key_layout_id);
! 		    last_key_layout_id = current_key_layout_id;
! 		  }
! 
! 		if (uchr_handle)
! 		  {
! 		    OSStatus status;
! 		    UInt16 key_action = er.what - keyDown;
! 		    UInt32 modifier_key_state =
! 		      (modifiers & ~mapped_modifiers) >> 8;
! 		    UInt32 keyboard_type = LMGetKbdType ();
! 		    SInt32 dead_key_state = 0;
! 		    UniChar code;
! 		    UniCharCount actual_length;
! 
! 		    status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle,
! 					     keycode, key_action,
! 					     modifier_key_state,
! 					     keyboard_type, 0,
! 					     &dead_key_state,
! 					     1, &actual_length, &code);
! 		    if (status == noErr && actual_length == 1)
! 		      {
! 			int charset_id, c1, c2;
! 
! 			if (code < 0x80)
! 			  {
! 			    inev.kind = ASCII_KEYSTROKE_EVENT;
! 			    inev.code = code;
! 			  }
! 			else if (code < 0x100)
! 			  {
! 			    if (code < 0xA0)
! 			      charset_id = CHARSET_8_BIT_CONTROL;
! 			    else
! 			      charset_id = charset_latin_iso8859_1;
! 			    inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
! 			    inev.code = MAKE_CHAR (charset_id, code, 0);
! 			  }
! 			else
! 			  {
! 			    if (code < 0x2500)
! 			      charset_id = charset_mule_unicode_0100_24ff,
! 				code -= 0x100;
! 			    else if (code < 0xE000)
! 			      charset_id = charset_mule_unicode_2500_33ff,
! 				code -= 0x2500;
! 			    else
! 			      charset_id = charset_mule_unicode_e000_ffff,
! 				code -= 0xE000;
! 			    c1 = (code / 96) + 32, c2 = (code % 96) + 32;
! 			    inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
! 			    inev.code = MAKE_CHAR (charset_id, c1, c2);
! 			  }
! 		      }
! 		  }
! #endif	/* MAC_OSX */
! 
! 		if (inev.kind == NO_EVENT)
! 		  {
! 		    /* 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.  */
! 		    /* Mask off modifier keys that are mapped to some
! 		       Emacs modifiers.  */
! 		    int new_modifiers = er.modifiers & ~mapped_modifiers;
! 		    /* 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;
! 		    inev.code = (int) KeyTranslate (kchr_ptr, new_keycode,
! 						    &some_state) & 0xff;
! 		    inev.kind = ASCII_KEYSTROKE_EVENT;
! 		  }
! 	      }
! 	  }
  	  break;
  
  	case kHighLevelEvent:

  reply	other threads:[~2006-05-20  8:26 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-25 20:34 Free modifier key assignment (OS X) David Reitter
2005-09-26 13:18 ` Stefan Monnier
2005-09-27  3:45 ` YAMAMOTO Mitsuharu
2005-09-27 10:01   ` David Reitter
2005-09-28  8:28     ` YAMAMOTO Mitsuharu
2006-05-20  8:26       ` YAMAMOTO Mitsuharu [this message]
2005-12-13  3:26   ` Carbon port: M-§ not recognized (Italian keyboards) YAMAMOTO Mitsuharu
  -- strict thread matches above, loose matches on Subject: below --
2005-12-11 17:33 David Reitter
2005-12-12  2:41 ` YAMAMOTO Mitsuharu
2006-01-17  0:26   ` David Reitter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=wlmzddje5a.wl%mituharu@math.s.chiba-u.ac.jp \
    --to=mituharu@math.s.chiba-u.ac.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.