RE: Subverting the first responder chain
RE: Subverting the first responder chain
- Subject: RE: Subverting the first responder chain
- From: "Allen Smith" <email@hidden>
- Date: Fri, 28 Mar 2008 23:20:37 -0700
- Thread-topic: Subverting the first responder chain
I'm sorry, my memory seems to have gotten muddled since I investigated this
issue. Upon revisiting my old test program, I realized -[super keyDown:]
*will* ultimately trigger menu items, barring weird issues like a superclass
or higher responder that intercepts the key. Apparently I believed that the
message to super didn't work precisely because the next responder in my main
application was accidentally swallowing all keyDowns. I apologize for the
misinformation, but thank you for helping me find a bug.
Allen
-----Original Message-----
From: John Stiles [mailto:email@hidden]
Sent: Fri 3/28/2008 2:35 PM
To: Allen Smith
Cc: cocoa dev
Subject: Re: Subverting the first responder chain
I did a test and if I call
[[self nextResponder] keyDown:theEvent];
from inside the -keyDown: method, it does in fact trigger the
appropriate hotkey on the menu. (On the other hand, the documentation
recommends your technique of handing off to super here:
http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/Event
HandlingBasics/chapter_4_section_2.html
which is probably a good idea if you want your view's superclass to take
a stab at the event, but in this case I have no interest in doing that.
I want the menu bar to get the event, not any views in the middle.)
So now I "just" keep a hash table of all the application's hotkeys and
query that at the top of -keyDown:. If the pressed key matches, I punt
the event to next responder, and everything works again. It's
disappointing and ugly, but it turned out to be less code than I
thought. Walking the menus and submenus recursively to build the table
is pretty simple, and I've already got a good hash table class which I
was able to put to good use.
Maybe I'll file a bug on this...
Allen Smith wrote:
>
> On Mar 27, 2008, at 8:12 PM, John Stiles wrote:
>
>> Wow, this sounds like a disaster.
>>
>> Maybe in my -keyDown: call I can walk the menus in the menu bar and
>> call -performKeyEquivalent on all of them. It's probably not fast :|
>> I was in the process of writing code that stores the menu bar's key
>> equivalents in a hash table and checks the hash table before handling
>> -keyDown:, maybe I'll just keep doing that. It's gross but I guess
>> all the potential solutions are gross.
>
> Also be aware that if any other view in your application becomes first
> responder, it too will swallow up your key equivalents. Short of
> overriding -[NSApp sendEvent:], I don't know of universal fix. Calling
> -[super keyDown:] as another poster suggested doesn't work; by the
> time an event is routed to -keyDown:, the system no longer appears to
> consider it a candidate for menu actions.
>
> Allen
>
>>
>> Ken Thomases wrote:
>>> On Mar 27, 2008, at 7:52 PM, John Stiles wrote:
>>>
>>>> I am implementing a custom NSView subclass (actually a simple
>>>> subclass of NSOpenGLView) that implements -keyDown: in order to
>>>> respond to user typing. Typically, this works great.
>>>>
>>>> However, I have a few menu items which respond to atypical hotkeys
>>>> (e.g. one responds to "space", another to "option+X"). In this
>>>> case, I've found that the view gets a -keyDown: event, which it
>>>> dutifully handles, and the menu hotkey is never handled. I'd prefer
>>>> it if the menu action were triggered and no -keyDown: event were
>>>> generated, and that's exactly what happens with more typical menu
>>>> hotkeys like command+letters. But my view doesn't know what is in
>>>> the menubar and so, without adding a lot of ugly special-case code,
>>>> from within the view's -keyDown: handler, it would be difficult to
>>>> know whether I need to send the event to the next responder or
>>>> handle the key myself.
>>>>
>>>> Is there any elegant solution to this problem? The last thing I
>>>> want to do is reimplement hotkey handling on my own, but I can't
>>>> think of any workarounds to this issue that don't involve my view
>>>> taking on a lot of extra knowledge about what's in the menubar, or
>>>> completely hacking the responder chain in some ugly way. It seems
>>>> that I can't forward on to the next responder and then ask "did you
>>>> handle it?"-if the responder chain fails to handle the event,
>>>> apparently it just calls -noResponderFor: on the window and that is
>>>> that-there's no return value of "YES" or "NO" or anything like that.
>>>
>>> From
>>>
<http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/Hand
lingKeyEvents/chapter_6_section_4.html>:
>>>
>>>
>>> "An application routes a key-equivalent event by sending it first
>>> down the view hierarchy of a window. The global NSApplication object
>>> dispatches events it recognizes as potential key equivalents (based
>>> on the presence of modifier flags) in its sendEvent: method. It
>>> sends a performKeyEquivalent: message to the key NSWindow object.
>>> [...] If no object in the view hierarchy handles the key
>>> equivalent, NSApp then sends performKeyEquivalent: to the menus in
>>> the menu bar."
>>>
>>> So, NSApplication requires modifier flags on the key event to
>>> recognize it as a potential key equivalent. Unfortunately, I find
>>> no documented way of changing the application object's criteria for
>>> recognizing key equivalents.
>>>
>>> So, I think you'll need to subclass NSApplication, override
>>> sendEvent:, check for key events which you think should be candidate
>>> key equivalents, and pass them to the key window and then the menu
>>> bar via performKeyEquivalent:. If either returns YES, stop
>>> processing the event. Otherwise, pass the event to [super sendEvent:].
>>>
>>> Cheers,
>>> Ken
>> _______________________________________________
>>
>> Cocoa-dev mailing list (email@hidden)
>>
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden