gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Problem with processing of key events


From: Fred Kiefer
Subject: Re: Problem with processing of key events
Date: Sat, 21 May 2011 22:52:46 +0200
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.17) Gecko/20110414 SUSE/3.1.10 Thunderbird/3.1.10

Hi Doug,

this very important mail seems to have been lost at that time. I just found it in my unread mail list. Sorry for that.

These back traces that you sent are very interesting. It is really hard to understand what is going on in the NSApplication sendEvent: method.

The criteria you came up with (is there any modifier set) looks rather arbitrary. But it could well be what Apple is using here.
Did you gather any additional information here?

Fred


On 17.01.2011 18:21, Doug Simons wrote:
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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]