Best practice for hidden keyboard shortcuts

  • I'm looking to provide hidden keyboard shortcuts in my cocoa app.
    Actually this was already working in Tiger but the technique I was
    employing seems to no longer work in Leopard.

    In Tiger I was using a hidden popup button. Worked great, but no more.
    I've search the lists for possible solutions but have not come across
    a concrete answer. Recommendations include using Carbon's
    kMenuAttrHidden, Leopard's new hidden menu attribute,
    performKeyEquivalent: and overriding NSApp's sendEvent:

    I don't mind delving into Carbon, but to get a MenuRef for a NSMenu I
    am required to use an undocumented method. I'd like to avoid that if i
    can. Leopard's new hidden menu attribute looks promising, but hiding a
    menu removes the key equivalents for its menu items, defeating my
    purpose. performKeyEquivalent would be great, but documentation says
    you are limited to key equivalents that have no modifiers or the shift
    modifier only. I'd like to use control and option as well.

    This leaves me with overriding NSApp's sendEvent: . My current
    thinking is to check in that method for key events with the cmd
    modifier and ask the main window or window's delegate if it would like
    to handle a key equivalent. This is similar to the
    performKeyEquivalent: route except I can now use additional modifiers.
    If the window or delegate doesn't care to handle the event, I simply
    call super's sendEvent:

    Before I go through with this implementation I was just wondering if
    all of that sounds right or if there is a better way to do it.

    -Phil
  • Phil,

    I had written a class of view which implements arbitrary key
    equivalents (with some exceptions, like cmd-tab) by overriding both -
    performKeyEquivalent: and -keyDown: -- I don't recall the specifics,
    but I know that both methods are called in different circumstances...

    dave

    On 2-Nov-07, at 9:20 AM, Philip Dow wrote:

    > I'm looking to provide hidden keyboard shortcuts in my cocoa app.
    > Actually this was already working in Tiger but the technique I was
    > employing seems to no longer work in Leopard.
    >
    > In Tiger I was using a hidden popup button. Worked great, but no
    > more. I've search the lists for possible solutions but have not come
    > across a concrete answer. Recommendations include using Carbon's
    > kMenuAttrHidden, Leopard's new hidden menu attribute,
    > performKeyEquivalent: and overriding NSApp's sendEvent:
    >
    > I don't mind delving into Carbon, but to get a MenuRef for a NSMenu
    > I am required to use an undocumented method. I'd like to avoid that
    > if i can. Leopard's new hidden menu attribute looks promising, but
    > hiding a menu removes the key equivalents for its menu items,
    > defeating my purpose. performKeyEquivalent would be great, but
    > documentation says you are limited to key equivalents that have no
    > modifiers or the shift modifier only. I'd like to use control and
    > option as well.
    >
    > This leaves me with overriding NSApp's sendEvent: . My current
    > thinking is to check in that method for key events with the cmd
    > modifier and ask the main window or window's delegate if it would
    > like to handle a key equivalent. This is similar to the
    > performKeyEquivalent: route except I can now use additional
    > modifiers. If the window or delegate doesn't care to handle the
    > event, I simply call super's sendEvent:
    >
    > Before I go through with this implementation I was just wondering if
    > all of that sounds right or if there is a better way to do it.
    >
    > -Phil
    >
  • Ah, I failed to mention that the views upon which the key equivalents
    act are not necessarily in focus, so they won't receive the keyDown
    events.

    -Phil

    On Nov 2, 2007, at 9:49 AM, David Spooner wrote:

    > Phil,
    >
    > I had written a class of view which implements arbitrary key
    > equivalents (with some exceptions, like cmd-tab) by overriding both -
    > performKeyEquivalent: and -keyDown: -- I don't recall the specifics,
    > but I know that both methods are called in different circumstances...
    >
    > dave
    >
    >
    > On 2-Nov-07, at 9:20 AM, Philip Dow wrote:
    >
    >> I'm looking to provide hidden keyboard shortcuts in my cocoa app.
    >> Actually this was already working in Tiger but the technique I was
    >> employing seems to no longer work in Leopard.
    >>
    >> In Tiger I was using a hidden popup button. Worked great, but no
    >> more. I've search the lists for possible solutions but have not
    >> come across a concrete answer. Recommendations include using
    >> Carbon's kMenuAttrHidden, Leopard's new hidden menu attribute,
    >> performKeyEquivalent: and overriding NSApp's sendEvent:
    >>
    >> I don't mind delving into Carbon, but to get a MenuRef for a NSMenu
    >> I am required to use an undocumented method. I'd like to avoid that
    >> if i can. Leopard's new hidden menu attribute looks promising, but
    >> hiding a menu removes the key equivalents for its menu items,
    >> defeating my purpose. performKeyEquivalent would be great, but
    >> documentation says you are limited to key equivalents that have no
    >> modifiers or the shift modifier only. I'd like to use control and
    >> option as well.
    >>
    >> This leaves me with overriding NSApp's sendEvent: . My current
    >> thinking is to check in that method for key events with the cmd
    >> modifier and ask the main window or window's delegate if it would
    >> like to handle a key equivalent. This is similar to the
    >> performKeyEquivalent: route except I can now use additional
    >> modifiers. If the window or delegate doesn't care to handle the
    >> event, I simply call super's sendEvent:
    >>
    >> Before I go through with this implementation I was just wondering
    >> if all of that sounds right or if there is a better way to do it.
    >>
    >> -Phil
    >>
    >

    Journler Developer
    <phil...>
  • You may be able to implement the methods in a higher-level responder;
    this leaves you with the problem of how to distribute the messages to
    the appropriate views, but you will also have to do that if you take
    the -sendEvent: route...

    dave

    On 2-Nov-07, at 11:38 AM, Philip Dow wrote:

    > Ah, I failed to mention that the views upon which the key
    > equivalents act are not necessarily in focus, so they won't receive
    > the keyDown events.
    >
    > -Phil
    >
    > On Nov 2, 2007, at 9:49 AM, David Spooner wrote:
    >
    >> Phil,
    >>
    >> I had written a class of view which implements arbitrary key
    >> equivalents (with some exceptions, like cmd-tab) by overriding both
    >> -performKeyEquivalent: and -keyDown: -- I don't recall the
    >> specifics, but I know that both methods are called in different
    >> circumstances...
    >>
    >> dave
    >>
  • If you all don't mind I'm going to post what I've done. I've seen this
    show up so many times, and this solution, if it isn't unknowingly
    screwing things up, feels clean.

    In your custom subclass of NSApplication (everybody's doing it!)
    override sendEvent: Can you feel the power!?

    - (void)sendEvent:(NSEvent *)anEvent
    {
    // is this a keyboard equivalent event ?
    // if so does the key window respond to custom keyboard equivalents?
    if ( [anEvent type] == NSKeyDown && ( [anEvent modifierFlags] &
    NSCommandKeyMask ) && [[[self keyWindow] windowController]
    respondsToSelector:@selector(performCustomKeyEquivalent:)] )
    {
      // if the key window doesn't have anything to do, pass the message
    onto super
      if ( ![[[self keyWindow] windowController]
    performSelector:@selector(performCustomKeyEquivalent:)
    withObject:anEvent] )
      [super sendEvent:anEvent];
    }
    else
    {
      // let super handle anything else
      [super sendEvent:anEvent];
    }
    }

    sendEvent is asking the frontmost window if its window controller
    responds to custom key events. There I am implementing
    performCustomKeyEquivalent:(NSEvent*)anEvent, where I check the
    charactersIgnoringModifiers and modifierFlags to decide how to act.

    In truth a view controller responsible for managing the window's
    actual content does that. The window controller is just passing the
    message on, but I suppose you could do whatever you want.

    Application wide hidden keyboard shortcuts. I guess keyboard
    equivalents aren't that hard.

    -Phil

    On Nov 2, 2007, at 11:21 AM, David Spooner wrote:

    >
    > You may be able to implement the methods in a higher-level
    > responder; this leaves you with the problem of how to distribute the
    > messages to the appropriate views, but you will also have to do that
    > if you take the -sendEvent: route...
    >
    > dave
    >
    > On 2-Nov-07, at 11:38 AM, Philip Dow wrote:
    >
    >> Ah, I failed to mention that the views upon which the key
    >> equivalents act are not necessarily in focus, so they won't receive
    >> the keyDown events.
    >>
    >> -Phil
    >>
    >> On Nov 2, 2007, at 9:49 AM, David Spooner wrote:
    >>
    >>> Phil,
    >>>
    >>> I had written a class of view which implements arbitrary key
    >>> equivalents (with some exceptions, like cmd-tab) by overriding
    >>> both -performKeyEquivalent: and -keyDown: -- I don't recall the
    >>> specifics, but I know that both methods are called in different
    >>> circumstances...
    >>>
    >>> dave
    >>>
    >

    Journler Developer
    <phil...>
  • What I've been doing since Mac OS X 10.0 is this:

    Instanciate an NSMenu in your main nib but don't add it to the menu
    bar, have an outlet to it in your NSApplication subclass
    (_hiddenMenu).  Implement sendEvent: like this

    - (void)sendEvent:(NSEvent *)i_event
    {
    if ( [i_event type] == NSKeyDown and
      ([i_event modifierFlags] & NSCommandKeyMask) != 0 and
      [_hiddenMenu performKeyEquivalent: i_event] )
    {
      return;
    }
    else
    {
      [super sendEvent: i_event];
    }
    }

    This let you edit your hidden shortcut and connect their action like
    normal menu items.

    Sandy.

    Le 07-11-03 à 13:58, Philip Dow a écrit :

    > If you all don't mind I'm going to post what I've done. I've seen
    > this show up so many times, and this solution, if it isn't
    > unknowingly screwing things up, feels clean.
    >
    > In your custom subclass of NSApplication (everybody's doing it!)
    > override sendEvent: Can you feel the power!?
    >
    > - (void)sendEvent:(NSEvent *)anEvent
    > {
    > // is this a keyboard equivalent event ?
    > // if so does the key window respond to custom keyboard equivalents?
    > if ( [anEvent type] == NSKeyDown && ( [anEvent modifierFlags] &
    > NSCommandKeyMask ) && [[[self keyWindow] windowController]
    > respondsToSelector:@selector(performCustomKeyEquivalent:)] )
    > {
    > // if the key window doesn't have anything to do, pass the message
    > onto super
    > if ( ![[[self keyWindow] windowController]
    > performSelector:@selector(performCustomKeyEquivalent:)
    > withObject:anEvent] )
    > [super sendEvent:anEvent];
    > }
    > else
    > {
    > // let super handle anything else
    > [super sendEvent:anEvent];
    > }
    > }
    >
    > sendEvent is asking the frontmost window if its window controller
    > responds to custom key events. There I am implementing
    > performCustomKeyEquivalent:(NSEvent*)anEvent, where I check the
    > charactersIgnoringModifiers and modifierFlags to decide how to act.
    >
    > In truth a view controller responsible for managing the window's
    > actual content does that. The window controller is just passing the
    > message on, but I suppose you could do whatever you want.
    >
    > Application wide hidden keyboard shortcuts. I guess keyboard
    > equivalents aren't that hard.
    >
    > -Phil
    >
    > On Nov 2, 2007, at 11:21 AM, David Spooner wrote:
    >
    >>
    >> You may be able to implement the methods in a higher-level
    >> responder; this leaves you with the problem of how to distribute
    >> the messages to the appropriate views, but you will also have to do
    >> that if you take the -sendEvent: route...
    >>
    >> dave
    >>
    >> On 2-Nov-07, at 11:38 AM, Philip Dow wrote:
    >>
    >>> Ah, I failed to mention that the views upon which the key
    >>> equivalents act are not necessarily in focus, so they won't
    >>> receive the keyDown events.
    >>>
    >>> -Phil
    >>>
    >>> On Nov 2, 2007, at 9:49 AM, David Spooner wrote:
    >>>
    >>>> Phil,
    >>>>
    >>>> I had written a class of view which implements arbitrary key
    >>>> equivalents (with some exceptions, like cmd-tab) by overriding
    >>>> both -performKeyEquivalent: and -keyDown: -- I don't recall the
    >>>> specifics, but I know that both methods are called in different
    >>>> circumstances...
    >>>>
    >>>> dave
    >>>>
    >>
    >
    >
    > Journler Developer
    > <phil...>
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today