Preventing controls gaining focus with KeyboardFocusTraverser


#1

I'm working on a plugin using juce 3.0.1 (AAX version at present) that allows keyboard input into value fields that we want to prevent from assigning keyboard focus to any controls after editing so that all ProTools key commands work after edits are made.

I first tried calling setWantsKeyboardFocus(false) on all the controls in my component and setFocusContainer(false) on the component containing the controls, but the tab key still gives those controls focus. I then created this custom KeyboardFocusTraverser class:

class KeyboardFocusController : public KeyboardFocusTraverser
{
public:
    juce::Component* getNextComponent(juce::Component* current) { return NULL; }
    juce::Component* getPreviousComponent(juce::Component* current) { return NULL; }
    juce::Component* getDefaultComponent(juce::Component* parent) { return NULL; }
};

This almost does exactly what I need, except that after completing an edit in a TextEditor control, keyboard focus jumps to one of the ComboBox controls, which then responds to the cursor and Enter keystrokes rather than passing them to ProTools. It acts the same whether the edit field is completed with either the tab or enter key. The tab key now is passed to the host unless a TextEditor control is active (it accepts the edit then which is the behavior I'm looking for) but I haven't found a way to prevent the ComboBox from gaining focus, which prevents the Enter key from being passed to the host.

Is there something special about ComboBox controls and key focus, and does anyone have ideas how to get around this?

Thanks!

-
rundio

 


#2

I too had problems with JUCE tip AAX plug-in ComboBoxes stealing keystrokes from Pro Tools even when nominally out of focus. After reading about others having issues some time ago (http://www.juce.com/forum/topic/minor-keyboard-focus-issues) and mucking around quite a bit with setEditable() and setWantsKeyboardFocus() myself to no avail, I cut bait and simply created a derived class ComboBox_IgnoreKeys that always returns false in keyPressed().  It means users can't use the arrows or enter key to manipulate the popup, but since they have to click with a mouse to open it anyway in my plug, that was a tradeoff I was willing to make.  Here's the quick and dirty class header which anyone is free to use, just drop it in a file ie. ComboBox_IgnoreKeys.h and replace ComboBox with ComboBox_IgnoreKeys in your PluginEditor.
 

/*
 *  ComboBox_IgnoreKeys.h
 */

#ifndef ComboBox_IgnoreKeys_H
#define ComboBox_IgnoreKeys_H

#include "../JuceLibraryCode/JuceHeader.h"

using namespace juce;

//==============================================================================

class ComboBox_IgnoreKeys : public ComboBox
{
public:
    ComboBox_IgnoreKeys (const String& componentName = String::empty): ComboBox(componentName) {};
    ~ComboBox_IgnoreKeys() {};

    // Don't steal keypresses - setEditable is borked and unreliable
    bool keyPressed (const KeyPress&) override {return false;};

public:
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBox_IgnoreKeys);
};

#endif //ComboBox_IgnoreKeys_H

#3

Thank you very much, this works great!