Search code examples
javamacosswingjcomboboxkey-bindings

Control-Option-Space key to open a Popup in a JCombobox in MAC with Voiceover utility


I have a JComboBox with multiple values in it. How to detect the keystroke control-option-space to open a pop-up window of JComboBox in MAC?


Solution

  • It's not clear if you want the control-option-space key binding in addition to, or instead of, the standard space key. In either case, you can evoke the aquaSpacePressed action using a binding such as the one shown below. See How to Use Key Bindings for details.

    combo.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
        KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
            KeyEvent.ALT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK),
        "aquaSpacePressed");
    

    Because this is Mac-specific, you may want to use a predicate such as this:

    System.getProperty("os.name").startsWith("Mac OS X")
    

    Addendum: The sscce below was used to test the scenario in the revised question.

    Addendum: For reasons that are not clear, enabling System Preferences > Speech > Text to Speech preempts the control-option-space binding. As an alternative, you can bind to the standard Action, "spacePopup", shown in the revised example below.

    import java.awt.EventQueue;
    import java.awt.event.KeyEvent;
    import javax.swing.JComboBox;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;
    
    /**
     * @see http://stackoverflow.com/a/13412208/230513
     */
    public class ComboKeyTest extends JPanel {
    
        public ComboKeyTest() {
            JComboBox cpmbo = new JComboBox();
            cpmbo.addItem("One");
            cpmbo.addItem("Two");
            cpmbo.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
                KeyEvent.ALT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK),
                "spacePopup");
    
            this.add(cpmbo);
        }
    
        private void display() {
            JFrame f = new JFrame("NewJavaGUI");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(this);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new ComboKeyTest().display();
                }
            });
        }
    }