1 /*
  2  * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 4741926
 27  * @summary JFormattedTextField/JSpinner always consumes certain key events
 28  * @key headful
 29  * @run main bug4741926
 30  */
 31 
 32 import java.awt.Robot;
 33 import java.awt.event.ActionEvent;
 34 import java.awt.event.FocusAdapter;
 35 import java.awt.event.FocusEvent;
 36 import java.awt.event.KeyEvent;
 37 import java.util.Date;
 38 import javax.swing.AbstractAction;
 39 import javax.swing.InputMap;
 40 import javax.swing.JComponent;
 41 import javax.swing.JFormattedTextField;
 42 import javax.swing.JFrame;
 43 import javax.swing.JPanel;
 44 import javax.swing.KeyStroke;
 45 import javax.swing.SwingUtilities;
 46 
 47 public class bug4741926 {
 48 
 49     static MyFormattedTextField ftf;
 50     static JFrame fr;
 51     static Robot robot;
 52     static volatile boolean passed_enter = false;
 53     static volatile boolean passed_escape = false;
 54     static volatile boolean ftfFocused = false;
 55     static volatile boolean keyProcessed = false;
 56 
 57     public static void main(String[] args) throws Exception {
 58 
 59         try {
 60             robot = new Robot();
 61             robot.setAutoDelay(100);
 62             SwingUtilities.invokeAndWait(() -> {
 63                 fr = new JFrame("Test");
 64                 ftf = new MyFormattedTextField();
 65                 ftf.setValue("JFormattedTextField");
 66                 JPanel p = (JPanel) fr.getContentPane();
 67                 p.add(ftf);
 68                 ftf.addFocusListener(new FocusAdapter() {
 69                     public void focusGained(FocusEvent e) {
 70                         ftfFocused = true;
 71                     }
 72                 });
 73                 InputMap map = p.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
 74 
 75                 map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
 76                         "enter-action");
 77                 p.getActionMap().put("enter-action", new AbstractAction() {
 78                     public void actionPerformed(ActionEvent e) {
 79                         passed_enter = true;
 80                         keyProcessed = true;
 81                     }
 82                 });
 83                 map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
 84                         "escape-action");
 85                 p.getActionMap().put("escape-action", new AbstractAction() {
 86                     public void actionPerformed(ActionEvent e) {
 87                         passed_escape = true;
 88                         keyProcessed = true;
 89                     }
 90                 });
 91                 fr.pack();
 92                 fr.setLocationRelativeTo(null);
 93                 fr.setVisible(true);
 94             });
 95             robot.waitForIdle();
 96             robot.delay(1000);
 97             test();
 98             if (!(passed_enter && passed_escape)) {
 99                 throw new RuntimeException("JFormattedTextField consume " +
100                         "Enter/Escape key event");
101             }
102         } finally {
103             SwingUtilities.invokeAndWait(() -> {
104                 if (fr != null) {
105                     fr.dispose();
106                 }
107             });
108         }
109     }
110 
111     public static void test() throws Exception {
112         SwingUtilities.invokeAndWait(() -> {
113             ftf.requestFocus();
114         });
115         robot.delay(500);
116         doTest(KeyEvent.VK_ENTER);
117         doTest(KeyEvent.VK_ESCAPE);
118     }
119 
120     static void doTest(int keyCode) throws InterruptedException {
121         keyProcessed = false;
122         KeyEvent key = new KeyEvent(ftf, KeyEvent.KEY_PRESSED,
123                                     new Date().getTime(), 0,
124                                     keyCode,
125                                     KeyEvent.CHAR_UNDEFINED);
126         ftf.processKey(key);
127     }
128 
129     static class MyFormattedTextField extends JFormattedTextField {
130         public void processKey(KeyEvent e) {
131             processKeyEvent(e);
132         }
133     }
134 }