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