grabKeyboardFocus(), wantsKeyboardFocus()

Hi, this has had me stumped for the last couple of days.

Here’s what I want to achieve:

I have a parent component as a “canvas” on which child components can be placed. If I dynamically create a new child component, it should be brought to the front, and given keyboard focus. The component with keyboard focus needs to be highlighted (with for example a red rectangle, in its paint() method). Clicking on child components should also bring them to the front and give them keyboard focus and also highlight them.

I have tried so many things, but have failed to get it to work properly yet. It often seems that I need to click twice, or actually move the child components to get them to respond properly.

I have tried so many different things with focusChangedListener, setWantsKeyboardFocus(), grabKeyboardFocus; explicitly setting focus order, setting timers to check that components are showing…etc
But almost always seem to need to click twice or move the child components before the highlight gets drawn on the correct component, and that component receives keyboard focus.

I’ve implemented an example of my understanding what you described here:

2 Likes

Thank you very much for taking the time to do that eyalamir, It works almost perfectly.

I now have it working in all except ONE scenario: I want to create widgets by dragging and dropping files onto the canvas. It seems when I dynamically create widgets that way, the keyboard focus is still given to the previous widget.

From this small change to your canvas component to enable file drag and drop to create widgets, you will see what i mean:
Canvas.h (1.1 KB)

My guess is that the whole app window goes out of focus when drag and drop occurs, and this in turn messes with the keyboard focus.

Yes, that’s the OS getting the app out of focus, I don’t think it’s something can be done in JUCE (but maybe I’m wrong).

You probably can store the highlighted component and on a timer bring the focus back.

1 Like

Thank you again. Have got it all working now (I Hope!)

Had to use a timer in my widgets to check the focus bool against the actual hasKeyboardFocus() result.

void Widget::timerCallback()
{
    if (widgetFocus && !hasKeyboardFocus(true))
    {
        grabKeyboardFocus();
        if (hasKeyboardFocus(true))
        {
            stopTimer();
        }
    }
}
1 Like