Is it impossible to know when your plugin is brought to the front or gains focus?

It would seem so.

  • AudioProcessorEditor::broughtToFront() (inherited from Component) - never called
  • AudioProcessorEditor::focusGained() (inherited from Component) - never called

Am I missing anything?

1 Like
1 Like

Thanks, I had seen that older post and hoped that someone since then had found something. Maybe I should have asked in that one…

It seems a glaring oversight to me that the VST3 spec does not include a way for a plugin to be notified when its window is brought to the front!

I don’t think VST3 is to blame here. The AudioProcessorEditor gains focus, it seems it just neglects - like Roli - that there might be someone waiting for a notification.

I would love to hear a comment from one of the JUCE programmers as to why this is not possible.

(BTW, Roli doesn’t own JUCE anymore, PACE does…)

I think neither Component::focusGained nor Component::broughtToFront is really suitable to receive notifications about host window focus.

focusGained should be called when the component gains keyboard focus. However, it’s possible for the host window to gain focus without giving keyboard focus to the plugin editor. Most hosts place additional keyboard-focusable widgets such as bypass buttons and preset selectors in their plugin windows. On a related note, I don’t think the plugin view should steal keyboard focus when its window is brought to the front, as the user might want to interact with other widgets in the window using the keyboard.

broughtToFront should be called when the component is moved to the front relative to its siblings. However, in the case that the plugin window is focused, the window will move to the front relative to other top-level windows. The order of the plugin editor will not change relative to its immediate siblings. As a result, I don’t think broughtToFront should receive window focus notifications.

To add proper support for this feature, I think we’d need to expand the (already overly-large) interface of Component with additional topLevelWindow(Gained|Lost)Focus functions. This would add a lot of complexity for what seems to be quite a niche use-case.

Additionally, depending on what you’re trying to do, detecting the focus of the top-level window may not behave as expected in all cases. A host is allowed to host multiple plugin views in the same editor window, so it’s possible that multiple editors might receive topLevelWindowGainedFocus notifications simultaneously if they were all shown in the same top-level window.

At the moment, this seems like quite a specialised feature, and I’m not convinced that it’s useful enough to be worth the implementation and ongoing maintentance cost. I’m open to arguments to the contrary, though.

It would be interesting to gain some insight into how niche this use case is. Based on data from this and another thread it seems like 5 users have found themselves needing to know if the plugin window has gained/lost focus.

My particular usecase was that (for better or worse) we required separate (optional) windows for our plugin, these needed to have the always on top setting, else they would get hidden behind certain other windows in certain DAWs, but this meant once the main plugin window lost focus that these additional windows hung around on top of everything else. I desperately wanted to stop that happening depending on if the main window was focused or not.

I suppose a FR would be the best way to gauge how many people would like it (useless to me though since I’ve exhausted all my votes, not even sure what on now!)

I knew there would be some reason why this isn’t just a “simple” addition :joy:

Opening a FR is a good idea, as this would help to gauge interest in adding a feature which would allow listening to the focus state of the host window.

If you don’t need to listen to the plugin window, and just need to know whether or not the editor (or one of its subcomponents) has focus, would something like this work for your use-case?

  • Override focusOfChildComponentChanged on your plugin editor
  • Query hasKeyboardFocus to determine the focus state of the editor
1 Like

The use case (for me at least) is that there is a bug on macOS Big Sur currently when a plugin is in the background and then comes to foreground, the UI is black until a repaint is called. If the black ui bug was fixed, then I wouldn’t need this feature.

I’ve not encountered this issue. Does it affect all plugins, or just JUCE plugins? If it’s JUCE-only, and you provide a set of steps to reproduce the issue (maybe in a new thread, to stop this one getting off-track), I’ll try to fix the problem.

There is a thread here. Can be reproduced with the juce demo runner: Repaint issue with JUCE_COREGRAPHICS_DRAW_ASYNC=1

The problem with this (correct me if I’m wrong), is that when your plugin window is brought to the front (I’m testing in the JUCE AudioPluginHost), the currentFocusedComponent is set to NULL. You can see that using a focusChangeListener.

Unlike a JUCE GUI App, where when the MainWIndow of your app (a DocumentWindow) is brought to the front, all sorts of stuff is done to restore the focus to what was the last focused component.

I’m working on both types of projects from a single source base, but my standalone app is a real JUCE GUI app, and not my plugin wrapped in a standalone. So I was looking to make the behavior a little more consistent between the two.

My use case was (going to be) trying to determine when the plugin window came to the front, so that I could target the next tab key press at a specific component, rather than having to have the user click inside the content in order to make tabbing work.

I’m not sure focusOfChildComponentChanged() would be of any use for this…

EDIT: BTW, please see this for a related request:

1 Like

I wanted to look into this. It seems this is completely unreliable as a method of determine the “front” status of your plugin window.

I built a simple plugin (VST3, AU) to test this a bit (with a few child components, and a message box to print out the results of calls to various focus related functions). You can download the “FocusTest” project here:

FocusTest.zip (35.4 KB)

I implemented the following functions in the AudioProcessorEditor component:

  • focusGained()
  • focusLost()
  • focusOfChildComponentChanged()
  • globalFocusChanged()
  • broughtToFront() <— never gets called, but it’s in there

It inherits from AsyncUpdater to display the currentlyFocusedComponent when the editor is launched.
“Plugin Editor requires Keyboard Focus” is checked in the Projucer project (although my understanding is this only has an effect on VST and AU, not VST3).

I tested JUCE’s AudioPluginHost (APH) on Mac and Windows, Reaper on Mac and Windows, and Logic on Mac. Of course, this is just a small sampling of hosts, but it shows how different they are.

Reaper Windows: this is the only one I tried that seems to work logically, where selecting another window unfocuses your plugin, while reselecting your plugin’s title bar refocuses the last focused component (and you get a focusOfChildComponentChanged()).

Conclusion: results are inconsistent from host to host, and platform to platform. There is no accurate way to deduce a change in the frontmost position of your plugin editor window from currently available methods. Which is why we need this:

Results of the tests (spreadsheet also included in download):

2 Likes

For this use case, you could keep track of the last focused component yourself. I’m doing this:

class MyEditor : juce::FocusChangeListener // etc
{
    bool focusWasLost{};
    juce::WeakReference<juce::Component> lastFocused{};

public:
    void globalFocusChanged (juce::Component* c)
    {
        if (c == this)
        {
            if (std::exchange (focusWasLost, false) && lastFocused.get() && lastFocused->isShowing())
                lastFocused->grabKeyboardFocus();
            else lastFocused = c;
        }
        else if (isParentOf (c))
        {
            focusWasLost = false;
            lastFocused = c;
        }
        else focusWasLost = true;
    }
}

When the editor gets the focus (however that happens) after having lost it to a non-child, it passes it to the last focused component (a child or the editor itself). You still need to click inside in most hosts, but at least you can click on the background and restore the tab order position.

Thanks, but I don’t want to have to click inside the plugin in order to restore focus to some component. I would like to know that the plugin window has come to the front, and then I would restore focus to a particular component (and not necessarily the lastFocused component). If the user brings it to the front by clicking inside it, well then something gets focused, that’s not an issue. What is an issue is when the user brings the plugin window to the front by clicking on the title bar, and NOTHING happens and there is no focus.

It’s ok, I was just giving an alternative. I tend to agree with Reuk on the rest -the plugin window is not owned by the plugin, what each host does with it is their design choice, for better or worse. In this case, even if you had a way to know that the window has come to the front, you’d have to steal the focus, and you’d lose it again if the title bar is clicked. I still think it would be good to have these methods, for something like Asimilon’s case, which seems hard to solve otherwise.

Another use case, is that if you are using a MenuBarComponent in your plugin, with an ApplicationCommandTarget and keyboard shortcuts, when your window is brought to the front by clicking in the titlebar, there is no focus and keyboard shortcuts do not work until you first click somewhere inside the window. If you could get a notification that the window has come to the front, you could focus the menubar and enable the keyboard shortcuts.