1 /*
2  * Copyright (c) 2010, 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 import javax.swing.*;
25 import java.awt.*;
26 import java.awt.event.ComponentAdapter;
27 import java.awt.event.ComponentEvent;
28 import java.awt.event.MouseAdapter;
29 import java.awt.event.MouseEvent;
30 import java.awt.geom.Area;
31 import java.awt.geom.GeneralPath;
32 import java.awt.geom.Rectangle2D;
33 
34 /*
35  * @test
36  * @key headful
37  * @summary Check if a window set with shape clips the contents
38  * Test Description: Check if PERPIXEL_TRANSPARENT translucency type is supported
39  *      by the current platform. Proceed if it is supported. Apply different types
40  *      of shapes on a Window which contains some awt components. Shape should be
41  *      applied in such a way that some components are partially clipped off. Check
42  *      if the components appear only partially and events work correctly for those
43  *      components - i.e. events occur only on the areas which appear and do not
44  *      occur on the clipped off areas. Events should be checked by clicking on the
45  *      visible and clipped regions. Repeat this for Window, Dialog and Frame.
46  * Expected Result: If PERPIXEL_TRANSPARENT translucency type is supported, clicking
47  *      on clipped region should deliver the event to the background (it should be
48  *      another Window behind the test window)
49  * @author mrkam
50  * @library /lib/client
51  * @build Common ExtendedRobot
52  * @run main SetShapeAndClickSwing
53  */
54 
55 public class SetShapeAndClickSwing extends Common {
56 
57     Component south, center, north;
58 
main(String[] args)59     public static void main(String[] args) throws Exception {
60         if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT))
61             for (Class<Window> windowClass: WINDOWS_TO_TEST)
62                 new SetShapeAndClickSwing(windowClass).doTest();
63     }
64 
SetShapeAndClickSwing(Class windowClass)65     public SetShapeAndClickSwing(Class windowClass) throws Exception {
66         super(windowClass);
67     }
68 
69     @Override
initBackgroundFrame()70     public void initBackgroundFrame() {
71         super.initBackgroundFrame();
72         background.addMouseListener(new MouseAdapter() {
73             @Override
74             public void mouseClicked(MouseEvent e) {
75                 clicked |= 1 << 0;
76             }
77         });
78     }
79 
80     @Override
createSwingComponents()81     public void createSwingComponents() {
82         window.setSize(200,200);
83         window.setLayout(new BorderLayout());
84 
85         south = new JLabel("South");
86         south.addMouseListener(new MouseAdapter() {
87             @Override
88             public void mouseClicked(MouseEvent e) {
89                 clicked |= 1 << 3;
90             }
91         });
92         window.add(south, BorderLayout.SOUTH);
93 
94         center = new JList();
95         center.addMouseListener(new MouseAdapter() {
96             @Override
97             public void mouseClicked(MouseEvent e) {
98                 clicked |= 1 << 2;
99             }
100         });
101         window.add(center, BorderLayout.CENTER);
102 
103         north = new JTextField("North");
104         north.addMouseListener(new MouseAdapter() {
105             @Override
106             public void mouseClicked(MouseEvent e) {
107                 clicked |= 1 << 1;
108             }
109         });
110         window.add(north, BorderLayout.NORTH);
111     }
112 
113     @Override
doTest()114     public void doTest() throws Exception {
115 
116         robot.waitForIdle();
117 
118         Point wls = window.getLocationOnScreen();
119         Point ls;
120         int y;
121         ls = north.getLocationOnScreen();
122         checkClick(ls.x + north.getWidth() / 3, ls.y + north.getHeight() / 2, 1);
123 
124         ls = center.getLocationOnScreen();
125         checkClick(ls.x + center.getWidth() * 3 / 4, ls.y + center.getHeight() * 3 / 4, 2);
126 
127         ls = south.getLocationOnScreen();
128         checkClick(ls.x + south.getWidth() * 2 / 3, ls.y + south.getHeight() / 2, 3);
129 
130         ls = center.getLocationOnScreen();
131         checkClick(ls.x + center.getWidth() / 4, ls.y + center.getHeight() / 4, 2);
132 
133         ls = north.getLocationOnScreen();
134         y = ls.y + north.getHeight() / 2;
135         checkClick(wls.x + 200 - (y - wls.y), y, 0);
136 
137         EventQueue.invokeAndWait(window::toFront);
138         robot.waitForIdle();
139 
140         ls = center.getLocationOnScreen();
141         y = ls.y + center.getHeight() / 2;
142         checkClick(wls.x + 200 - (y - wls.y), y, 0);
143 
144         EventQueue.invokeAndWait(window::toFront);
145         robot.waitForIdle();
146 
147         ls = south.getLocationOnScreen();
148         y = ls.y + south.getHeight() / 2;
149         checkClick(wls.x + 200 - (y - wls.y), y, 0);
150 
151         EventQueue.invokeAndWait(window::dispose);
152         EventQueue.invokeAndWait(background::dispose);
153 
154         robot.waitForIdle();
155     }
156 
157     @Override
applyShape()158     public void applyShape() {
159         Area shape = new Area(new Rectangle2D.Float(0, 0, 200, 200));
160         GeneralPath gp;
161         gp = new GeneralPath();
162         gp.moveTo(190, 0);
163         gp.lineTo(200, 0);
164         gp.lineTo(200, 10);
165         gp.lineTo(10, 200);
166         gp.lineTo(0, 200);
167         gp.lineTo(0, 190);
168         gp.closePath();
169         shape.subtract(new Area(gp));
170 
171         window.setShape(shape);
172     }
173 }
174