• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
RE: Subverting the first responder chain
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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

  • Follow-Ups:
    • Re: Subverting the first responder chain
      • From: John Stiles <email@hidden>
References: 
 >Subverting the first responder chain (From: John Stiles <email@hidden>)
 >Re: Subverting the first responder chain (From: Ken Thomases <email@hidden>)
 >Re: Subverting the first responder chain (From: John Stiles <email@hidden>)
 >Re: Subverting the first responder chain (From: Allen Smith <email@hidden>)
 >Re: Subverting the first responder chain (From: John Stiles <email@hidden>)

  • Prev by Date: Re: Core Data and NSOperation
  • Next by Date: Re: machine with null serial number?
  • Previous by thread: Re: Subverting the first responder chain
  • Next by thread: Re: Subverting the first responder chain
  • Index(es):
    • Date
    • Thread