1 import javax.imageio.ImageIO; 
   2 import javax.swing.JDialog; 
   3 import javax.swing.JFrame; 
   4 import javax.swing.SwingUtilities; 
   5 import javax.swing.WindowConstants;
   6 import java.awt.*;
   7 import java.awt.event.WindowEvent;
   8 import java.awt.event.WindowListener; 
   9 import java.awt.image.BufferedImage; 
  10 import java.io.File; 
  11 import java.io.IOException; 
  12 import java.lang.reflect.InvocationTargetException; 
  13 import java.util.Arrays; 
  14 
  15 /* @test
  16  * @bug 8182638
  17  * @summary [macosx] Active modal dialog is hidden by another non-active one
  18  * @run main/othervm HiddenActiveModalTest
  19  */ 
  20 
  21 
  22 // The test displays two modal dialogs one by one 
  23 // and checks that the latest modal dialog would be on top of all windows 
  24 public class HiddenActiveModalTest implements Runnable {
  25 
  26     private static JFrame frame = new JFrame("HiddenActiveModalTest");
  27 
  28     private static boolean verbose = false; 
  29     private static boolean passed = true; 
  30 
  31     static DialogThread modalDialogThread1; 
  32 
  33     static DialogThread modalDialogThread2; 
  34 
  35     static class DialogThread { 
  36 
  37         JDialog dialog; 
  38 
  39         private String dialogTitle; 
  40         private Point location; 
  41         private int width; 
  42         private int height; 
  43         private DialogListener eventListener;
  44         private Color c;
  45 
  46 
  47         DialogThread(String dialogTitle, Point location, int width, int height, DialogListener eventListener, Color c) {
  48             this.dialogTitle = dialogTitle; 
  49             this.location = location; 
  50             this.width = width; 
  51             this.height = height; 
  52             this.eventListener = eventListener;
  53             this.c = c;
  54         }
  55 
  56         void run() { 
  57             dialog = new JDialog(frame, true); 
  58             dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
  59             dialog.getContentPane().setBackground(c);
  60             dialog.setTitle(dialogTitle); 
  61 
  62             dialog.setLocation(location); 
  63             dialog.setSize(width, height); 
  64 
  65             if (eventListener != null) 
  66                 dialog.addWindowListener(eventListener); 
  67 
  68             dialog.setVisible(true); 
  69         } 
  70 
  71         void removeWindowListener() { 
  72             dialog.removeWindowListener(eventListener); 
  73         } 
  74     } 
  75 
  76     static abstract class DialogListener implements WindowListener { 
  77 
  78         @Override 
  79         public void windowClosing(WindowEvent e) { 
  80 
  81         } 
  82 
  83         @Override 
  84         public void windowClosed(WindowEvent e) { 
  85 
  86         } 
  87 
  88         @Override 
  89         public void windowIconified(WindowEvent e) { 
  90 
  91         } 
  92 
  93         @Override 
  94         public void windowDeiconified(WindowEvent e) { 
  95 
  96         } 
  97 
  98         @Override 
  99         public void windowActivated(WindowEvent e) { 
 100 
 101         } 
 102 
 103         @Override 
 104         public void windowDeactivated(WindowEvent e) { 
 105 
 106         } 
 107     } 
 108 
 109     static class FirstDialogListener extends DialogListener { 
 110         @Override 
 111         public void windowOpened(WindowEvent windowEvent) { 
 112             modalDialogThread1.removeWindowListener(); 
 113             modalDialogThread2 = new DialogThread( 
 114                     "Modal input 2", 
 115                     new Point(5, 50), 
 116                     300, 200, 
 117                     new SecondDialogListener(), Color.GREEN);
 118             modalDialogThread2.run(); 
 119         } 
 120     } 
 121 
 122     static class SecondDialogListener extends DialogListener { 
 123         @Override 
 124         public void windowOpened(WindowEvent windowEvent) { 
 125             try { 
 126                 Robot robot = new Robot(); 
 127                 Dimension shotSize = modalDialogThread2.dialog.getContentPane().getSize(); 
 128                 Rectangle captureRect = new Rectangle(modalDialogThread2.dialog.getContentPane().getLocationOnScreen(),
 129                         shotSize); 
 130 
 131                 try { 
 132                     Thread.sleep(1000); 
 133                 } catch (InterruptedException e) { 
 134                     e.printStackTrace(); 
 135                 } 
 136 
 137                 BufferedImage screenImage = robot.createScreenCapture(captureRect); 
 138 
 139                 int rgb; 
 140                 int expectedRGB = Color.GREEN.getRGB();
 141 
 142 
 143                 for (int row = 1; row < shotSize.height; row++) {
 144                     try {
 145                         // remove transparance
 146                         rgb = screenImage.getRGB(shotSize.width / 2, row);
 147 
 148                         if (verbose) {
 149                             System.out.print((rgb == expectedRGB) ? " ." : " " + Integer.toHexString(rgb));
 150                         }
 151 
 152                         passed = passed & (expectedRGB == rgb);
 153 
 154                     } catch (ArrayIndexOutOfBoundsException e) {
 155                         throw new RuntimeException(e);
 156                     }
 157 
 158                 }
 159 
 160 
 161                 if (verbose) {
 162                     ImageIO.write(screenImage, "bmp", new File("test392.bmp"));
 163                 }
 164 
 165                 if (!passed) 
 166                     throw new RuntimeException("The second dialog window was not on top"); 
 167 
 168             } catch (AWTException | IOException e) { 
 169                 throw new RuntimeException(e); 
 170             } 
 171             modalDialogThread2.dialog.dispose(); 
 172             modalDialogThread1.dialog.dispose(); 
 173             frame.dispose(); 
 174         } 
 175     } 
 176 
 177     public void run() { 
 178         frame.setSize(350, 300); 
 179         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
 180         frame.setVisible(true); 
 181 
 182         modalDialogThread1 = new DialogThread( 
 183                 "Modal input 1", 
 184                 new Point(10, 75), 
 185                 250, 150, 
 186                 new FirstDialogListener(), Color.RED);
 187         modalDialogThread1.run(); 
 188     } 
 189 
 190     public static void main(String[] args) throws Exception { 
 191         HiddenActiveModalTest.verbose = Arrays.asList(args).contains("-verbose");
 192         try { 
 193             SwingUtilities.invokeAndWait(new HiddenActiveModalTest());
 194         } catch (InterruptedException | InvocationTargetException e) { 
 195             throw new RuntimeException(e); 
 196         } 
 197     } 
 198 }