comparison src/macterm.c @ 70854:6384ae23d84a

(fn_keycode_to_xkeysym_table, convert_fn_keycode): Remove. (fn_keycode_to_keycode_table) [MAC_OSX]: New variable. (mac_set_unicode_keystroke_event) [TARGET_API_MAC_CARBON]: New function. (XTread_socket) [TARGET_API_MAC_CARBON]: Use it. (XTread_socket) [MAC_OSX]: Try 'uchr' Unicode keyboard-layout resource to backtranslate key with modifiers. (XTread_socket): Don't set read_socket_inev around AEProcessAppleEvent.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Tue, 23 May 2006 08:11:10 +0000
parents 28a79d5b3fb9
children acd53b4b2285 c44562301a11
comparison
equal deleted inserted replaced
70853:993df0652ff7 70854:6384ae23d84a
9627 { 9627 {
9628 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f]; 9628 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
9629 return *xKeySym != 0; 9629 return *xKeySym != 0;
9630 } 9630 }
9631 9631
9632 static unsigned char fn_keycode_to_xkeysym_table[] = { 9632 #ifdef MAC_OSX
9633 /* Table for translating Mac keycode with the laptop `fn' key to that
9634 without it. Destination symbols in comments are keys on US
9635 keyboard, and they may not be the same on other types of
9636 keyboards. */
9637 static unsigned char fn_keycode_to_keycode_table[] = {
9633 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9638 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9634 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9639 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9635 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9640 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9636 9641
9637 /*0x30*/ 0, 0, 0, 0, 9642 /*0x30*/ 0, 0, 0, 0,
9638 /*0x34*/ 0, 0, 0, 0, 9643 /*0x34*/ 0, 0, 0, 0,
9639 /*0x38*/ 0, 0, 0, 0, 9644 /*0x38*/ 0, 0, 0, 0,
9640 /*0x3C*/ 0, 0, 0, 0, 9645 /*0x3C*/ 0, 0, 0, 0,
9641 9646
9642 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/, 9647 /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/,
9643 /*0x44*/ 0, '/' /*kp-+*/, 0, 0, 9648 /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9644 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/, 9649 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9645 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0, 9650 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-- -> ';'*/, 0,
9646 9651
9647 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/, 9652 /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9648 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/, 9653 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9649 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/, 9654 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9650 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0, 9655 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9651 9656
9652 /*0x60*/ 0, 0, 0, 0, 9657 /*0x60*/ 0, 0, 0, 0,
9653 /*0x64*/ 0, 0, 0, 0, 9658 /*0x64*/ 0, 0, 0, 0,
9654 /*0x68*/ 0, 0, 0, 0, 9659 /*0x68*/ 0, 0, 0, 0,
9655 /*0x6C*/ 0, 0, 0, 0, 9660 /*0x6C*/ 0, 0, 0, 0,
9656 9661
9657 /*0x70*/ 0, 0, 0, 0, 9662 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9658 /*0x74*/ 0, 0, 0, 0, 9663 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0, 0x7c /*end -> right*/,
9659 /*0x78*/ 0, 0, 0, 0, 9664 /*0x78*/ 0, 0x7d /*pgdown -> down*/, 0, 0,
9660 /*0x7C*/ 0, 0, 0, 0 9665 /*0x7C*/ 0, 0, 0, 0
9661 }; 9666 };
9662 static int 9667 #endif /* MAC_OSX */
9663 convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
9664 {
9665 #ifdef MAC_OSX
9666 /* Use the special map to translate keys when function modifier is
9667 to be caught. KeyTranslate can't be used in that case.
9668 We can't detect the function key using the input_event.modifiers,
9669 because this uses the high word of an UInt32. Therefore,
9670 we'll just read it out of the original eventRef.
9671 */
9672
9673
9674 /* TODO / known issues
9675
9676 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9677 The above table always translates to lower characters. We need to use
9678 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9679
9680 - The table is meant for English language keyboards, and it will work
9681 for many others with the exception of key combinations like Fn-ö on
9682 a German keyboard, which is currently mapped to Fn-;.
9683 How to solve this without keeping separate tables for all keyboards
9684 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9685 value for keycode with the modifiers in he high byte, i.e. no room for the
9686 Fn modifier. That's why we need the table.
9687
9688 */
9689 OSStatus err;
9690 UInt32 mods = 0;
9691 if (!NILP(Vmac_function_modifier))
9692 {
9693 err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
9694 NULL, sizeof (UInt32), NULL, &mods);
9695 if (err == noErr && mods & kEventKeyModifierFnMask)
9696 { *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
9697
9698 return (*newCode != 0);
9699 }
9700 }
9701 #endif
9702 return false;
9703 }
9704
9705 static int
9706 backtranslate_modified_keycode(int mods, int keycode, int def)
9707 {
9708 EventModifiers mapped_modifiers =
9709 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9710 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9711 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9712
9713 if (mods & mapped_modifiers)
9714 {
9715 /* This code comes from Keyboard Resource,
9716 Appendix C of IM - Text. This is necessary
9717 since shift is ignored in KCHR table
9718 translation when option or command is pressed.
9719 It also does not translate correctly
9720 control-shift chars like C-% so mask off shift
9721 here also.
9722
9723 Not done for combinations with the option key (alt)
9724 unless it is to be caught by Emacs: this is
9725 to preserve key combinations translated by the OS
9726 such as Alt-3.
9727 */
9728 /* Mask off modifier keys that are mapped to some Emacs
9729 modifiers. */
9730 int new_modifiers = mods & ~mapped_modifiers;
9731 /* set high byte of keycode to modifier high byte*/
9732 int new_keycode = keycode | new_modifiers;
9733 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9734 unsigned long some_state = 0;
9735 return (int) KeyTranslate (kchr_ptr, new_keycode,
9736 &some_state) & 0xff;
9737 /* TO DO: Recognize two separate resulting characters, "for
9738 example, when the user presses Option-E followed by N, you
9739 can map this through the KeyTranslate function using the
9740 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9741 returns as two characters in the bytes labeled Character code
9742 1 and Character code 2." (from Carbon API doc) */
9743
9744 }
9745 else
9746 return def;
9747 }
9748
9749 9668
9750 #if !USE_CARBON_EVENTS 9669 #if !USE_CARBON_EVENTS
9751 static RgnHandle mouse_region = NULL; 9670 static RgnHandle mouse_region = NULL;
9752 9671
9753 Boolean 9672 Boolean
9816 kEventPriorityStandard); 9735 kEventPriorityStandard);
9817 if (event) 9736 if (event)
9818 ReleaseEvent (event); 9737 ReleaseEvent (event);
9819 9738
9820 return err; 9739 return err;
9740 }
9741
9742 static void
9743 mac_set_unicode_keystroke_event (code, buf)
9744 UniChar code;
9745 struct input_event *buf;
9746 {
9747 int charset_id, c1, c2;
9748
9749 if (code < 0x80)
9750 {
9751 buf->kind = ASCII_KEYSTROKE_EVENT;
9752 buf->code = code;
9753 }
9754 else if (code < 0x100)
9755 {
9756 if (code < 0xA0)
9757 charset_id = CHARSET_8_BIT_CONTROL;
9758 else
9759 charset_id = charset_latin_iso8859_1;
9760 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
9761 buf->code = MAKE_CHAR (charset_id, code, 0);
9762 }
9763 else
9764 {
9765 if (code < 0x2500)
9766 charset_id = charset_mule_unicode_0100_24ff,
9767 code -= 0x100;
9768 else if (code < 0x33FF)
9769 charset_id = charset_mule_unicode_2500_33ff,
9770 code -= 0x2500;
9771 else if (code >= 0xE000)
9772 charset_id = charset_mule_unicode_e000_ffff,
9773 code -= 0xE000;
9774 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
9775 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
9776 buf->code = MAKE_CHAR (charset_id, c1, c2);
9777 }
9821 } 9778 }
9822 #endif 9779 #endif
9823 9780
9824 /* Emacs calls this whenever it wants to read an input event from the 9781 /* Emacs calls this whenever it wants to read an input event from the
9825 user. */ 9782 user. */
10336 case keyUp: 10293 case keyUp:
10337 case autoKey: 10294 case autoKey:
10338 { 10295 {
10339 int keycode = (er.message & keyCodeMask) >> 8; 10296 int keycode = (er.message & keyCodeMask) >> 8;
10340 int xkeysym; 10297 int xkeysym;
10298 static SInt16 last_key_script = -1;
10299 SInt16 current_key_script;
10300 UInt32 modifiers = er.modifiers, mapped_modifiers;
10301
10302 mapped_modifiers =
10303 (NILP (Vmac_control_modifier) ? 0 : controlKey)
10304 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
10305 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
10341 10306
10342 #if USE_CARBON_EVENTS && defined (MAC_OSX) 10307 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10308 mapped_modifiers |=
10309 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
10310
10311 GetEventParameter (eventRef, kEventParamKeyModifiers,
10312 typeUInt32, NULL,
10313 sizeof (UInt32), NULL, &modifiers);
10314
10343 /* When using Carbon Events, we need to pass raw keyboard 10315 /* When using Carbon Events, we need to pass raw keyboard
10344 events to the TSM ourselves. If TSM handles it, it 10316 events to the TSM ourselves. If TSM handles it, it
10345 will pass back noErr, otherwise it will pass back 10317 will pass back noErr, otherwise it will pass back
10346 "eventNotHandledErr" and we can process it 10318 "eventNotHandledErr" and we can process it
10347 normally. */ 10319 normally. */
10348 if ((mac_pass_command_to_system 10320 if (!(modifiers
10349 || !(er.modifiers & cmdKey)) 10321 & mapped_modifiers
10350 && (mac_pass_control_to_system 10322 & ~(mac_pass_command_to_system ? cmdKey : 0)
10351 || !(er.modifiers & controlKey)) 10323 & ~(mac_pass_control_to_system ? controlKey : 0)))
10352 && (NILP (Vmac_option_modifier)
10353 || !(er.modifiers & optionKey)))
10354 if (SendEventToEventTarget (eventRef, toolbox_dispatcher) 10324 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10355 != eventNotHandledErr) 10325 != eventNotHandledErr)
10356 break; 10326 break;
10357 #endif 10327 #endif
10358 if (er.what == keyUp) 10328 if (er.what == keyUp)
10359 break; 10329 break;
10360
10361 #if 0
10362 if (dpyinfo->x_focus_frame == NULL)
10363 {
10364 /* Beep if keyboard input occurs when all the frames
10365 are invisible. */
10366 SysBeep (1);
10367 break;
10368 }
10369 #endif
10370
10371 {
10372 static SInt16 last_key_script = -1;
10373 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
10374
10375 if (last_key_script != current_key_script)
10376 {
10377 struct input_event event;
10378
10379 EVENT_INIT (event);
10380 event.kind = LANGUAGE_CHANGE_EVENT;
10381 event.arg = Qnil;
10382 event.code = current_key_script;
10383 event.timestamp = timestamp;
10384 kbd_buffer_store_event (&event);
10385 count++;
10386 }
10387 last_key_script = current_key_script;
10388 }
10389 10330
10390 ObscureCursor (); 10331 ObscureCursor ();
10391 10332
10392 f = mac_focus_frame (dpyinfo); 10333 f = mac_focus_frame (dpyinfo);
10393 10334
10396 { 10337 {
10397 clear_mouse_face (dpyinfo); 10338 clear_mouse_face (dpyinfo);
10398 dpyinfo->mouse_face_hidden = 1; 10339 dpyinfo->mouse_face_hidden = 1;
10399 } 10340 }
10400 10341
10401 /* translate the keycode back to determine the original key */ 10342 current_key_script = GetScriptManagerVariable (smKeyScript);
10402 /* Convert key code if function key is pressed. 10343 if (last_key_script != current_key_script)
10403 Otherwise, if non-ASCII-event, take care of that 10344 {
10404 without re-translating the key code. */ 10345 struct input_event event;
10346
10347 EVENT_INIT (event);
10348 event.kind = LANGUAGE_CHANGE_EVENT;
10349 event.arg = Qnil;
10350 event.code = current_key_script;
10351 event.timestamp = timestamp;
10352 kbd_buffer_store_event (&event);
10353 count++;
10354 last_key_script = current_key_script;
10355 }
10356
10357 #ifdef MAC_OSX
10358 if (modifiers & kEventKeyModifierFnMask
10359 && keycode <= 0x7f
10360 && fn_keycode_to_keycode_table[keycode])
10361 keycode = fn_keycode_to_keycode_table[keycode];
10362 #endif
10363 if (keycode_to_xkeysym (keycode, &xkeysym))
10364 {
10365 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
10366 inev.code = 0xff00 | xkeysym;
10367 }
10368 else if (modifiers & mapped_modifiers)
10369 {
10370 /* translate the keycode back to determine the
10371 original key */
10372 #ifdef MAC_OSX
10373 static SInt16 last_key_layout_id = 0;
10374 static Handle uchr_handle = (Handle)-1;
10375 SInt16 current_key_layout_id =
10376 GetScriptVariable (current_key_script, smScriptKeys);
10377
10378 if (uchr_handle == (Handle)-1
10379 || last_key_layout_id != current_key_layout_id)
10380 {
10381 uchr_handle = GetResource ('uchr', current_key_layout_id);
10382 last_key_layout_id = current_key_layout_id;
10383 }
10384
10385 if (uchr_handle)
10386 {
10387 OSStatus status;
10388 UInt16 key_action = er.what - keyDown;
10389 UInt32 modifier_key_state =
10390 (modifiers & ~mapped_modifiers) >> 8;
10391 UInt32 keyboard_type = LMGetKbdType ();
10392 SInt32 dead_key_state = 0;
10393 UniChar code;
10394 UniCharCount actual_length;
10395
10396 status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle,
10397 keycode, key_action,
10398 modifier_key_state,
10399 keyboard_type,
10400 kUCKeyTranslateNoDeadKeysMask,
10401 &dead_key_state,
10402 1, &actual_length, &code);
10403 if (status == noErr && actual_length == 1)
10404 mac_set_unicode_keystroke_event (code, &inev);
10405 }
10406 #endif /* MAC_OSX */
10407
10408 if (inev.kind == NO_EVENT)
10409 {
10410 /* This code comes from Keyboard Resource,
10411 Appendix C of IM - Text. This is necessary
10412 since shift is ignored in KCHR table
10413 translation when option or command is pressed.
10414 It also does not translate correctly
10415 control-shift chars like C-% so mask off shift
10416 here also. */
10417 /* Mask off modifier keys that are mapped to some
10418 Emacs modifiers. */
10419 int new_modifiers = er.modifiers & ~mapped_modifiers;
10420 /* set high byte of keycode to modifier high byte*/
10421 int new_keycode = keycode | new_modifiers;
10422 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
10423 unsigned long some_state = 0;
10424 UInt32 new_char_code;
10425
10426 new_char_code = KeyTranslate (kchr_ptr, new_keycode,
10427 &some_state);
10428 if (new_char_code == 0)
10429 /* Seems like a dead key. Append up-stroke. */
10430 new_char_code = KeyTranslate (kchr_ptr,
10431 new_keycode | 0x80,
10432 &some_state);
10433 if (new_char_code)
10434 {
10435 inev.kind = ASCII_KEYSTROKE_EVENT;
10436 inev.code = new_char_code & 0xff;
10437 }
10438 }
10439 }
10440
10441 if (inev.kind == NO_EVENT)
10442 {
10443 inev.kind = ASCII_KEYSTROKE_EVENT;
10444 inev.code = er.message & charCodeMask;
10445 }
10446
10405 #if USE_CARBON_EVENTS 10447 #if USE_CARBON_EVENTS
10406 if (convert_fn_keycode (eventRef, keycode, &xkeysym)) 10448 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10449 #else
10450 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
10451 #endif
10452 inev.modifiers |= (extra_keyboard_modifiers
10453 & (meta_modifier | alt_modifier
10454 | hyper_modifier | super_modifier));
10455 XSETFRAME (inev.frame_or_window, f);
10456
10457 #if TARGET_API_MAC_CARBON
10458 if (inev.kind == ASCII_KEYSTROKE_EVENT
10459 && inev.code >= 0x80 && inev.modifiers)
10407 { 10460 {
10408 inev.code = xkeysym; 10461 OSStatus err;
10409 /* this doesn't work - tried to add shift modifiers */ 10462 TextEncoding encoding = kTextEncodingMacRoman;
10410 inev.code = 10463 TextToUnicodeInfo ttu_info;
10411 backtranslate_modified_keycode(er.modifiers & (~0x2200), 10464
10412 xkeysym | 0x80, xkeysym); 10465 UpgradeScriptInfoToTextEncoding (current_key_script,
10413 inev.kind = ASCII_KEYSTROKE_EVENT; 10466 kTextLanguageDontCare,
10467 kTextRegionDontCare,
10468 NULL, &encoding);
10469 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
10470 if (err == noErr)
10471 {
10472 UniChar code;
10473 Str255 pstr;
10474 ByteCount unicode_len;
10475
10476 pstr[0] = 1;
10477 pstr[1] = inev.code;
10478 err = ConvertFromPStringToUnicode (ttu_info, pstr,
10479 sizeof (UniChar),
10480 &unicode_len, &code);
10481 if (err == noErr && unicode_len == sizeof (UniChar))
10482 mac_set_unicode_keystroke_event (code, &inev);
10483 DisposeTextToUnicodeInfo (&ttu_info);
10484 }
10414 } 10485 }
10415 else 10486 #endif
10416 #endif
10417 if (keycode_to_xkeysym (keycode, &xkeysym))
10418 {
10419 inev.code = 0xff00 | xkeysym;
10420 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
10421 }
10422 else
10423 {
10424 inev.code =
10425 backtranslate_modified_keycode(er.modifiers, keycode,
10426 er.message & charCodeMask);
10427 inev.kind = ASCII_KEYSTROKE_EVENT;
10428 }
10429 } 10487 }
10430
10431 #if USE_CARBON_EVENTS
10432 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10433 #else
10434 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
10435 #endif
10436 inev.modifiers |= (extra_keyboard_modifiers
10437 & (meta_modifier | alt_modifier
10438 | hyper_modifier | super_modifier));
10439 XSETFRAME (inev.frame_or_window, f);
10440 break; 10488 break;
10441 10489
10442 case kHighLevelEvent: 10490 case kHighLevelEvent:
10443 read_socket_inev = &inev;
10444 AEProcessAppleEvent (&er); 10491 AEProcessAppleEvent (&er);
10445 read_socket_inev = NULL;
10446 break; 10492 break;
10447 10493
10448 default: 10494 default:
10449 break; 10495 break;
10450 } 10496 }