1 /* 2 * Copyright (c) 2010, 2014, 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 java.awt.*; 25 import java.awt.event.WindowAdapter; 26 import java.awt.event.WindowEvent; 27 import java.awt.event.WindowFocusListener; 28 import java.awt.geom.Area; 29 import java.awt.geom.GeneralPath; 30 import java.awt.geom.Rectangle2D; 31 import java.util.HashMap; 32 33 /* 34 * @test 35 * @bug 8013450 36 * @summary Check if the window events (Focus and Activation) are triggered correctly 37 * when clicked on visible and clipped areas. 38 * 39 * Test Description: Check if PERPIXEL_TRANSPARENT Translucency type is supported 40 * by the current platform. Proceed if it is supported. Apply different 41 * types of shapes on a Window. Make it appear with a known background. 42 * Check if mouse events which result in window-activated events are 43 * triggered only within the window's shape and not outside. Repeat this 44 * for Window, Dialog and Frame. 45 * Expected Result: If PERPIXEL_TRANSPARENT Translucency type is supported, window should 46 * gain focus and should trigger activated events only when it is clicked on the 47 * visible areas. Events should be delivered to the background window if clicked 48 * on the clipped areas. 49 * 50 * @author mrkam 51 * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com) 52 * @library ../../../../lib/testlibrary 53 * @build Common ExtendedRobot 54 * @run main FocusAWTTest 55 */ 56 57 public class FocusAWTTest extends Common { 58 59 ExtendedRobot robot; 60 int dx; 61 int dy; 62 static final int x = 20; 63 static final int y = 400; 64 65 static volatile HashMap<String, Boolean> flags = new HashMap<String, Boolean>(); 66 static { 67 flags.put("backgroundWindowActivated", false); 68 flags.put("backgroundWindowDeactivated", false); 69 flags.put("backgroundWindowGotFocus", false); 70 flags.put("backgroundWindowLostFocus", false); 71 flags.put("foregroundWindowGotFocus", false); 72 flags.put("foregroundWindowLostFocus", false); 73 flags.put("foregroundWindowActivated", false); 74 flags.put("foregroundWindowDeactivated", false); 75 } 76 77 public static void main(String[] ignored) throws Exception{ 78 if (checkTranslucencyMode(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT)) 79 for (Class<Window> windowClass: WINDOWS_TO_TEST) { 80 new FocusAWTTest(windowClass).doTest(); 81 } 82 } 83 84 public FocusAWTTest(Class windowClass) throws Exception { 85 super(windowClass); 86 this.robot = new ExtendedRobot(); 87 robot.waitForIdle(); 88 EventQueue.invokeAndWait(() -> { 89 dx = background.getX() - x; 90 dy = background.getY() - y; 91 }); 92 robot.waitForIdle(); 93 } 94 95 @Override 96 public void initBackgroundFrame() { 97 background = new Frame(); 98 background.setSize(300, 300); 99 background.setLocation(x, y); 100 background.setFocusable(true); 101 background.setFocusableWindowState(true); 102 103 background.addWindowFocusListener(new WindowFocusListener() { 104 public void windowGainedFocus(WindowEvent e) { flags.put("backgroundWindowGotFocus", true); } 105 public void windowLostFocus(WindowEvent e) { flags.put("backgroundWindowLostFocus", true); } 106 }); 107 108 background.addWindowListener(new WindowAdapter() { 109 public void windowActivated(WindowEvent e) { flags.put("backgroundWindowActivated", true); } 110 public void windowDeactivated(WindowEvent e) { flags.put("backgroundWindowDeactivated", true); } 111 }); 112 background.add(new TextArea()); 113 background.setVisible(true); 114 } 115 116 @Override 117 public void initGUI() { 118 if (windowClass.equals(Frame.class)) { 119 window = new Frame() { 120 public void paint(Graphics g) { 121 g.setColor(Color.BLUE); 122 g.fillRect(0, 0, 200, 200); 123 } 124 }; 125 ((Frame) window).setUndecorated(true); 126 } else if (windowClass.equals(Dialog.class)) { 127 window = new Dialog(background) { 128 public void paint(Graphics g) { 129 g.setColor(Color.BLUE); 130 g.fillRect(0, 0, 200, 200); 131 } 132 }; 133 ((Dialog) window).setUndecorated(true); 134 } else { 135 window = new Window(background) { 136 public void paint(Graphics g) { 137 g.setColor(Color.BLUE); 138 g.fillRect(0, 0, 200, 200); 139 } 140 }; 141 window.setFocusable(true); 142 window.setFocusableWindowState(true); 143 } 144 145 window.setPreferredSize(new Dimension(200, 200)); 146 window.setLocation(70 + dx, 450 + dy); 147 window.setLayout(new BorderLayout()); 148 149 window.addWindowFocusListener(new WindowFocusListener() { 150 public void windowGainedFocus(WindowEvent e) { flags.put("foregroundWindowGotFocus", true); } 151 public void windowLostFocus(WindowEvent e) { flags.put("foregroundWindowLostFocus", true); } 152 }); 153 154 window.addWindowListener(new WindowAdapter() { 155 public void windowActivated(WindowEvent e) { flags.put("foregroundWindowActivated", true); } 156 public void windowDeactivated(WindowEvent e) { flags.put("foregroundWindowDeactivated", true); } 157 }); 158 159 applyShape(); 160 window.pack(); 161 window.setAlwaysOnTop(true); 162 window.setVisible(true); 163 } 164 165 @Override 166 public void doTest() throws Exception { 167 super.doTest(); 168 final Point wls = new Point(); 169 final Dimension size = new Dimension(); 170 EventQueue.invokeAndWait(() -> { 171 window.requestFocus(); 172 wls.setLocation(window.getLocationOnScreen()); 173 window.getSize(size); 174 }); 175 176 robot.waitForIdle(); 177 178 check(wls.x + size.width - 5, wls.y + 5, wls.x + size.width / 3, wls.y + size.height / 3); 179 check(wls.x + size.width / 2, wls.y + size.height / 2, wls.x + size.width * 2 / 3, wls.y + size.height * 2 / 3); 180 181 EventQueue.invokeAndWait(() -> { 182 background.dispose(); 183 window.dispose(); 184 }); 185 186 robot.waitForIdle(); 187 } 188 189 @Override 190 public void applyShape() { 191 Shape shape; 192 Area a = new Area(new Rectangle2D.Float(0, 0, 200, 200)); 193 GeneralPath gp; 194 gp = new GeneralPath(); 195 gp.moveTo(190, 0); 196 gp.lineTo(200, 0); 197 gp.lineTo(200, 10); 198 gp.lineTo(10, 200); 199 gp.lineTo(0, 200); 200 gp.lineTo(0, 190); 201 gp.closePath(); 202 a.subtract(new Area(gp)); 203 shape = a; 204 205 window.setShape(shape); 206 } 207 208 private void check(int xb, int yb, int xw, int yw) throws Exception { 209 checkClick(xb, yb, "backgroundWindowGotFocus"); 210 checkClick(xw, yw, "foregroundWindowGotFocus"); 211 checkClick(xb, yb, "foregroundWindowLostFocus"); 212 checkClick(xw, yw, "backgroundWindowLostFocus"); 213 214 if (window instanceof Dialog || window instanceof Frame) { 215 checkClick(xb, yb, "backgroundWindowActivated"); 216 checkClick(xw, yw, "foregroundWindowActivated"); 217 checkClick(xb, yb, "foregroundWindowDeactivated"); 218 checkClick(xw, yw, "backgroundWindowDeactivated"); 219 } 220 221 } 222 223 private void checkClick(int x, int y, String flag) throws Exception { 224 System.out.println("Trying to click point " + x + ", " + y + ", looking for " + flag + " to trigger."); 225 226 flags.put(flag, false); 227 228 robot.mouseMove(x, y); 229 robot.click(); 230 int i = 0; 231 while (i < 5000 && !flags.get(flag)) { 232 robot.waitForIdle(50); 233 i += 50; 234 } 235 236 if (!flags.get(flag)) 237 throw new RuntimeException(flag + " is not triggered for click on point " + x + ", " + y + " for " + windowClass + "!"); 238 } 239 }