swiftcocoafirst-respondernsmenunsmenuitem

How to handle modifier keys in Cocoa menubar application


So I have a menu bar application that has a slider inside a custom view: I want the ability to press the option key while dragging to make the slider snap to increments.

Right now, everything is working... except I cannot find a single way to notify my menu app that the option key is being pressed. Here's what I've tried:

  1. NSEvent.addGlobalMonitorForEvents

    • "Note that your handler will not be called for events that are sent to your own application."
  2. NSEvent.addLocalMonitorForEvents

    • "Your handler will not be called for events that are consumed by nested event-tracking loops such as control tracking, menu tracking, or window dragging"
  3. NSApplication.shared.currentEvent

    • This dosesn't work because the flagsChanged event isn't handled by the app, so this value is set to another value (mouse button presses).
  4. flagsChanged(with event: NSEvent)

    • This doesn't get called. I've set the viewController to acceptFirstResponder as well as resigned the first responder of the view. Also, I've subclassed the view and overridden flagsChanged and that hasn't worked.
  5. I've tried creating a menu item that has a key like "s" or "p" to trigger an action. But when the "action" gets triggered, the menu bar hides...

So I'm trying to find how I can be notified when the option key is pressed. Is this possible? I can clarify if you have any questions.


Solution

  • In your custom slider view's mouseDragged method, you'd simply check the NSEvent parameter's modifierFlags to see if it contains the option key.

    --

    Since it could be interpreted that the slider is an actual NSSlider, if that's the case then the slider's control is really implemented in with an NSSliderCell, and the mouse tracking gets handed off from the view to the cell within mouseDown, so the NSSlider's mouseDragged wouldn't be called, and instead you'd have to do work in the cell's trackMouse:inRect:... method. But if you're using an NSSlider, then you'd probably simply want to use altIncrementValue.