Midikeyboard component when pressing MenuBarModel Item or any type of menu item note doesn't turn off

I have have functions checking whether the focus is gained or lost but it makes no difference the notes hang when pressing menu bar items

How are you activating the keys? Are you clicking on them or are they coming from a midi device? I’ve tried the latter and can’t seem to reproduce your bug.

Open the plugin host demo hold a note with your computer keyboard and any vst connected and click a menu bar model button let go of the note it hangs

Same thing happens with tracktion

Fabian this is on OS X on Windows the focus lost and focus gain is being called which is a good thing,but not on OS X

OK I can re-produce this now but I’m not really sure how best to fix this (ideas welcome!). If you make the menu bar non-native (as it is on Windows) then the focus will obviously be lost correctly. I can easily have JUCE do the same for native mac menus: simply replace lines juce_mac_MainMenu.mm:731 to juce_mac_MainMenu.mm:735 with:

if (isTracking)
{
    const int numPeers = ComponentPeer::getNumPeers();
    for (int i = 0; i < numPeers; ++i)
        if (ComponentPeer* peer = ComponentPeer::getPeer (i))
            peer->handleFocusLoss();
}
else
{
    if (menuHandler->defferedUpdateRequested)
    {
        menuHandler->defferedUpdateRequested = false;
        menuHandler->menuBarItemsChanged (menuHandler->currentModel);
    }
}

However, this is probably not what most JUCE apps want as the focus of all components will always be lost when using the main menu bar. This is normal on Windows, but on mac it’s normal for the currently focused component to keep it’s focus when accessing the main menu bar. Try this on any native OS X text edit field and access the menu bar.

To be absolutely sure, I implemented a very basic “MidiKeyboardComponent” with native OS X code. Similar to JUCE’s MidiKeyboardComponent, it will reset the state if the focus is lost (see code below, it derives from NSButton). It behaves the same way as JUCE’s MidiKeyboardComponent, i.e. the keys become stuck.

I think we might need to add a new callback to JUCE which tells components if the main menu bar was accessed. What do you think?

@implementation NativeFakeMidiKeyboardComponent

- (id) initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    
    return self;
}

- (BOOL)canBecomeKeyView
{
    return YES;
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
}

- (void)keyDown:(NSEvent *)theEvent
{
    if ([[theEvent characters] isEqual:@"g"])
        [self setFloatValue:1.0f];
    else
        [super keyDown:theEvent];
}

- (void)keyUp:(NSEvent *)theEvent
{
    if ([[theEvent characters] isEqual:@"g"])
        [self setFloatValue:0.0f];
    else
        [super keyUp:theEvent];
}

- (BOOL)becomeFirstResponder
{
    return YES;
}

- (BOOL)resignFirstResponder
{
    [self setFloatValue:0.0f];
    return YES;
}
@end

Thanks for info Fabian. What ever you think is the best option.

My solution. I ended up having to make another thread for global key events setting off note on note off cause this got ride of my MenuBarModel issue as well as other focusing issues, but again it’s not full proof, and probably not practical.

I get access violations sometimes for the global KeyPress, and the thread is always on so you will hear notes playing when truly out of focus of the TopLevelWindow at least for Windows haven’t tested this OS X.

Kind of ridiculous, but my thoughts were this way nothing has to have focus and the computer midi will always work when the app is running. Maybe have a button to toggle it on and off. Still working on refining this method.

If you use the code modifications that I’ve suggested above (replacing lines juce_mac_MainMenu.mm:731 to juce_mac_MainMenu.mm:735), does this work for you in principle? Can you quickly test it without your workarounds? If this works then I’ll add this to JUCE as a flag which you can set for a component, i.e. losesFocusOnMainMenuBarAccess or something similar.

It works it stops the notes! Thanks Fabian!

OK I’ve fixed this on the develop branch. The MIDIKeyboardComponent will now work correctly.

Just a heads up. I’ve reworked the fix a bit. Adding a new flag to Component just to fix this problem seemed a bit excessive. I’ve now added a new listener callback to MenuBarModel which you can use when the user accesses the menu bar (MenuBarComponent or the Mac’s main menu bar). Look at the plugin host demo to see how to use it. Sorry for the inconvenience on this.