ShapedTranslucentWindowClick.java revision 14851:980da45565c8
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
24import java.awt.*;
25import java.awt.event.*;
26import java.awt.geom.Area;
27import java.awt.geom.GeneralPath;
28import java.awt.geom.Rectangle2D;
29import java.util.BitSet;
30
31/*
32 * @test
33 * @key headful
34 * @summary Check if a translucent shaped window trigger events correctly.
35 *
36 * Test Description: Check if TRANSLUCENT and PERPIXEL_TRANSPARENT traslucency
37 *      types are supported on the current platform. Proceed if both are
38 *      supported. Create a window with some components in it and a shape
39 *      applied. Apply the shape such that some components are partially
40 *      clipped. Set an opacity value less than 1. Check if the components
41 *      behave correctly on mouse and key events. Do this test for awt Window.
42 * Expected Result: Mouse and key events must work correctly. Only that portion
43 *      of a component within the shape should trigger events. Key events
44 *      should be tested for focus events and TextField/TextArea.
45 *
46 * @author mrkam
47 * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
48 * @library ../../../../lib/testlibrary
49 * @build Common ExtendedRobot
50 * @run main ShapedTranslucentWindowClick
51 */
52
53public class ShapedTranslucentWindowClick extends Common {
54
55    Component south, center, north;
56
57    volatile BitSet backgroundFlags = new BitSet(11);
58    volatile BitSet southFlags = new BitSet(11);
59    volatile BitSet centerFlags = new BitSet(11);
60    volatile BitSet northFlags = new BitSet(11);
61    static BitSet reference = BitSet.valueOf(new long[] {2047}); // 111 1111 1111
62
63    public static void main(String[] ignored) throws Exception{
64        if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT) &&
65                checkTranslucencyMode(GraphicsDevice.WindowTranslucency.TRANSLUCENT))
66            new ShapedTranslucentWindowClick(Window.class).doTest();
67    }
68
69    public ShapedTranslucentWindowClick(Class windowClass) throws Exception {
70        super(windowClass);
71        addListeners(south, southFlags);
72        addListeners(center, centerFlags);
73        addListeners(north, northFlags);
74        addListeners(background, backgroundFlags);
75    }
76
77    @Override
78    public void initGUI() {
79
80        window = new Window(background);
81        south = new Button("South Button");
82        center = new TextArea("Center Text Area");
83        north = new TextField("North Text Field");
84
85        window.setLocation(250, 250);
86        window.setPreferredSize(new Dimension(200, 200));
87        window.setOpacity(0.7f);
88        applyShape();
89        window.setLayout(new BorderLayout());
90
91        window.add(south, BorderLayout.SOUTH);
92        window.add(center, BorderLayout.CENTER);
93        window.add(north, BorderLayout.NORTH);
94
95        window.pack();
96        window.setVisible(true);
97        window.toFront();
98
99        System.out.println("Checking " + window.getClass().getName() + "...");
100    }
101
102    @Override
103    public void doTest() throws Exception {
104
105        robot.waitForIdle();
106        robot.mouseMove(background.getLocationOnScreen().x+50, background.getLocationOnScreen().y+50);
107        robot.waitForIdle();
108        robot.click();
109
110        Point wls = window.getLocationOnScreen();
111        Point ls;
112        int y;
113
114        robot.waitForIdle();
115
116        ls = north.getLocationOnScreen();
117        checkClickAndType(ls.x + north.getWidth() / 3, ls.y + north.getHeight() / 2, northFlags);
118
119        ls = center.getLocationOnScreen();
120        checkClickAndType(ls.x + center.getWidth() / 4, ls.y + center.getHeight() / 4, centerFlags);
121
122        ls = center.getLocationOnScreen();
123        checkClickAndType(ls.x + center.getWidth() * 3 / 4, ls.y + center.getHeight() * 3 / 4, centerFlags);
124
125        ls = south.getLocationOnScreen();
126        checkClickAndType(ls.x + south.getWidth() * 2 / 3, ls.y + south.getHeight() / 2, southFlags);
127
128        ls = north.getLocationOnScreen();
129        y = ls.y + north.getHeight() / 2;
130        checkClickAndType(wls.x + 200 - (y - wls.y), y, backgroundFlags);
131
132        EventQueue.invokeAndWait(window::toFront);
133        robot.waitForIdle();
134
135        ls = center.getLocationOnScreen();
136        y = ls.y + center.getHeight() / 2;
137        checkClickAndType(wls.x + 200 - (y - wls.y), y, backgroundFlags);
138
139        EventQueue.invokeAndWait(window::toFront);
140        robot.waitForIdle();
141
142        ls = south.getLocationOnScreen();
143        y = ls.y + south.getHeight() / 2;
144        checkClickAndType(wls.x + 200 - (y - wls.y), y, backgroundFlags);
145
146        EventQueue.invokeAndWait(window::dispose);
147        EventQueue.invokeAndWait(background::dispose);
148
149        robot.waitForIdle();
150    }
151
152    @Override
153    public void applyShape() {
154        Area shape = new Area(new Rectangle2D.Float(0, 0, 200, 200));
155        GeneralPath gp;
156        gp = new GeneralPath();
157        gp.moveTo(190, 0);
158        gp.lineTo(200, 0);
159        gp.lineTo(200, 10);
160        gp.lineTo(10, 200);
161        gp.lineTo(0, 200);
162        gp.lineTo(0, 190);
163        gp.closePath();
164        shape.subtract(new Area(gp));
165
166        window.setShape(shape);
167    }
168
169    void checkClickAndType(int x, int y, BitSet bits){
170        bits.clear(0, 10);
171
172        robot.mouseMove(x, y);
173        robot.click();
174        robot.dragAndDrop(MouseInfo.getPointerInfo().getLocation(), new Point(x+5, y));
175        robot.mouseWheel(1);
176        robot.waitForIdle();
177
178        robot.type('a');
179
180        robot.mouseMove(350, 50);
181        robot.waitForIdle();
182
183        //robot.delay(20*1000);
184        if (!bits.equals(reference)){
185            for( int i = 0; i < 11; i++)
186                System.err.print(( bits.get(i) ? 1 : 0 ) + ", ");
187            System.err.println();
188            throw new RuntimeException("Bit mask is not fully set: "+bits);
189        }
190    }
191
192    static void addListeners(Component component, BitSet bits) {
193        component.addMouseListener(new MouseListener() {
194            public void mouseClicked(MouseEvent e) { bits.set(0);}
195            public void mousePressed(MouseEvent e) { bits.set(1); }
196            public void mouseReleased(MouseEvent e) { bits.set(2); }
197            public void mouseEntered(MouseEvent e) { bits.set(3); }
198            public void mouseExited(MouseEvent e) { bits.set(4); }
199        });
200        component.addMouseMotionListener(new MouseMotionListener() {
201            public void mouseDragged(MouseEvent e) { bits.set(5); }
202            public void mouseMoved(MouseEvent e) { bits.set(6); }
203        });
204        component.addMouseWheelListener((e) -> bits.set(7));
205        component.addKeyListener(new KeyListener() {
206            public void keyTyped(KeyEvent e) { bits.set(8); }
207            public void keyPressed(KeyEvent e) { bits.set(9); }
208            public void keyReleased(KeyEvent e) { bits.set(10); }
209        });
210    };
211}
212