KeyListener and the 'tab' key

I do not get keyPress callback when I press 'tab' key. Other keys seem to work fine. 

What OS?

Windows

Yes, I can confirm that behaviour in the JuceDemo. Will take a look.

Hi there,

I had a deeper look and there's nothing wrong with the keyPressed callback.

To confirm, create a new GUI Application from the Introjucer/Projucer, slap a bool keyPressed (const KeyPress&) override { /* ... */ } into the MainContentComponent, start the app, press the tab key and observe that the callback is called just fine.

It must be something else in your code, such as the focus being switched to the next component when you press tab (that's what the JuceDemo does, too). So the key press never arrives at the component you expect it to because it lost keyboard focus.

I did some debuging and I found problem.

juce_ComponentPeer.cpp

line:: 218

            if (isTab || isShiftTab)
            {
                currentlyFocused->moveKeyboardFocusToSibling (isTab);
                keyWasUsed = (currentlyFocused != Component::getCurrentlyFocusedComponent());
                if (keyWasUsed || deletionChecker == nullptr)
                    break;
            }

Perhaps there is a way to prevent this focus issue?

If you have a component that actually uses the tab key, then that code will never be reached.

Nope, not true.

Loop that goes through component parents breaks when i reaches component that accepts focus.

juce_ComponentPeer.cpp, line:: 191

 

My juce::KeyListener is implemented on DocumentWindow. 

.

What I said is definitely true, but maybe you misunderstood.

If the focused component overrides keyPressed and consumes the tab key, then the code above will not be reached - it'll stop at line 211. Otherwise, yes, it'll try to use the tab to change focus, but if you stop that happening with the methods I gave you above, then it will also get passed up to the parents.

If I call this on my main document window after all components are created then 'tab' key works.


static void SetWantsKeyboardFocusToFalse(juce::Component* comp)
{
    comp->setWantsKeyboardFocus(false);
    for (int i = 0; i < comp->getNumChildComponents(); i++)
    {
        SetWantsKeyboardFocusToFalse(comp->getChildComponent(i));
    }
}

But I'm sure this is not correct solution. Are there any side effects if I do this?

Components, that set wantsFocusFlag to true are:

juce::Button, juce::Viewport, juce::ListBox, juce::TextEditor, juce::TreeView, juce::AlertWindow and juce::TopLevelWindow

If any of these components are created then 'tab' stops working. 

 

 

That's nasty. There are a ton of methods for changing this behaviour in Component - see createFocusTraverser(), setExplicitFocusOrder(), setFocusContainer() etc

Thanks for sugestions. I overrided createFocusTraverser on my main DocumentWindow and it seems to work.

Or do you have better sugestion?


juce::KeyboardFocusTraverser* MainWindow::createFocusTraverser() //override
{
    return nullptr;
}

Yeah, that would work.