< prev index next >

test/java/awt/Window/WindowResizingOnDPIChanging/WindowResizingOnSetLocationTest.java

Print this page




   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.Color;

  25 import java.awt.FlowLayout;
  26 import java.awt.Font;
  27 import java.awt.Graphics;
  28 import java.awt.Graphics2D;
  29 import java.awt.GraphicsConfiguration;
  30 import java.awt.GraphicsDevice;
  31 import java.awt.GraphicsEnvironment;
  32 import java.awt.GridBagConstraints;
  33 import java.awt.GridBagLayout;
  34 import java.awt.HeadlessException;
  35 import java.awt.Image;
  36 import java.awt.Insets;
  37 import java.awt.Rectangle;
  38 import java.awt.event.ActionEvent;
  39 import java.awt.event.ActionListener;
  40 import java.awt.event.WindowAdapter;
  41 import java.awt.event.WindowEvent;
  42 import java.awt.geom.AffineTransform;
  43 import java.awt.image.AbstractMultiResolutionImage;
  44 import java.awt.image.BufferedImage;
  45 import java.awt.image.ImageObserver;
  46 import java.util.Arrays;
  47 import java.util.Collections;
  48 import java.util.List;
  49 import java.util.concurrent.CountDownLatch;
  50 import java.util.concurrent.TimeUnit;
  51 import javax.swing.JButton;

  52 import javax.swing.JFrame;
  53 import javax.swing.JPanel;
  54 import javax.swing.JTextArea;
  55 import javax.swing.SwingUtilities;
  56 
  57 /* @test
  58  * @bug 8175293
  59  * @summary HiDPI (Windows): Swing components have incorrect sizes after
  60  *          changing display resolution
  61  * @run main/manual/othervm WindowResizingOnSetLocationTest
  62  */
  63 public class WindowResizingOnSetLocationTest {
  64 
  65     private static volatile boolean testResult = false;
  66     private static volatile CountDownLatch countDownLatch;
  67     private static TestFrame frame;
  68     private static JFrame mainFrame;




  69 
  70     private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
  71             + "Verify that a window is properly resized after setting the location"
  72             + " to a display with different DPI.\n"
  73             + "\n"
  74             + "The test is applicable for a multi-monitor system where displays"
  75             + " are configured to have different DPI\n"
  76             + "\n"
  77             + "1. Press Show Frame button\n"
  78             + "The frame appear.\n"



  79             + "2. Check that the string \"scales [ScaleX, ScaleY]\" is painted on the window"
  80             + " where ScaleX and ScaleY are the scales for current display.\n"
  81             + "The scales are calculated as DPI / 96 and are 1 for the DPI value 96"
  82             + " and 2 for the DPI value 192.\n"
  83             + "3. Press 'Move to another display' button.\n"
  84             + "4. Check that the frame appears on the another display.\n"
  85             + "5. Check that the string \"scales [ScaleX, ScaleY]\" is updated"
  86             + " to show the right display scales.\n"
  87             + "6. Check that the window is properly resized.\n"
  88             + "7. Check that the window is properly repainted and does not contain drawing artifacts\n"
  89             + "Try different display positions (left, right, top, bottom).\n"
  90             + "If all tests are passed, press PASS, else press FAIL.\n";
  91 
  92     public static void main(String args[]) throws Exception {
  93 
  94         countDownLatch = new CountDownLatch(1);
  95         SwingUtilities.invokeLater(WindowResizingOnSetLocationTest::createUI);
  96         countDownLatch.await(15, TimeUnit.MINUTES);
  97         if (!testResult) {
  98             throw new RuntimeException("Test fails!");
  99         }
 100     }
 101 
 102     private static void createUI() {
 103 


 104         mainFrame = new JFrame("DPI change test");
 105         GridBagLayout layout = new GridBagLayout();
 106         JPanel mainControlPanel = new JPanel(layout);
 107         JPanel resultButtonPanel = new JPanel(layout);
 108 
 109         GridBagConstraints gbc = new GridBagConstraints();
 110 
 111         JPanel testPanel = new JPanel(new FlowLayout());
 112         JButton frameButton = new JButton("Show Frame");
 113         frameButton.addActionListener((e) -> {
 114             int x = 20;
 115             int y = 10;
 116             int w = 400;
 117             int h = 300;
 118 
 119             frame = new TestFrame(w, h);
 120             frame.setLocation(x, y);
 121             frame.setVisible(true);
 122 
 123         });
 124         testPanel.add(frameButton);


 125 
 126         gbc.gridx = 0;
 127         gbc.gridy = 0;
 128         gbc.fill = GridBagConstraints.HORIZONTAL;
 129         mainControlPanel.add(testPanel, gbc);
 130 
 131         JTextArea instructionTextArea = new JTextArea();
 132         instructionTextArea.setText(INSTRUCTIONS);
 133         instructionTextArea.setEditable(false);
 134         instructionTextArea.setBackground(Color.white);
 135 
 136         gbc.gridx = 0;
 137         gbc.gridy = 1;
 138         gbc.fill = GridBagConstraints.HORIZONTAL;
 139         mainControlPanel.add(instructionTextArea, gbc);
 140 
 141         JButton passButton = new JButton("Pass");
 142         passButton.setActionCommand("Pass");
 143         passButton.addActionListener((ActionEvent e) -> {
 144             testResult = true;


 176 
 177             @Override
 178             public void windowClosing(WindowEvent e) {
 179                 disposeFrames();
 180                 countDownLatch.countDown();
 181             }
 182         });
 183         mainFrame.setVisible(true);
 184     }
 185 
 186     private static void disposeFrames() {
 187         if (frame != null && frame.isVisible()) {
 188             frame.dispose();
 189         }
 190 
 191         if (mainFrame != null && mainFrame.isVisible()) {
 192             mainFrame.dispose();
 193         }
 194     }
 195 





















































































 196     static class TestFrame extends JFrame {
 197 
 198         private final TestMultiResolutionImage mrImage;
 199 
 200         public TestFrame(int width, int height) throws HeadlessException {
 201             super("Test Frame");
 202             setSize(width, height);
 203             mrImage = new TestMultiResolutionImage(width, height);
 204 
 205             JPanel panel = new JPanel(new FlowLayout()) {
 206                 @Override
 207                 public void paint(Graphics g) {
 208                     super.paint(g);
 209                     AffineTransform tx = ((Graphics2D) g).getTransform();
 210                     mrImage.scaleX = tx.getScaleX();
 211                     mrImage.scaleY = tx.getScaleY();
 212                     Insets insets = getInsets();
 213                     g.drawImage(mrImage, insets.left, insets.bottom, null);
 214                 }
 215             };
 216 
 217             JButton button = new JButton("Move to another display");
 218             button.addActionListener((e) -> {
 219                 GraphicsConfiguration config = getGraphicsConfiguration();
 220                 GraphicsDevice device = config.getDevice();
 221 
 222                 GraphicsDevice[] devices = GraphicsEnvironment
 223                         .getLocalGraphicsEnvironment()
 224                         .getScreenDevices();
 225 
 226                 boolean found = false;
 227                 for (GraphicsDevice dev : devices) {
 228                     if (!dev.equals(device)) {
 229                         found = true;
 230                         Rectangle bounds = dev.getDefaultConfiguration().getBounds();
 231 
 232                         AffineTransform tx = config.getDefaultTransform();
 233                         int x = (int) Math.round(bounds.x / tx.getScaleX()) + 15;
 234                         int y = (int) Math.round(bounds.y / tx.getScaleY()) + 15;
 235                         frame.setLocation(x, y);
 236                         break;
 237                     }
 238                 }
 239 
 240                 if (!found) {
 241                     System.out.println("Another display not found!");
 242                 }


 243             });
 244 
 245             panel.add(button);
 246             add(panel);
 247         }
 248     }
 249 
 250     static class TestMultiResolutionImage extends AbstractMultiResolutionImage {
 251 
 252         final int width;
 253         final int height;
 254         double scaleX;
 255         double scaleY;
 256 
 257         public TestMultiResolutionImage(int width, int height) {
 258             this.width = width;
 259             this.height = height;
 260         }
 261 
 262         @Override




   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.BasicStroke;
  25 import java.awt.BorderLayout;
  26 import java.awt.Color;
  27 import java.awt.Dimension;
  28 import java.awt.FlowLayout;
  29 import java.awt.Font;
  30 import java.awt.Graphics;
  31 import java.awt.Graphics2D;
  32 import java.awt.GraphicsConfiguration;
  33 import java.awt.GraphicsDevice;
  34 import java.awt.GraphicsEnvironment;
  35 import java.awt.GridBagConstraints;
  36 import java.awt.GridBagLayout;
  37 import java.awt.HeadlessException;
  38 import java.awt.Image;
  39 import java.awt.Insets;
  40 import java.awt.Rectangle;
  41 import java.awt.event.ActionEvent;
  42 import java.awt.event.ActionListener;
  43 import java.awt.event.WindowAdapter;
  44 import java.awt.event.WindowEvent;
  45 import java.awt.geom.AffineTransform;
  46 import java.awt.image.AbstractMultiResolutionImage;
  47 import java.awt.image.BufferedImage;
  48 import java.awt.image.ImageObserver;
  49 import java.util.Arrays;
  50 import java.util.Collections;
  51 import java.util.List;
  52 import java.util.concurrent.CountDownLatch;
  53 import java.util.concurrent.TimeUnit;
  54 import javax.swing.JButton;
  55 import javax.swing.JComponent;
  56 import javax.swing.JFrame;
  57 import javax.swing.JPanel;
  58 import javax.swing.JTextArea;
  59 import javax.swing.SwingUtilities;
  60 
  61 /* @test
  62  * @bug 8175293 8176097
  63  * @summary Window set location to a display with different DPI does not properly work

  64  * @run main/manual/othervm WindowResizingOnSetLocationTest
  65  */
  66 public class WindowResizingOnSetLocationTest {
  67 
  68     private static volatile boolean testResult = false;
  69     private static volatile CountDownLatch countDownLatch;
  70     private static TestFrame frame;
  71     private static JFrame mainFrame;
  72     private static Rectangle[] screenBounds;
  73     private static double[][] scales;
  74     private static int screen1 = -1;
  75     private static int screen2 = -1;
  76 
  77     private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
  78             + "Verify that a window is properly resized after setting the location"
  79             + " to a display with different DPI.\n"
  80             + "\n"
  81             + "The test is applicable for a multi-monitor system where displays"
  82             + " are configured to have different DPI\n"
  83             + "\n"
  84             + "1. Press Show Frame button\n"
  85             + "  (note that the button is disabled in case there are no two monitors"
  86             + " with different DPI)\n"
  87             + "The frame should appear in the center of the display (either"
  88             + " on the first or on the second).\n"
  89             + "2. Check that the string \"scales [ScaleX, ScaleY]\" is painted on the window"
  90             + " where ScaleX and ScaleY are the scales for current display.\n"
  91             + "The scales are calculated as DPI / 96 and are 1 for the DPI value 96"
  92             + " and 2 for the DPI value 192.\n"
  93             + "3. Press 'Move to another display' button.\n"
  94             + "4. Check that the frame appears on the another display.\n"
  95             + "5. Check that the string \"scales [ScaleX, ScaleY]\" is updated"
  96             + " to show the right display scales.\n"
  97             + "6. Check that the window is properly resized.\n"
  98             + "7. Check that the window is properly repainted and does not contain drawing artifacts\n"

  99             + "If all tests are passed, press PASS, else press FAIL.\n";
 100 
 101     public static void main(String args[]) throws Exception {
 102 
 103         countDownLatch = new CountDownLatch(1);
 104         SwingUtilities.invokeLater(WindowResizingOnSetLocationTest::createUI);
 105         countDownLatch.await(15, TimeUnit.MINUTES);
 106         if (!testResult) {
 107             throw new RuntimeException("Test fails!");
 108         }
 109     }
 110 
 111     private static void createUI() {
 112 
 113         initScreenBounds();
 114 
 115         mainFrame = new JFrame("DPI change test");
 116         GridBagLayout layout = new GridBagLayout();
 117         JPanel mainControlPanel = new JPanel(layout);
 118         JPanel resultButtonPanel = new JPanel(layout);
 119 
 120         GridBagConstraints gbc = new GridBagConstraints();
 121 
 122         JPanel testPanel = new JPanel(new BorderLayout());
 123         JButton frameButton = new JButton("Show Frame");
 124         frameButton.addActionListener((e) -> {
 125             GraphicsConfiguration gc = GraphicsEnvironment
 126                     .getLocalGraphicsEnvironment()
 127                     .getScreenDevices()[screen1]
 128                     .getDefaultConfiguration();
 129 
 130             Rectangle rect = getCenterRect(screenBounds[screen2]);
 131             frame = new TestFrame(gc, rect);
 132             frame.setVisible(true);
 133 
 134         });
 135         frameButton.setEnabled(screen1 != -1 && screen2 != -1);
 136         testPanel.add(getDisplaysComponent(), BorderLayout.CENTER);
 137         testPanel.add(frameButton, BorderLayout.SOUTH);
 138 
 139         gbc.gridx = 0;
 140         gbc.gridy = 0;
 141         gbc.fill = GridBagConstraints.HORIZONTAL;
 142         mainControlPanel.add(testPanel, gbc);
 143 
 144         JTextArea instructionTextArea = new JTextArea();
 145         instructionTextArea.setText(INSTRUCTIONS);
 146         instructionTextArea.setEditable(false);
 147         instructionTextArea.setBackground(Color.white);
 148 
 149         gbc.gridx = 0;
 150         gbc.gridy = 1;
 151         gbc.fill = GridBagConstraints.HORIZONTAL;
 152         mainControlPanel.add(instructionTextArea, gbc);
 153 
 154         JButton passButton = new JButton("Pass");
 155         passButton.setActionCommand("Pass");
 156         passButton.addActionListener((ActionEvent e) -> {
 157             testResult = true;


 189 
 190             @Override
 191             public void windowClosing(WindowEvent e) {
 192                 disposeFrames();
 193                 countDownLatch.countDown();
 194             }
 195         });
 196         mainFrame.setVisible(true);
 197     }
 198 
 199     private static void disposeFrames() {
 200         if (frame != null && frame.isVisible()) {
 201             frame.dispose();
 202         }
 203 
 204         if (mainFrame != null && mainFrame.isVisible()) {
 205             mainFrame.dispose();
 206         }
 207     }
 208 
 209     static void initScreenBounds() {
 210 
 211         GraphicsDevice[] devices = GraphicsEnvironment
 212                 .getLocalGraphicsEnvironment()
 213                 .getScreenDevices();
 214 
 215         screenBounds = new Rectangle[devices.length];
 216         scales = new double[devices.length][2];
 217         for (int i = 0; i < devices.length; i++) {
 218             GraphicsConfiguration gc = devices[i].getDefaultConfiguration();
 219             screenBounds[i] = gc.getBounds();
 220             AffineTransform tx = gc.getDefaultTransform();
 221             scales[i][0] = tx.getScaleX();
 222             scales[i][1] = tx.getScaleY();
 223         }
 224 
 225         for (int i = 0; i < devices.length; i++) {
 226             for (int j = i + 1; j < devices.length; j++) {
 227                 if (scales[i][0] != scales[j][0] || scales[i][1] != scales[j][1]) {
 228                     screen1 = i;
 229                     screen2 = j;
 230                 }
 231             }
 232         }
 233     }
 234 
 235     private static Rectangle getCenterRect(Rectangle rect) {
 236         int w = rect.width / 2;
 237         int h = rect.height / 2;
 238         int x = rect.x + w / 2;
 239         int y = rect.y + h / 2;
 240 
 241         return new Rectangle(x, y, w, h);
 242     }
 243 
 244     static JComponent getDisplaysComponent() {
 245 
 246         Rectangle rect = screenBounds[0];
 247         for (int i = 0; i < screenBounds.length; i++) {
 248             rect = rect.union(screenBounds[i]);
 249         }
 250 
 251         final BufferedImage img = new BufferedImage(rect.width, rect.height, BufferedImage.TYPE_INT_RGB);
 252         Graphics2D g = img.createGraphics();
 253         g.setColor(Color.WHITE);
 254         g.fillRect(0, 0, rect.width, rect.height);
 255         g.translate(-rect.x, -rect.y);
 256 
 257         g.setStroke(new BasicStroke(8f));
 258         for (int i = 0; i < screenBounds.length; i++) {
 259             Rectangle r = screenBounds[i];
 260             g.setColor(Color.BLACK);
 261             g.drawRect(r.x, r.y, r.width, r.height);
 262 
 263             g.setColor(Color.ORANGE);
 264             Rectangle cr = getCenterRect(r);
 265             g.fillRect(cr.x, cr.y, cr.width, cr.height);
 266 
 267             double scaleX = scales[i][0];
 268             double scaleY = scales[i][1];
 269             float fontSize = rect.height / 7;
 270             g.setFont(g.getFont().deriveFont(fontSize));
 271             g.setColor(Color.BLUE);
 272             g.drawString(String.format("Scale: [%2.1f, %2.1f]", scaleX, scaleY),
 273                     r.x + r.width / 8, r.y + r.height / 2);
 274 
 275         }
 276 
 277         g.dispose();
 278 
 279         JPanel panel = new JPanel() {
 280 
 281             @Override
 282             public void paint(Graphics g) {
 283                 super.paint(g);
 284                 g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
 285 
 286             }
 287         };
 288 
 289         panel.setPreferredSize(new Dimension(400, 200));
 290 
 291         return panel;
 292     }
 293 
 294     static class TestFrame extends JFrame {
 295 
 296         private final TestMultiResolutionImage mrImage;
 297 
 298         public TestFrame(GraphicsConfiguration gc, Rectangle rect) throws HeadlessException {
 299             super(gc);
 300             setBounds(rect);
 301             mrImage = new TestMultiResolutionImage(rect.width, rect.height);
 302 
 303             JPanel panel = new JPanel(new FlowLayout()) {
 304                 @Override
 305                 public void paint(Graphics g) {
 306                     super.paint(g);
 307                     AffineTransform tx = ((Graphics2D) g).getTransform();
 308                     mrImage.scaleX = tx.getScaleX();
 309                     mrImage.scaleY = tx.getScaleY();
 310                     Insets insets = getInsets();
 311                     g.drawImage(mrImage, insets.left, insets.bottom, null);
 312                 }
 313             };
 314 
 315             JButton button = new JButton("Move to another display");
 316             button.addActionListener((e) -> {
 317                 GraphicsConfiguration config = getGraphicsConfiguration();

 318 
 319                 GraphicsDevice[] devices = GraphicsEnvironment
 320                         .getLocalGraphicsEnvironment()
 321                         .getScreenDevices();
 322 













 323 
 324                 int index = devices[screen1].getDefaultConfiguration().equals(config)
 325                         ? screen2 : screen1;
 326 
 327                 Rectangle r = getCenterRect(screenBounds[index]);
 328                 frame.setBounds(r);
 329             });
 330 
 331             panel.add(button);
 332             add(panel);
 333         }
 334     }
 335 
 336     static class TestMultiResolutionImage extends AbstractMultiResolutionImage {
 337 
 338         final int width;
 339         final int height;
 340         double scaleX;
 341         double scaleY;
 342 
 343         public TestMultiResolutionImage(int width, int height) {
 344             this.width = width;
 345             this.height = height;
 346         }
 347 
 348         @Override


< prev index next >