[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Problem with processing of key events
From: |
Doug Simons |
Subject: |
Problem with processing of key events |
Date: |
Mon, 17 Jan 2011 10:21:43 -0700 |
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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Problem with processing of key events,
Doug Simons <=