--- /dev/null 2016-02-24 11:45:17.377928705 +0300 +++ new/test/lib/testlibrary/SystemTrayIconHelper.java 2016-02-29 18:03:00.260206514 +0300 @@ -0,0 +1,218 @@ +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +/* + * @summary This is a helper class to find the location of a system tray icon, + * and skip some OS specific cases in tests. + * @library ../../../../../lib/testlibrary + * @build ExtendedRobot SystemTrayIconHelper + */ +public class SystemTrayIconHelper { + + static Frame frame; + + /** + * Call this method if the tray icon need to be followed in an automated manner + * This method will be called by automated testcases + */ + static Point getTrayIconLocation(TrayIcon icon) throws Exception { + if (icon == null) { + return null; + } + + //This is added just in case the tray's native menu is visible. + //It has to be hidden if visible. For that, we are showing a Frame + //and clicking on it - the assumption is, the menu will + //be closed if another window is clicked + ExtendedRobot robot = new ExtendedRobot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame(); + frame.setSize(100, 100); + frame.setVisible(true); + }); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth() / 2, + frame.getLocationOnScreen().y + frame.getHeight() / 2); + robot.waitForIdle(); + robot.click(); + EventQueue.invokeAndWait(frame::dispose); + } catch (Exception e) { + return null; + } + + if (System.getProperty("os.name").startsWith("Win")) { + try { + // sun.awt.windows.WTrayIconPeer + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension iconSize = icon.getSize(); + + int width = (int) iconSize.getWidth(); + int height = (int) iconSize.getHeight(); + + // Some previously created icons may not be removed + // from tray until mouse move on it. So we glide + // through the whole tray bar. + robot.glide((int) screenSize.getWidth(), (int) (screenSize.getHeight()-15), 0, (int) (screenSize.getHeight() - 15), 1, 2); + + BufferedImage screen = robot.createScreenCapture(new Rectangle(screenSize)); + + for (int x = (int) (screenSize.getWidth()-width); x > 0; x--) { + for (int y = (int) (screenSize.getHeight()-height); y > (screenSize.getHeight()-50); y--) { + if (imagesEquals(((BufferedImage)icon.getImage()).getSubimage(0, 0, width, height), screen.getSubimage(x, y, width, height))) { + Point point = new Point(x + 5, y + 5); + System.out.println("Icon location " + point); + return point; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } else if (System.getProperty("os.name").startsWith("Mac")) { + Point2D point2d; + try { + // sun.lwawt.macosx.CTrayIcon + Field f_peer = getField( java.awt.TrayIcon.class, "peer"); + Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.reflect.Module.class); + m_addExports.invoke(null, "sun.lwawt.macosx", robot.getClass().getModule()); + + + Object peer = f_peer.get(icon); + Method m_getModel = peer.getClass().getDeclaredMethod( + "getModel"); + m_getModel.setAccessible(true); + long model = (Long) (m_getModel.invoke(peer, new Object[]{})); + Method m_getLocation = peer.getClass().getDeclaredMethod( + "nativeGetIconLocation", new Class[]{Long.TYPE}); + m_getLocation.setAccessible(true); + point2d = (Point2D)m_getLocation.invoke(peer, new Object[]{model}); + Point po = new Point((int)(point2d.getX()), (int)(point2d.getY())); + po.translate(10, -5); + System.out.println("Icon location " + po); + return po; + }catch(Exception e) { + e.printStackTrace(); + return null; + } + } else { + try { + // sun.awt.X11.XTrayIconPeer + Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.reflect.Module.class); + m_addExports.invoke(null, "sun.awt.X11", robot.getClass().getModule()); + + Field f_peer = getField(java.awt.TrayIcon.class, "peer"); + + SystemTrayIconHelper.openTrayIfNeeded(robot); + + Object peer = f_peer.get(icon); + Method m_getLOS = peer.getClass().getDeclaredMethod( + "getLocationOnScreen", new Class[]{}); + m_getLOS.setAccessible(true); + Point point = (Point)m_getLOS.invoke(peer, new Object[]{}); + point.translate(5, 5); + System.out.println("Icon location " + point); + return point; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + return null; + } + + static Field getField(final Class clz, final String fieldName) { + Field res = null; + try { + res = (Field)AccessController.doPrivileged((PrivilegedExceptionAction) () -> { + Field f = clz.getDeclaredField(fieldName); + f.setAccessible(true); + return f; + }); + } catch (PrivilegedActionException ex) { + ex.printStackTrace(); + } + return res; + } + + static boolean imagesEquals(BufferedImage img1, BufferedImage img2) { + for (int x = 0; x < img1.getWidth(); x++) { + for (int y = 0; y < img1.getHeight(); y++) { + if (img1.getRGB(x, y) != img2.getRGB(x, y)) + return false; + } + } + return true; + } + + static void doubleClick(Robot robot) { + if (System.getProperty("os.name").startsWith("Mac")) { + robot.mousePress(InputEvent.BUTTON3_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON3_MASK); + } else { + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + } + + // Method for skipping some OS specific cases + static boolean skip(int button) { + if (System.getProperty("os.name").toLowerCase().startsWith("win")){ + if (button == InputEvent.BUTTON1_MASK){ + // See JDK-6827035 + return true; + } + } else if (System.getProperty("os.name").toLowerCase().contains("os x")){ + // See JDK-7153700 + return true; + } + return false; + } + + public static boolean openTrayIfNeeded(Robot robot) { + String sysv = System.getProperty("os.version"); + System.out.println("System version is " + sysv); + //Additional step to raise the system try in Gnome 3 in OEL 7 + if(isOel7()) { + System.out.println("OEL 7 detected"); + GraphicsConfiguration gc = GraphicsEnvironment. + getLocalGraphicsEnvironment().getDefaultScreenDevice(). + getDefaultConfiguration(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + if(insets.bottom > 0) { + Dimension screenSize = Toolkit.getDefaultToolkit() + .getScreenSize(); + robot.mouseMove(screenSize.width - insets.bottom / 2, + screenSize.height - insets.bottom / 2); + robot.delay(50); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.waitForIdle(); + robot.delay(1000); + System.out.println("Tray is opened"); + return true; + } + } + return false; + } + + public static boolean isOel7() { + return System.getProperty("os.name").toLowerCase() + .contains("linux") && System.getProperty("os.version") + .toLowerCase().contains("el7"); + } +}