1/*
2 * Copyright (c) 2011, 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 7108598 8172009
28 * @summary Container.paint/KeyboardFocusManager.clearMostRecentFocusOwner methods deadlock
29 * @library ../../regtesthelpers
30 * @author Oleg Pekhovskiy
31 * @build Util
32 * @run main PaintSetEnabledDeadlock
33 */
34
35import java.awt.Button;
36import java.awt.Color;
37import java.awt.Dimension;
38import java.awt.Frame;
39import java.awt.Graphics;
40import java.awt.GridLayout;
41import java.awt.Image;
42import java.awt.Panel;
43import java.awt.Rectangle;
44import java.awt.Robot;
45import java.awt.event.MouseAdapter;
46import java.awt.event.MouseEvent;
47import java.awt.event.WindowAdapter;
48import java.awt.event.WindowEvent;
49import test.java.awt.regtesthelpers.Util;
50
51public class PaintSetEnabledDeadlock extends Frame {
52
53    final TestPanel panel;
54    final Button button;
55
56    public static void main(String[] args) {
57        PaintSetEnabledDeadlock frame = new PaintSetEnabledDeadlock();
58        frame.setSize(200, 200);
59        frame.setVisible(true);
60
61        Robot robot = Util.createRobot();
62        robot.setAutoDelay(100);
63        robot.setAutoWaitForIdle(true);
64
65        for (int i = 0; i < 20; ++i) {
66            Util.clickOnComp(frame.panel, robot);
67            Util.clickOnComp(frame.button, robot);
68        }
69
70        boolean ret = frame.panel.stop();
71        frame.dispose();
72
73        if (!ret) {
74            throw new RuntimeException("Test failed!");
75        }
76        System.out.println("Test passed.");
77    }
78
79    public PaintSetEnabledDeadlock() {
80        super("7108598 test");
81        setLayout(new GridLayout(1, 2));
82        addWindowListener(new WindowAdapter() {
83
84            @Override
85            public void windowClosing(WindowEvent e) {
86                panel.stop();
87                System.exit(0);
88            }
89        });
90        panel = new TestPanel();
91        add(panel);
92        button = new Button("Enable");
93        button.addMouseListener(new MouseAdapter() {
94
95            @Override
96            public void mousePressed(MouseEvent e) {
97                panel.setEnabled(true);
98                panel.sync();
99                panel.repaint();
100            }
101        });
102        add(button);
103    }
104}
105
106class TestPanel extends Panel implements Runnable {
107
108    Image image = null;
109    Thread thread = null;
110    volatile boolean active = true;
111    final Object sync = new Object();
112    Panel panel = this;
113
114    public TestPanel() {
115        addMouseListener(new MouseAdapter() {
116
117            @Override
118            public void mouseReleased(MouseEvent e) {
119                synchronized (panel) {
120                    sync();
121                    panel.setEnabled(false);
122                }
123                panel.repaint();
124            }
125        });
126        thread = new Thread(this);
127        thread.start();
128    }
129
130    @Override
131    public void paint(Graphics paramGraphics) {
132        synchronized (getTreeLock()) {
133            Rectangle rect = getBounds();
134            if (image == null) {
135                image = createImage(rect.width, rect.height);
136            }
137
138            if (image != null) {
139                paramGraphics.drawImage(image, 0, 0, this);
140            }
141        }
142    }
143
144    @Override
145    public void run() {
146        while (active) {
147            try {
148                synchronized (sync) {
149                    sync.wait();
150                }
151            } catch (InterruptedException ex) {
152            }
153            if (active) {
154                draw();
155            }
156        }
157    }
158
159    public boolean stop() {
160        active = false;
161        try {
162            sync();
163            thread.join(1000);
164            if (thread.isAlive()) {
165                thread.interrupt();
166                return false;
167            }
168        } catch (InterruptedException ex) {
169            return false;
170        }
171        return true;
172    }
173
174    public void draw() {
175        synchronized (getTreeLock()) {
176            if (image != null) {
177                Graphics localGraphics = image.getGraphics();
178                Dimension size = getSize();
179                localGraphics.setColor(isEnabled() ? Color.green : Color.red);
180                localGraphics.fillRect(0, 0, size.width, size.height);
181                super.paint(localGraphics);
182                localGraphics.dispose();
183                getTreeLock().notifyAll();
184            }
185        }
186    }
187
188    public void sync() {
189        synchronized (sync) {
190            sync.notify();
191        }
192    }
193}
194