1 /* 2 * Copyright (c) 2014, 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 java.awt.*; 25 import java.awt.event.*; 26 import java.awt.geom.Point2D; 27 import java.awt.image.BufferedImage; 28 import java.lang.reflect.Field; 29 import java.lang.reflect.Method; 30 import java.security.AccessController; 31 import java.security.PrivilegedActionException; 32 import java.security.PrivilegedExceptionAction; 33 34 /* 35 * @summary This is a helper class to find the location of a system tray icon, 36 * and skip some OS specific cases in tests. 37 * @library /lib/client 38 * @build ExtendedRobot SystemTrayIconHelper 39 */ 40 public class SystemTrayIconHelper { 41 42 static Frame frame; 43 44 /** 45 * Call this method if the tray icon need to be followed in an automated manner 46 * This method will be called by automated testcases 47 */ getTrayIconLocation(TrayIcon icon)48 static Point getTrayIconLocation(TrayIcon icon) throws Exception { 49 if (icon == null) { 50 return null; 51 } 52 53 //This is added just in case the tray's native menu is visible. 54 //It has to be hidden if visible. For that, we are showing a Frame 55 //and clicking on it - the assumption is, the menu will 56 //be closed if another window is clicked 57 ExtendedRobot robot = new ExtendedRobot(); 58 try { 59 EventQueue.invokeAndWait(() -> { 60 frame = new Frame(); 61 frame.setSize(100, 100); 62 frame.setVisible(true); 63 }); 64 robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth() / 2, 65 frame.getLocationOnScreen().y + frame.getHeight() / 2); 66 robot.waitForIdle(); 67 robot.click(); 68 EventQueue.invokeAndWait(frame::dispose); 69 } catch (Exception e) { 70 return null; 71 } 72 73 if (System.getProperty("os.name").startsWith("Win")) { 74 try { 75 // sun.awt.windows.WTrayIconPeer 76 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 77 Dimension iconSize = icon.getSize(); 78 79 int width = (int) iconSize.getWidth(); 80 int height = (int) iconSize.getHeight(); 81 82 // Some previously created icons may not be removed 83 // from tray until mouse move on it. So we glide 84 // through the whole tray bar. 85 robot.glide((int) screenSize.getWidth(), (int) (screenSize.getHeight()-15), 0, (int) (screenSize.getHeight() - 15), 1, 2); 86 87 BufferedImage screen = robot.createScreenCapture(new Rectangle(screenSize)); 88 89 for (int x = (int) (screenSize.getWidth()-width); x > 0; x--) { 90 for (int y = (int) (screenSize.getHeight()-height); y > (screenSize.getHeight()-50); y--) { 91 if (imagesEquals(((BufferedImage)icon.getImage()).getSubimage(0, 0, width, height), screen.getSubimage(x, y, width, height))) { 92 Point point = new Point(x + 5, y + 5); 93 System.out.println("Icon location " + point); 94 return point; 95 } 96 } 97 } 98 } catch (Exception e) { 99 e.printStackTrace(); 100 return null; 101 } 102 } else if (System.getProperty("os.name").startsWith("Mac")) { 103 Point2D point2d; 104 try { 105 // sun.lwawt.macosx.CTrayIcon 106 Field f_peer = getField( java.awt.TrayIcon.class, "peer"); 107 Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.Module.class); 108 m_addExports.invoke(null, "sun.lwawt.macosx", robot.getClass().getModule()); 109 110 111 Object peer = f_peer.get(icon); 112 Class<?> superclass = peer.getClass().getSuperclass(); 113 System.out.println("superclass = " + superclass); 114 Field m_getModel = superclass.getDeclaredField("ptr"); 115 m_getModel.setAccessible(true); 116 long model = (Long) m_getModel.get(peer); 117 Method m_getLocation = peer.getClass().getDeclaredMethod( 118 "nativeGetIconLocation", new Class[]{Long.TYPE}); 119 m_getLocation.setAccessible(true); 120 point2d = (Point2D)m_getLocation.invoke(peer, new Object[]{model}); 121 Point po = new Point((int)(point2d.getX()), (int)(point2d.getY())); 122 po.translate(10, -5); 123 System.out.println("Icon location " + po); 124 return po; 125 }catch(Exception e) { 126 e.printStackTrace(); 127 return null; 128 } 129 } else { 130 try { 131 // sun.awt.X11.XTrayIconPeer 132 Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.Module.class); 133 m_addExports.invoke(null, "sun.awt.X11", robot.getClass().getModule()); 134 135 Field f_peer = getField(java.awt.TrayIcon.class, "peer"); 136 137 SystemTrayIconHelper.openTrayIfNeeded(robot); 138 139 Object peer = f_peer.get(icon); 140 Method m_getLOS = peer.getClass().getDeclaredMethod( 141 "getLocationOnScreen", new Class[]{}); 142 m_getLOS.setAccessible(true); 143 Point point = (Point)m_getLOS.invoke(peer, new Object[]{}); 144 point.translate(5, 5); 145 System.out.println("Icon location " + point); 146 return point; 147 } catch (Exception e) { 148 e.printStackTrace(); 149 return null; 150 } 151 } 152 return null; 153 } 154 getField(final Class clz, final String fieldName)155 static Field getField(final Class clz, final String fieldName) { 156 Field res = null; 157 try { 158 res = (Field)AccessController.doPrivileged((PrivilegedExceptionAction) () -> { 159 Field f = clz.getDeclaredField(fieldName); 160 f.setAccessible(true); 161 return f; 162 }); 163 } catch (PrivilegedActionException ex) { 164 ex.printStackTrace(); 165 } 166 return res; 167 } 168 imagesEquals(BufferedImage img1, BufferedImage img2)169 static boolean imagesEquals(BufferedImage img1, BufferedImage img2) { 170 for (int x = 0; x < img1.getWidth(); x++) { 171 for (int y = 0; y < img1.getHeight(); y++) { 172 if (img1.getRGB(x, y) != img2.getRGB(x, y)) 173 return false; 174 } 175 } 176 return true; 177 } 178 doubleClick(Robot robot)179 static void doubleClick(Robot robot) { 180 if (System.getProperty("os.name").startsWith("Mac")) { 181 robot.mousePress(InputEvent.BUTTON3_MASK); 182 robot.delay(50); 183 robot.mouseRelease(InputEvent.BUTTON3_MASK); 184 } else { 185 robot.mousePress(InputEvent.BUTTON1_MASK); 186 robot.delay(50); 187 robot.mouseRelease(InputEvent.BUTTON1_MASK); 188 robot.delay(50); 189 robot.mousePress(InputEvent.BUTTON1_MASK); 190 robot.delay(50); 191 robot.mouseRelease(InputEvent.BUTTON1_MASK); 192 } 193 } 194 195 // Method for skipping some OS specific cases skip(int button)196 static boolean skip(int button) { 197 if (System.getProperty("os.name").toLowerCase().startsWith("win")){ 198 if (button == InputEvent.BUTTON1_MASK){ 199 // See JDK-6827035 200 return true; 201 } 202 } else if (System.getProperty("os.name").toLowerCase().contains("os x")){ 203 // See JDK-7153700 204 return true; 205 } 206 return false; 207 } 208 openTrayIfNeeded(Robot robot)209 public static boolean openTrayIfNeeded(Robot robot) { 210 String sysv = System.getProperty("os.version"); 211 System.out.println("System version is " + sysv); 212 //Additional step to raise the system try in Gnome 3 in OEL 7 213 if(isOel7()) { 214 System.out.println("OEL 7 detected"); 215 GraphicsConfiguration gc = GraphicsEnvironment. 216 getLocalGraphicsEnvironment().getDefaultScreenDevice(). 217 getDefaultConfiguration(); 218 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); 219 if(insets.bottom > 0) { 220 Dimension screenSize = Toolkit.getDefaultToolkit() 221 .getScreenSize(); 222 robot.mouseMove(screenSize.width - insets.bottom / 2, 223 screenSize.height - insets.bottom / 2); 224 robot.delay(50); 225 robot.mousePress(InputEvent.BUTTON1_MASK); 226 robot.delay(50); 227 robot.mouseRelease(InputEvent.BUTTON1_MASK); 228 robot.waitForIdle(); 229 robot.delay(1000); 230 System.out.println("Tray is opened"); 231 return true; 232 } 233 } 234 return false; 235 } 236 isOel7()237 public static boolean isOel7() { 238 return System.getProperty("os.name").toLowerCase() 239 .contains("linux") && System.getProperty("os.version") 240 .toLowerCase().contains("el7"); 241 } 242 } 243