I'm experience some event handling issues when attempting to use arrow keys without modifiers as key equivalents for menu items in the main menu bar. The problem I'm experiencing is that the main menu bar is handling the key down event as a key equivalent event before a tableView is able to. When the tableView is the first responder, the up/down arrow keys do not change the tableView's selection but rather trigger the key equivalent in the main menu bar.
The reason for this is that the incoming keyDown
event for an arrow key is first passed to performKeyEquivalent
on the target window, which in turns passes that event down the chain. NSTableView
does not respond to this so the event bubbles back up to the application where it next dispatches it to the main menu, via performKeyEquivalent
, and thus the event is consumed.
If the main menu does not have a key equivalent, then the event goes back to the window and down the chain via keyDown
, which the tableView does respond to and correctly handles.
This is documented by Apple (more or less) in their Event Handling Guide.
Is there a proper way to handle key equivalents like arrow keys without modifiers such that they both appear in the menu item when it's being displayed, but are also properly consumed by any subviews that might handle them?
I've tried various tricks, but each one has numerous pros-and-cons:
NSMenu delegate
One can implement menuHasKeyEquivalent
but it appears that you have to implement that for the entire main menu. While you could easily filter out the arrow keys, you also have to validate every other key equivalent, which isn't very practical.
Subclass NSApplication
You can override sendEvent:
in NSApplication but the logic for keeping track of where you are in the event handling chain gets a bit hairy.
NSEvent tap
Similar to subclassing NSApplication
. Things are a bit cleaner here because I can cheat and have the event tap a bit closer to the tableView, but you're still left with a lot of logic to determine when the tap should consume the event and "force-feed" it to the tableView versus when you should let the event be handled normally.
I'm curious if anyone has any suggestions on how best to implement an arrow key as a key equivalent when no modifiers are present and a tableView might be present.
(macOS 10.11+)