Re: manual item enabling

Graham Cox

Hi Kurt, re-reading the documentation on basic event handling might help:

particularly “The Path of Key Events”, and “Handling Key Equivalents"

Note that I mentioned NSResponder. Both NSApplication and NSView both subclass NSResponder, so there are two very different objects that receive events. I was thinking about this in terms of NSView, but NSApplication does things a little differently.

but if keyDown is what calls performKeyEquivalent, then how could performKeyEquivalent help

NSApplication’s -sendEvent: calls -performKeyEquivalent: but AFAICS, no -keyDown: method ever calls it - it’s always handled before that is called.

It’s still a little unclear to me why the standard approach that Cocoa takes to menu updating can’t be used here. In both the key equivalent case and the click on the menu case, the responder chain is asked to -validateMenuItem: for as many menu items as needed (I would expect this to be just one for a key equivalent), and you just return YES or NO to indicate the enable state of the item. But that validation method is free to examine any other property of the menu item, so if there is some legacy there of command numbers or whatever, the validation method can use it. The validation method can also change the text of a menu item.

Now I recall that in TCL, the whole menu structure (per menu? I forget now) was passed to the responder chain so it was less granular than Cocoa, so the update mechanism would enable a whole bunch of items at once. Is my understanding correct that you’d rather port that code more or less “as is”? In which case possibly the menu delegate approach is going to be more appropriate than validating individual items.

But I would suggest that handling individual items is not so very different - it’s the same concept, just broken down a little more so that you deal with one item at a time. In fact your code is generally written so that that multiple-calling situation is irrelevant. The same validation method handles ALL the cases pertaining to the current responder object, just as the TCL update method does. It’s just that the Cocoa method is called multiple times, but only one case applies, and the TCL method is called only once, but multiple cases apply. The difference between the two is actually minor. In the cocoa case, you just need to add an additional if() per item that checks that the passed item is actually the one you want.

so for example, in the TCL case, you’d have had code that was equivalent to:

- (void) updateMenu:(CMenu*) menu
menu.items[kNewItem].enable = YES;
menu.items[kOpenItem].enable = YES;
menu.items[kQuitItem].enable = YES;

[nextResponder updateMenu:menu];

and in Cocoa, you change that to:

- (BOOL) validateMenuItem:(NSMenuItem*) item
if( item.command == kNewItem )
return YES;

if( item.command == kOpenItem )
return YES;

if( item.command == kQuitItem )
return YES;

return [nextResponder validateMenuItem:item];

Note this is just conceptual code - there is no method on NSMenuItem called -command. So you’d have to deal with that difference, or use the menu item's -action property instead, which is the usual way.

So in my view, you’re overthinking this. Just let Cocoa do its thing and adapt the validation to suit rather than try to stick with your TCL approach and adapt the event handling to suit.

Of course I don’t have your code in front of me, so this may be off base.


On 7 Apr 2020, at 10:47 am, Kurt Bigler <kkblists@...> wrote:


Thanks Eric, Allan, and Graham for your help on this last November 24-25.  This issue got pushed into the background and I'm only now getting back to it.  I'm replying specifically to Graham's post due to the specifics I'm addressing.

I did not yet take Eric's advice to use menuNeedsUpdate since I'd like to take a shortcut for an interrim release we'd now like to do ASAP.  So this addresses that shortcut described by both Graham and Allan.

I used the approach of overriding NSMenu for the main app menu.  I update menus in the performKeyEquivalent override before calling super.  It does not help.

Curiously also and by implication in contrast with what Graham stated, I'm seeing performKeyEquivalent gets called from within my application-level override of sendEvent, where I added code conditional on [event type] == NSKeyDown prior to [super sendEvent...].  I use that code now just to log the occurrence.  But previously I had tried updating menus there, which also did not work.

So to state the obvious, if per Graham, "key equivalents are pulled out before -keyDown" but if keyDown is what calls performKeyEquivalent, then how could performKeyEquivalent help?  In fact it doesn't.  But I also see Graham mentioning views as possible places to trap performKeyEquivalent and I also wonder whether there is something about that that I'm missing.



On 11/24/19 2:58:17 PM, Graham Cox wrote:
The menu key equivalents are pulled out before -keyDown: is called. You can override that event in -performKeyEquivalent:, a methof of NSResponder (and therefore views, etc). You can probably call your menu update method and then call super to handle the key equivalent.
On 25 Nov 2019, at 8:28 am, Kurt Bigler via Cocoa-dev <cocoa-dev@...> wrote:

The last possible moment for key equivalents is a keyDown event. Unfortunately Cocoa doesn't seem to let me catch this event and act on it to update menus prior to key equivalent processing.

-Kurt Bigler

Join to automatically receive all group messages.