EnqueueWithDialogTest.java revision 14851:980da45565c8
1/*
2 * Copyright (c) 2003, 2016, 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 * @key headful
27 * @bug 4799136
28 * @summary Tests that type-ahead for dialog works and doesn't block program
29 * @author Dmitry.Cherepanov@SUN.COM area=awt.focus
30 * @run main EnqueueWithDialogTest
31 */
32
33import java.awt.*;
34import java.lang.reflect.InvocationTargetException;
35import java.awt.event.*;
36import java.util.concurrent.CountDownLatch;
37import java.util.concurrent.TimeUnit;
38
39/*
40 * The purpose of this test is check that the type-head
41 * works correctly on Windows. That means that the key
42 * events are not delivered until a focus transfer is
43 * completed. Another regression test EnqueueWithDialogButton
44 * doesn't work on Windows because of the bug 6347235.
45 * This test workaround the bug by means of the removing
46 * button from the dialog.
47 */
48
49public class EnqueueWithDialogTest
50{
51    static Frame f;
52    static Button b;
53    static Dialog d;
54    static CountDownLatch pressLatch = new CountDownLatch(1);
55    static CountDownLatch robotLatch = new CountDownLatch(1);
56    static volatile boolean gotFocus = false;
57    static Robot robot;
58    public static void main(String args[]) throws Exception {
59        EnqueueWithDialogTest test = new EnqueueWithDialogTest();
60        test.init();
61        test.start();
62    }
63    public void init()
64    {
65        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
66                public void eventDispatched(AWTEvent e) {
67                    if (e instanceof InputEvent){
68                        System.err.println(e.toString()+","+((InputEvent)e).getWhen());
69                    }else{
70                        System.err.println(e.toString());
71                    }
72                 }
73            }, AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
74
75
76        f = new Frame("frame");
77        f.setPreferredSize(new Dimension(100,100));
78        f.setLocation(100,50);
79        b = new Button("press");
80        d = new Dialog(f, "dialog", true);
81        d.setPreferredSize(new Dimension(70,70));
82        d.pack();
83        d.addKeyListener(new KeyAdapter() {
84                public void keyPressed(KeyEvent e) {
85                    System.err.println("DIALOG pressed: should arrive after got focus");
86                    d.dispose();
87                    f.dispose();
88                    // Typed-ahead key events should only be accepted if
89                    // they arrive after FOCUS_GAINED
90                    if (gotFocus) {
91                        pressLatch.countDown();
92                    }
93                }
94            });
95        d.addFocusListener(new FocusAdapter() {
96                public void focusGained(FocusEvent e) {
97                    gotFocus = true;
98                    System.err.println("DIALOG got focus");
99                }
100            });
101        f.add(b);
102        f.pack();
103        b.addActionListener(new ActionListener() {
104                public void actionPerformed(ActionEvent e) {
105                    System.err.println(e.toString()+","+e.getWhen());
106                    System.err.println("B pressed");
107                    robotLatch.countDown();
108
109                    EventQueue.invokeLater(new Runnable() {
110                            public void run() {
111                                waitTillShown(d);
112                                EnqueueWithDialogTest.this.d.toFront();
113                                EnqueueWithDialogTest.this.moveMouseOver(d);
114                            }
115                        });
116
117                    // This will cause enqueue the following key events
118                    d.setVisible(true);
119                }
120            });
121
122    }//End  init()
123
124    public void start () throws Exception
125    {
126        try {
127            robot = new Robot();
128            //robot.setAutoDelay(50);
129        } catch (Exception e) {
130            throw new RuntimeException("Can't create robot:" + e);
131        }
132
133        f.setVisible(true);
134        waitTillShown(b);
135        System.err.println("b is shown");
136        f.toFront();
137        moveMouseOver(f);
138        robot.waitForIdle();
139        robot.delay(100);
140        makeFocused(b);
141        robot.waitForIdle();
142        robot.delay(100);
143        System.err.println("b is focused");
144
145        robot.keyPress(KeyEvent.VK_SPACE);
146        robot.keyRelease(KeyEvent.VK_SPACE);
147        System.err.println("space typed once");
148        boolean ok = robotLatch.await(1, TimeUnit.SECONDS);
149        if(!ok) {
150            throw new RuntimeException("Was B button pressed?");
151        }
152
153        robot.keyPress(KeyEvent.VK_SPACE);
154        robot.keyRelease(KeyEvent.VK_SPACE);
155        System.err.println("space typed twice");
156        robot.delay(500);
157        ok = pressLatch.await(3, TimeUnit.SECONDS);
158        if(!ok) {
159            throw new RuntimeException("Type-ahead doesn't work");
160        }
161
162    }// start()
163
164    private void moveMouseOver(Container c) {
165        Point p = c.getLocationOnScreen();
166        Dimension d = c.getSize();
167        robot.mouseMove(p.x + (int)(d.getWidth()/2), p.y + (int)(d.getHeight()/2));
168    }
169
170    private void waitTillShown(Component c) {
171        while (true) {
172            try {
173                Thread.sleep(100);
174                c.getLocationOnScreen();
175                break;
176            } catch (InterruptedException ie) {
177                ie.printStackTrace();
178                break;
179            } catch (Exception e) {
180            }
181        }
182    }
183    private void makeFocused(Component comp) {
184        if (comp.isFocusOwner()) {
185            return;
186        }
187        final Semaphore sema = new Semaphore();
188        final FocusAdapter fa = new FocusAdapter() {
189                public void focusGained(FocusEvent fe) {
190                    sema.raise();
191                }
192            };
193        comp.addFocusListener(fa);
194        comp.requestFocusInWindow();
195        if (comp.isFocusOwner()) {
196            return;
197        }
198        try {
199            sema.doWait(3000);
200        } catch (InterruptedException ie) {
201            ie.printStackTrace();
202        }
203        comp.removeFocusListener(fa);
204        if (!comp.isFocusOwner()) {
205            throw new RuntimeException("Can't make " + comp + " focused, current owner is " + KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner());
206        }
207    }
208
209static class Semaphore {
210    boolean state = false;
211    int waiting = 0;
212    public Semaphore() {
213    }
214    public synchronized void doWait() throws InterruptedException {
215        if (state) {
216            return;
217        }
218        waiting++;
219        wait();
220        waiting--;
221    }
222    public synchronized void doWait(int timeout) throws InterruptedException {
223        if (state) {
224            return;
225        }
226        waiting++;
227        wait(timeout);
228        waiting--;
229    }
230    public synchronized void raise() {
231        state = true;
232        if (waiting > 0) {
233            notifyAll();
234        }
235    }
236    public synchronized boolean getState() {
237        return state;
238    }
239}
240}
241