Ticket UUID: | 1626ed65b879bd76db99ef6abbbe18b64bef95a5 | |||
Title: | ⌘ ´ (command-acute) in Spanish keyboard → immediate crash (how many years so?) | |||
Type: | Bug | Version: | 8.6 | |
Submitter: | juanfal | Created on: | 2021-02-28 18:57:34 | |
Subsystem: | 83. Mac OS X Build | Assigned To: | marc_culler | |
Priority: | 5 Medium | Severity: | Critical | |
Status: | Closed | Last Modified: | 2021-03-02 20:09:40 | |
Resolution: | Fixed | Closed By: | jan.nijtmans | |
Closed on: | 2021-03-02 20:09:40 | |||
Description: |
$ wish8.6 (just after entering, I pressed ⌘ ` ) % 2021-02-28 19:53:02.897 wish8.6[44867:5138805] -[TKMenu submenuAction:]: unrecognized selector sent to instance 0x7fdb57ccfe30 2021-02-28 19:53:02.903 wish8.6[44867:5138805] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TKMenu submenuAction:]: unrecognized selector sent to instance 0x7fdb57ccfe30' *** First throw call stack: ( 0 CoreFoundation 0x00007fff204bcd6f __exceptionPreprocess + 242 1 libobjc.A.dylib 0x00007fff201f5bbb objc_exception_throw + 48 2 CoreFoundation 0x00007fff2053f4c8 -[NSObject(NSObject) __retain_OA] + 0 3 CoreFoundation 0x00007fff20424dcd ___forwarding___ + 1448 4 CoreFoundation 0x00007fff20424798 _CF_forwarding_prep_0 + 120 5 AppKit 0x00007fff22d79067 -[NSApplication(NSResponder) sendAction:to:from:] + 288 6 AppKit 0x00007fff23020469 -[NSCarbonMenuImpl performMenuAction:withTarget:] + 144 7 AppKit 0x00007fff22e7afe9 -[NSMenu _performKeyEquivalentWithDelegate:] + 188 8 AppKit 0x00007fff22e7ab28 -[NSMenu performKeyEquivalent:] + 71 9 AppKit 0x00007fff232d1a8f routeKeyEquivalent + 534 10 AppKit 0x00007fff22cdffff -[NSApplication(NSEvent) sendEvent:] + 1147 11 libtk8.6.dylib 0x0000000108e9d740 -[TKApplication(TKNotify) sendEvent:] + 124 12 libtk8.6.dylib 0x0000000108e9df49 TkMacOSXEventsCheckProc + 397 13 libtcl8.6.dylib 0x00000001091caed0 Tcl_DoOneEvent + 302 14 libtk8.6.dylib 0x0000000108deebc5 Tk_MainLoop + 33 15 libtk8.6.dylib 0x0000000108dfb7d2 Tk_MainEx + 1624 16 wish8.6 0x0000000100b12e1c main + 47 17 libdyld.dylib 0x00007fff20365f3d start + 1 18 ??? 0x0000000000000001 0x0 + 1 ) libc++abi: terminating with uncaught exception of type NSException Abort trap: 6 | |||
User Comments: |
jan.nijtmans added on 2021-03-02 20:09:40:
Great! @aivarannamaa, I don't see any way for a workaround using the latest Tk release.... Sorry. marc_culler (claiming to be Marc Culler) added on 2021-03-02 19:28:40: Incidentally, it seems that the best way to input a backquote with a Spanish keyboard is probably to type acute space. That works, anyway. marc_culler (claiming to be Marc Culler) added on 2021-03-02 19:19:03: I think this is resolved now. I changed the logic so that a dead key which also has a Command modifier will not be processed by the text input client. This eliminated the crash I was seeing at exit. But the override of [NSMenu performKeyEquivalent] is still needed. Having that callback return NO when it receives a key event with no characters does not interfere with performing the KeyEquivalent. Apparently that happens at some other level in the responder chain, without causing an abort, if the callback returns NO. In particular the ⌘` accelerator works correctly with a Spanish keyboard. So I merged the fix and will close this ticket now. jan.nijtmans added on 2021-03-02 16:44:41: Thanks, @marc, for the explanation. Makes sense! So the solution is not there yet. No problem for now. marc_culler (claiming to be Marc Culler) added on 2021-03-02 15:55:10: Actually, the exception in the logic should only be for the Command modifier. There are many cases where Option is used to create a key that behaves the way that acute does on the Spanish keyboard. The compose key for a grave accent on a US keyboard is Option-e, for example. marc_culler (claiming to be Marc Culler) added on 2021-03-02 15:10:30: @jan: this explains everything, and means that this really is a Tk bug. It is caused by a subtle aspect of the NSTextInputClient protocol which, of course, is undocumented by Apple. I will have to rework the patch. Here is the story. The Spanish keyboard does not have a backquote key. The substitute for a backquote is a standalone acute accent. But the acute accent key is intended only for use in composition sequences. To generate a standalone acute accent with a Spanish keyboard, e.g. to type the shell command: echo `ls` the fake backquotes have to be generated with some sort of composition sequence, such as acute - left arrow - right arrow. However, Command-backquote is a built-in accelerator on macOS which cycles through the open windows of the application. With a Spanish keyboard Apple substitutes Command-acute as the accelerator. The crash is happening because the Command-acute key is initiating a composition sequence, meaning that the text input system has created an incomplete key event, with no characters, and cached it to be delivered later, when the next key is pressed. It has to wait for the next key so it can figure out which accented letter should be used as the character for the key event. But, even though the key event is incomplete, it is still getting passed to [NSMenu performKeyEquivalent] which recognizes that the key is an accelerator and passes the incomplete event on to the menu system. The acute key should not initiate a composition sequence if it has modifiers. In fact, no key with modifiers should ever initiate a composition sequence. So I think the logic in tkMacOSXKeyEvent.c needs to be adjusted so as to ensure that is the case. aivarannamaa added on 2021-03-02 12:23:28: I guess it will take time until this fix ends up in a release and more time until the release is included in official Python distributions. Can you suggest a work-around for the end application? I tried capturing all key-presses to see if I can neutralize this situation with a "break", but the event never made to my event handler. Is there anything else I could try? Some menu options? Or can I change something in the tcl files of Tcl/Tk distribution? jan.nijtmans added on 2021-03-02 07:22:08: Actually, it's not the backtick causing the crash it's the 'acute' accent '´' which is causing it. The US keyboard doesn't have that character. Therefore I changed the title of this ticket now. I tested the fix, and it works fine. Well done! I agree this looks like an Apple bug, most likely already present for a long time. GTG, just merge when you feel ready. I don't think it's possible to write a test-case for this. marc_culler (claiming to be Marc Culler) added on 2021-03-01 18:02:31: OK. I pushed a fix to a bugfix branch. I do not think this is a Tk bug. It is also not caused by the Menu handling not being able to handle chars larger than 127. It appears to be an Apple bug, and therefore will never be fixed. I found that the callback method [NSMenu performKeyEquivalent] was being passed a malformed NSEvent of type NSEventTypeKeyDown. The event had no characters, which causes an abort somewhere inside of Apple's menu code. The method should return a boolean value indicating whether to call a menu accelerator. The workaround in the bugfix branch is to override the method for the TKMenu class to make it return NO if the event that it receives has no characters. This change caused a crash at exit because the setMarkedText method in the NSTextInputClient would get called for the TKContentView of a toplevel which had been destroyed. So I had to add a guard against that. These bad events are not generated when pressing Command-backquote on a US keyboard. I don't know if there are other ways to generate them. I also don't know how long this bug has been around or which versions of macOS are affected. jan.nijtmans added on 2021-03-01 09:41:10: I can also reproduce it, when switching the keyboard to Spanish layout. When debugging tkMacOSXKeyEvent.c, I see: 2021-03-01 10:11:52.044 tktest[4813:30012] -[TKApplication(0x7fb522f28ff0) tkProcessKeyEvent:] repeat=0 mods=100000 char=0 code=33 c=585162096 type=10 2021-03-01 10:11:52.044 tktest[4813:30012] keyDown: Begin compose sequence. 2021-03-01 10:11:52.044 tktest[4813:30012] setMarkedText '´' len =1 range 0 from 1 2021-03-01 10:11:52.044 tktest[4813:30012] insertText '´' len = 1 So an XEvent with the '´' character (decimal 180) is created, looks OK to me so far. The ⌘ character has as result that the next character is sent to the Menu. Apparently, the menu handling part cannot handle codes >= 128. @marc, can you help here? chrstphrchvz added on 2021-02-28 22:58:07: I can reproduce this with core-8-6-branch on macOS 10.15 with Spanish keyboard layout: Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x00007fff7166733a __pthread_kill + 10 1 libsystem_pthread.dylib 0x00007fff71727e60 pthread_kill + 430 2 libsystem_c.dylib 0x00007fff715ee808 abort + 120 3 libc++abi.dylib 0x00007fff6e855458 abort_message + 231 4 libc++abi.dylib 0x00007fff6e8468bf demangling_terminate_handler() + 262 5 libobjc.A.dylib 0x00007fff70381a57 _objc_terminate() + 96 6 libc++abi.dylib 0x00007fff6e854887 std::__terminate(void (*)()) + 8 7 libc++abi.dylib 0x00007fff6e857387 __cxa_rethrow + 99 8 libobjc.A.dylib 0x00007fff7037fe1c objc_exception_rethrow + 37 9 com.apple.AppKit 0x00007fff34b4ac37 -[NSCarbonMenuImpl performMenuAction:withTarget:] + 242 10 com.apple.AppKit 0x00007fff349abf2d -[NSMenu _performKeyEquivalentWithDelegate:] + 188 11 com.apple.AppKit 0x00007fff349aba62 -[NSMenu performKeyEquivalent:] + 71 12 com.apple.AppKit 0x00007fff34de19ab routeKeyEquivalent + 521 13 com.apple.AppKit 0x00007fff347fd87d -[NSApplication(NSEvent) sendEvent:] + 1161 14 libtk8.6.dylib 0x0000000102462e5e -[TKApplication(TKNotify) sendEvent:] + 206 (tkMacOSXNotify.c:205) 15 libtk8.6.dylib 0x00000001024639f8 TkMacOSXEventsCheckProc + 536 (tkMacOSXNotify.c:578) 16 libtcl8.6.dylib 0x00000001026d9dcd Tcl_DoOneEvent + 493 (tclNotify.c:961) 17 libtk8.6.dylib 0x000000010232ac59 Tk_MainLoop + 41 (tkEvent.c:2108) 18 libtk8.6.dylib 0x0000000102342b18 Tk_MainEx + 2376 (tkMain.c:377) 19 wish8.6 0x00000001022ecdde main + 78 (tkAppInit.c:89) 20 libdyld.dylib 0x00007fff7151fcc9 start + 1 |
