From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: YAMAMOTO Mitsuharu Newsgroups: gmane.emacs.devel Subject: Re: Free modifier key assignment (OS X) Date: Sat, 20 May 2006 17:26:09 +0900 Organization: Faculty of Science, Chiba University Message-ID: References: <1949F677-E294-4028-B103-F56D8CB48824@gmail.com> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: sea.gmane.org 1148113597 22167 80.91.229.2 (20 May 2006 08:26:37 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sat, 20 May 2006 08:26:37 +0000 (UTC) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat May 20 10:26:33 2006 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1FhMn7-0000xX-7J for ged-emacs-devel@m.gmane.org; Sat, 20 May 2006 10:26:29 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FhMn6-000369-Iw for ged-emacs-devel@m.gmane.org; Sat, 20 May 2006 04:26:28 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1FhMmt-000363-9i for emacs-devel@gnu.org; Sat, 20 May 2006 04:26:15 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1FhMms-00035r-2L for emacs-devel@gnu.org; Sat, 20 May 2006 04:26:14 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FhMmr-00035o-Uv for emacs-devel@gnu.org; Sat, 20 May 2006 04:26:13 -0400 Original-Received: from [133.82.132.2] (helo=mathmail.math.s.chiba-u.ac.jp) by monty-python.gnu.org with esmtp (Exim 4.52) id 1FhMqM-0007px-3F for emacs-devel@gnu.org; Sat, 20 May 2006 04:29:51 -0400 Original-Received: from church.math.s.chiba-u.ac.jp (church [133.82.132.36]) by mathmail.math.s.chiba-u.ac.jp (Postfix) with ESMTP id F3DB32CB3 for ; Sat, 20 May 2006 17:26:09 +0900 (JST) Original-To: emacs-devel@gnu.org In-Reply-To: User-Agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.6 (Marutamachi) APEL/10.6 Emacs/22.0.50 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:54860 Archived-At: 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-=F6 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-=F6 may be recognized as H-\232 instead of H-=F6 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 !=3D 0; } =20 ! static unsigned char fn_keycode_to_xkeysym_table[] =3D { /*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 !=3D 0; } =20 ! static unsigned char fn_keycode_to_keycode_table[] =3D { /*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, =20 ! /*0x40*/ 0, 0x2e /*kp-. =3D .*/, 0, 0x50 /*kp-* =3D 'p'*/, ! /*0x44*/ 0, '/' /*kp-+*/, 0, 0, ! /*0x48*/ 0, 0, 0, 0x30 /*kp-/ =3D '0'*/, ! /*0x4C*/ 0, 0, 0x3b /*kp-- =3D ';'*/, 0, !=20 ! /*0x50*/ 0, 0x2d /*kp-=3D =3D '-'*/, 0x6d /*kp-0 =3D 'm'*/, 0x6a /*kp-1= =3D 'j'*/, ! /*0x54*/ 0x6b /*kp-2 =3D 'k'*/, 0x6c /*kp-3 =3D '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, =20 /*0x60*/ 0, 0, 0, 0, /*0x64*/ 0, 0, 0, 0, /*0x68*/ 0, 0, 0, 0, /*0x6C*/ 0, 0, 0, 0, =20 ! /*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, =20 ! /*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, !=20 ! /*0x50*/ 0, 0x1b /*kp-=3D -> '-'*/, 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, =20 /*0x60*/ 0, 0, 0, 0, /*0x64*/ 0, 0, 0, 0, /*0x68*/ 0, 0, 0, 0, /*0x6C*/ 0, 0, 0, 0, =20 ! /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/, ! /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0, 0x7c /*e= nd -> right*/, ! /*0x78*/ 0, 0x7d /*pgdown -> down*/, 0, 0, /*0x7C*/ 0, 0, 0, 0 }; static int *************** *** 9673,9682 **** =20 /* TODO / known issues =20 ! - 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->*. !=20 - The table is meant for English language keyboards, and it will work for many others with the exception of key combinations like Fn-=F6 on a German keyboard, which is currently mapped to Fn-;. --- 9673,9679 ---- =20 /* TODO / known issues =20 ! !!!! 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-=F6 on a German keyboard, which is currently mapped to Fn-;. *************** *** 9693,9699 **** err =3D GetEventParameter (eventRef, kEventParamKeyModifiers, typeU= Int32, NULL, sizeof (UInt32), NULL, &mods); if (err =3D=3D noErr && mods & kEventKeyModifierFnMask) ! { *newCode =3D fn_keycode_to_xkeysym_table [keyCode & 0x7f]; =20 return (*newCode !=3D 0); } --- 9690,9696 ---- err =3D GetEventParameter (eventRef, kEventParamKeyModifiers, typeU= Int32, NULL, sizeof (UInt32), NULL, &mods); if (err =3D=3D noErr && mods & kEventKeyModifierFnMask) ! { *newCode =3D fn_keycode_to_keycode_table [keyCode & 0x7f]; =20 return (*newCode !=3D 0); } *************** *** 9702,9751 **** return false; } =20 - static int - backtranslate_modified_keycode(int mods, int keycode, int def) - { - EventModifiers mapped_modifiers =3D - (NILP (Vmac_control_modifier) ? 0 : controlKey) - | (NILP (Vmac_option_modifier) ? 0 : optionKey) - | (NILP (Vmac_command_modifier) ? 0 : cmdKey); -=20 - 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. -=20 - 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 =3D mods & ~mapped_modifiers; - /* set high byte of keycode to modifier high byte*/ - int new_keycode =3D keycode | new_modifiers; - Ptr kchr_ptr =3D (Ptr) GetScriptManagerVariable (smKCHRCache); - unsigned long some_state =3D 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 =B4n, which KeyTranslate - returns as two characters in the bytes labeled Character code - 1 and Character code 2." (from Carbon API doc) */ -=20 - } - else - return def; - } -=20 =20 #if !USE_CARBON_EVENTS static RgnHandle mouse_region =3D NULL; --- 9699,9704 ---- *************** *** 10338,10343 **** --- 10291,10299 ---- { int keycode =3D (er.message & keyCodeMask) >> 8; int xkeysym; + static SInt16 last_key_script =3D -1; + SInt16 current_key_script; + UInt32 modifiers =3D er.modifiers, mapped_modifiers; =20 #if USE_CARBON_EVENTS && defined (MAC_OSX) /* When using Carbon Events, we need to pass raw keyboard *************** *** 10358,10392 **** if (er.what =3D=3D keyUp) break; =20 - #if 0 - if (dpyinfo->x_focus_frame =3D=3D NULL) - { - /* Beep if keyboard input occurs when all the frames - are invisible. */ - SysBeep (1); - break; - } - #endif -=20 - { - static SInt16 last_key_script =3D -1; - SInt16 current_key_script =3D GetScriptManagerVariable (smKeyScrip= t); -=20 - if (last_key_script !=3D current_key_script) - { - struct input_event event; -=20 - EVENT_INIT (event); - event.kind =3D LANGUAGE_CHANGE_EVENT; - event.arg =3D Qnil; - event.code =3D current_key_script; - event.timestamp =3D timestamp; - kbd_buffer_store_event (&event); - count++; - } - last_key_script =3D current_key_script; - } -=20 ObscureCursor (); =20 f =3D mac_focus_frame (dpyinfo); --- 10314,10319 ---- *************** *** 10398,10442 **** dpyinfo->mouse_face_hidden =3D 1; } =20 ! /* 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 =3D xkeysym; ! /* this doesn't work - tried to add shift modifiers */ ! inev.code =3D ! backtranslate_modified_keycode(er.modifiers & (~0x2200), ! xkeysym | 0x80, xkeysym); ! inev.kind =3D ASCII_KEYSTROKE_EVENT; } - else - #endif - if (keycode_to_xkeysym (keycode, &xkeysym)) - { - inev.code =3D 0xff00 | xkeysym; - inev.kind =3D NON_ASCII_KEYSTROKE_EVENT; - } - else - { - inev.code =3D - backtranslate_modified_keycode(er.modifiers, keycode, - er.message & charCodeMask); - inev.kind =3D ASCII_KEYSTROKE_EVENT; - } - } =20 #if USE_CARBON_EVENTS ! inev.modifiers =3D mac_event_to_emacs_modifiers (eventRef); #else ! inev.modifiers =3D mac_to_emacs_modifiers (er.modifiers); #endif ! inev.modifiers |=3D (extra_keyboard_modifiers ! & (meta_modifier | alt_modifier ! | hyper_modifier | super_modifier)); ! XSETFRAME (inev.frame_or_window, f); break; =20 case kHighLevelEvent: --- 10325,10484 ---- dpyinfo->mouse_face_hidden =3D 1; } =20 ! current_key_script =3D GetScriptManagerVariable (smKeyScript); ! if (last_key_script !=3D current_key_script) { ! struct input_event event; !=20 ! EVENT_INIT (event); ! event.kind =3D LANGUAGE_CHANGE_EVENT; ! event.arg =3D Qnil; ! event.code =3D current_key_script; ! event.timestamp =3D timestamp; ! kbd_buffer_store_event (&event); ! count++; ! last_key_script =3D current_key_script; } =20 #if USE_CARBON_EVENTS ! inev.modifiers =3D mac_event_to_emacs_modifiers (eventRef); #else ! inev.modifiers =3D mac_to_emacs_modifiers (er.modifiers); ! #endif ! inev.modifiers |=3D (extra_keyboard_modifiers ! & (meta_modifier | alt_modifier ! | hyper_modifier | super_modifier)); !=20 ! XSETFRAME (inev.frame_or_window, f); !=20 ! #if USE_CARBON_EVENTS ! { ! int tmp_code; !=20 ! if (convert_fn_keycode (eventRef, keycode, &tmp_code)) ! keycode =3D tmp_code; ! } #endif ! if (keycode_to_xkeysym (keycode, &xkeysym)) ! { ! inev.kind =3D NON_ASCII_KEYSTROKE_EVENT; ! inev.code =3D 0xff00 | xkeysym; ! break; ! } !=20 ! #if USE_CARBON_EVENTS ! GetEventParameter (eventRef, kEventParamKeyModifiers, ! typeUInt32, NULL, ! sizeof (UInt32), NULL, &modifiers); ! #endif !=20 ! mapped_modifiers =3D ! (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 ! ; !=20 ! if (!(modifiers & mapped_modifiers)) ! { ! inev.kind =3D ASCII_KEYSTROKE_EVENT; ! inev.code =3D er.message & charCodeMask; ! } ! else ! { ! /* translate the keycode back to determine the ! original key */ ! #ifdef MAC_OSX ! static SInt16 last_key_layout_id =3D 0; ! static Handle uchr_handle =3D (Handle)-1; ! SInt16 current_key_layout_id =3D ! GetScriptVariable (current_key_script, smScriptKeys); !=20 ! if (uchr_handle =3D=3D (Handle)-1 ! || last_key_layout_id !=3D current_key_layout_id) ! { ! uchr_handle =3D GetResource ('uchr', current_key_layout_id); ! last_key_layout_id =3D current_key_layout_id; ! } !=20 ! if (uchr_handle) ! { ! OSStatus status; ! UInt16 key_action =3D er.what - keyDown; ! UInt32 modifier_key_state =3D ! (modifiers & ~mapped_modifiers) >> 8; ! UInt32 keyboard_type =3D LMGetKbdType (); ! SInt32 dead_key_state =3D 0; ! UniChar code; ! UniCharCount actual_length; !=20 ! status =3D UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle, ! keycode, key_action, ! modifier_key_state, ! keyboard_type, 0, ! &dead_key_state, ! 1, &actual_length, &code); ! if (status =3D=3D noErr && actual_length =3D=3D 1) ! { ! int charset_id, c1, c2; !=20 ! if (code < 0x80) ! { ! inev.kind =3D ASCII_KEYSTROKE_EVENT; ! inev.code =3D code; ! } ! else if (code < 0x100) ! { ! if (code < 0xA0) ! charset_id =3D CHARSET_8_BIT_CONTROL; ! else ! charset_id =3D charset_latin_iso8859_1; ! inev.kind =3D MULTIBYTE_CHAR_KEYSTROKE_EVENT; ! inev.code =3D MAKE_CHAR (charset_id, code, 0); ! } ! else ! { ! if (code < 0x2500) ! charset_id =3D charset_mule_unicode_0100_24ff, ! code -=3D 0x100; ! else if (code < 0xE000) ! charset_id =3D charset_mule_unicode_2500_33ff, ! code -=3D 0x2500; ! else ! charset_id =3D charset_mule_unicode_e000_ffff, ! code -=3D 0xE000; ! c1 =3D (code / 96) + 32, c2 =3D (code % 96) + 32; ! inev.kind =3D MULTIBYTE_CHAR_KEYSTROKE_EVENT; ! inev.code =3D MAKE_CHAR (charset_id, c1, c2); ! } ! } ! } ! #endif /* MAC_OSX */ !=20 ! if (inev.kind =3D=3D 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 =3D er.modifiers & ~mapped_modifiers; ! /* set high byte of keycode to modifier high byte*/ ! int new_keycode =3D keycode | new_modifiers; ! Ptr kchr_ptr =3D (Ptr) GetScriptManagerVariable (smKCHRCache); ! unsigned long some_state =3D 0; ! inev.code =3D (int) KeyTranslate (kchr_ptr, new_keycode, ! &some_state) & 0xff; ! inev.kind =3D ASCII_KEYSTROKE_EVENT; ! } ! } ! } break; =20 case kHighLevelEvent: