Hello, Some key events are not being processed exactly as they should be.
We have been experiencing a problem in this scenario: We have a window with a table view, a "delete" button, and a text field. The delete button deletes the selected item in the table view, and has its keyEquivalent set to the delete key. So pressing delete with something selected in the table view will delete it. The problem is this: When we are editing a value in the text field, pressing delete will still delete the selected item in the table view, rather than deleting a character in the field. We don't have this problem on OS X. After considerable time looking at the code and reading all of the relevant parts of the Cocoa documentation, I think I've figured out what the difference is and (more or less) how to fix it. The Cocoa documentation talks about dispatching "events it recognizes as potential key equivalents (based on the presence of modifier flags)" as key equivalents. GNUstep has been sending ALL key events in this way, which caused the problem, since the delete button would handle the event in its performKeyEquivalent: method and it would never be sent to the text field. So I've changed NSApplication's sendEvent: method to only call performKeyEquivalent: when the event has modifier keys (other than the shift key, which I think is not considered a modifier in this context). With this change in place, the delete key event goes to the text field as it should, but now the opposite problem exists, namely that the delete button NEVER gets the event, even when the field is not being edited. To handle this part of the problem, I modified NSWindow's keyDown: method to send performKeyEquivalent: to itself. In this way, performKeyEquivalent: will be sent to every view in the window for ALL keyDown events (that aren't otherwise handled), those with modifiers first, from NSApplication, and those without modifiers later, from NSWindow's keyDown after the event has been up the responder chain. I believe this is approximately how Cocoa handles it, based on backtraces I captured (see below) although the documentation doesn't seem to be explicit about this point. My code in NSApplication looks like this: NSApplication.m:2059 unsigned int modifiers = [theEvent modifierFlags]; BOOL usesModifiers = ((modifiers & ~NSShiftKeyMask) != 0); BOOL handledKeyEquivalent = NO; if (usesModifiers) handledKeyEquivalent = [[self keyWindow] performKeyEquivalent: theEvent]; if (handledKeyEquivalent == NO && [[self mainMenu] performKeyEquivalent: theEvent] == NO) { [[theEvent window] sendEvent: theEvent]; } break; And the code in NSWindow: NSWindow.m: 3272 unsigned int modifiers = [theEvent modifierFlags]; BOOL usesModifiers = ((modifiers & ~NSShiftKeyMask) != 0); if (!usesModifiers && [self performKeyEquivalent:theEvent]) return; Let me know if you'd like me to go ahead and check this in -- I hesitate to just throw it in without any warning in this case because this is tinkering with fairly basic behavior that may have subtle impacts. The code in NSWindow in particular could be moved earlier in the keyDown: method (and I'm inclined to think that it should be) to allow performKeyEquivalent: to take precedence over the standard tab and shift-tab behavior, etc. -- what do you think? Regards, Doug P.S. Here are some Cocoa backtraces from our application running on OS X that give some clues about how Cocoa handles these events: Delete key pressed on view with the scenario presented above, with an item selected in the table view and NO active field editor. Note that performKeyEquivalent: is invoked from NSWindow's keyDown: method: #0 0x00099a0b in -[EGGSuite deleteScripts:] at EGGSuite.m:3287 #1 0x9360ac46 in -[NSApplication sendAction:to:from:] #2 0x93a06a8c in -[NSMatrix sendAction:to:] #3 0x939f8fe5 in -[NSMatrix sendAction] #4 0x93a066a1 in -[NSMatrix performKeyEquivalent:] #5 0x93704858 in -[NSControl _performKeyEquivalent:conditionally:] #6 0x939fff1f in -[NSMatrix _performKeyEquivalent:conditionally:] #7 0x93704724 in -[NSView performKeyEquivalent:] #8 0x93704724 in -[NSView performKeyEquivalent:] #9 0x93704724 in -[NSView performKeyEquivalent:] #10 0x93704724 in -[NSView performKeyEquivalent:] #11 0x93704496 in -[NSWindow performKeyEquivalent:] #12 0x937a97a7 in -[NSWindow keyDown:] #13 0x935f7ac1 in forwardMethod #14 0x935f7ac1 in forwardMethod #15 0x935f7ac1 in forwardMethod #16 0x935f7ac1 in forwardMethod #17 0x935f7ac1 in forwardMethod #18 0x935f7ac1 in forwardMethod #19 0x938f6565 in -[NSControl keyDown:] #20 0x937ddf61 in -[NSTableView keyDown:] #21 0x936e1d38 in -[NSWindow sendEvent:] #22 0x935fa817 in -[NSApplication sendEvent:] #23 0x9358e2a7 in -[NSApplication run] #24 0x935862d9 in NSApplicationMain #25 0x000029ac in main at main.m:13 Right arrow pressed in a slightly different scenario, with buttons that use arrow keys as their key equivalents, with a table view item selected WITH OR WITHOUT an active field editor (no difference, presumably because arrow keys are treated as having a modifier key down, so performKeyEquivalent: is called directly from [NSApplication sendEvent:]) (note: GNUstep and Cocoa behave the same way in this scenario): #0 0x000a4530 in -[EGGSuite moveScheduledScriptIn:] at EGGSuite.m:4967 #1 0x9360ac46 in -[NSApplication sendAction:to:from:] #2 0x93a06a8c in -[NSMatrix sendAction:to:] #3 0x939f8fe5 in -[NSMatrix sendAction] #4 0x93a066a1 in -[NSMatrix performKeyEquivalent:] #5 0x93704858 in -[NSControl _performKeyEquivalent:conditionally:] #6 0x939fff1f in -[NSMatrix _performKeyEquivalent:conditionally:] #7 0x93704724 in -[NSView performKeyEquivalent:] #8 0x93704724 in -[NSView performKeyEquivalent:] #9 0x93704724 in -[NSView performKeyEquivalent:] #10 0x93704724 in -[NSView performKeyEquivalent:] #11 0x93704496 in -[NSWindow performKeyEquivalent:] #12 0x937041e1 in -[NSApplication _handleKeyEquivalent:] #13 0x935fa1f2 in -[NSApplication sendEvent:] #14 0x9358e2a7 in -[NSApplication run] #15 0x935862d9 in NSApplicationMain #16 0x000029ac in main at main.m:13 _______________________________________________ Gnustep-dev mailing list Gnustep-dev@gnu.org http://lists.gnu.org/mailman/listinfo/gnustep-dev