1 /*
   2  * Copyright (c) 2013, 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 import java.awt.BorderLayout;
  24 import java.awt.Color;
  25 import java.awt.Cursor;
  26 import java.awt.Dialog;
  27 import java.awt.Frame;
  28 import java.awt.Graphics;
  29 import java.awt.Graphics2D;
  30 import java.awt.Image;
  31 import java.awt.Label;
  32 import java.awt.Point;
  33 import java.awt.TextArea;
  34 import java.awt.Toolkit;
  35 import java.awt.image.BufferedImage;
  36 import java.util.LinkedList;
  37 import java.util.List;
  38 import javax.swing.JApplet;
  39 import sun.awt.OSInfo;
  40 import sun.awt.image.MultiResolutionImage;
  41 
  42 /**
  43  * @test
  44  * @bug 8028212
  45  * @summary [macosx] Custom Cursor HiDPI support
  46  * @author Alexander Scherbatiy
  47  * @run applet/manual=yesno MultiResolutionCursorTest.html
  48  */
  49 public class MultiResolutionCursorTest extends JApplet {
  50     //Declare things used in the test, like buttons and labels here
  51 
  52     static final int sizes[] = {16, 32, 128};
  53     static final Color colors[] = {Color.WHITE, Color.RED, Color.GREEN, Color.BLUE};
  54 
  55     public void init() {
  56         //Create instructions for the user here, as well as set up
  57         // the environment -- set the layout manager, add buttons,
  58         // etc.
  59         this.setLayout(new BorderLayout());
  60 
  61         if (OSInfo.getOSType().equals(OSInfo.OSType.MACOSX)) {
  62             String[] instructions = {
  63                 "Verify that high resolution custom cursor is used"
  64                 + " on HiDPI displays.",
  65                 "1) Run the test on Retina display or enable the Quartz Debug"
  66                 + " and select the screen resolution with (HiDPI) label",
  67                 "2) Move the cursor to the Test Frame",
  68                 "3) Check that cursor has red, green or blue color",
  69                 "If so, press PASS, else press FAIL."
  70             };
  71             Sysout.createDialogWithInstructions(instructions);
  72 
  73         } else {
  74             String[] instructions = {
  75                 "This test is not applicable to the current platform. Press PASS."
  76             };
  77             Sysout.createDialogWithInstructions(instructions);
  78         }
  79     }//End  init()
  80 
  81     public void start() {
  82         //Get things going.  Request focus, set size, et cetera
  83         setSize(200, 200);
  84         setVisible(true);
  85         validate();
  86 
  87         final Image image = new MultiResolutionCursor();
  88 
  89         int center = sizes[0] / 2;
  90         Cursor cursor = Toolkit.getDefaultToolkit().createCustomCursor(
  91                 image, new Point(center, center), "multi-resolution cursor");
  92 
  93         Frame frame = new Frame("Test Frame");
  94         frame.setSize(300, 300);
  95         frame.setLocation(300, 50);
  96         frame.add(new Label("Move cursor here"));
  97         frame.setCursor(cursor);
  98         frame.setVisible(true);
  99     }// start()
 100 
 101 
 102     static class MultiResolutionCursor extends BufferedImage implements MultiResolutionImage {
 103 
 104         List<Image> highResolutionImages;
 105 
 106         public MultiResolutionCursor() {
 107             super(sizes[0], sizes[0], BufferedImage.TYPE_INT_RGB);
 108 
 109             draw(getGraphics(), 0);
 110             highResolutionImages = new LinkedList<>();
 111             highResolutionImages.add(this);
 112 
 113             for (int i = 1; i < sizes.length; i++) {
 114                 BufferedImage highResolutionImage =
 115                         new BufferedImage(sizes[i], sizes[i], BufferedImage.TYPE_INT_RGB);
 116                 draw(highResolutionImage.getGraphics(), i);
 117                 highResolutionImages.add(highResolutionImage);
 118             }
 119         }
 120 
 121         @Override
 122         public Image getResolutionVariant(int width, int height) {
 123 
 124             for (int i = 0; i < sizes.length; i++) {
 125                 Image image = highResolutionImages.get(i);
 126                 int w = image.getWidth(null);
 127                 int h = image.getHeight(null);
 128 
 129                 if (width <= w && height <= h) {
 130                     return image;
 131                 }
 132             }
 133 
 134             return highResolutionImages.get(highResolutionImages.size() - 1);
 135         }
 136 
 137         void draw(Graphics graphics, int index) {
 138             Graphics2D g2 = (Graphics2D) graphics;
 139             Color color = colors[index];
 140             g2.setColor(color);
 141             g2.fillRect(0, 0, sizes[index], sizes[index]);
 142         }
 143 
 144         @Override
 145         public List<Image> getResolutionVariants() {
 146             return highResolutionImages;
 147         }
 148     }
 149 }// class BlockedWindowTest
 150 
 151 /* Place other classes related to the test after this line */
 152 /**
 153  * **************************************************
 154  * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk
 155  * of code whose purpose is to make user interaction uniform, and thereby make
 156  * it simpler to read and understand someone else's test.
 157  * **************************************************
 158  */
 159 /**
 160  * This is part of the standard test machinery. It creates a dialog (with the
 161  * instructions), and is the interface for sending text messages to the user. To
 162  * print the instructions, send an array of strings to Sysout.createDialog
 163  * WithInstructions method. Put one line of instructions per array entry. To
 164  * display a message for the tester to see, simply call Sysout.println with the
 165  * string to be displayed. This mimics System.out.println but works within the
 166  * test harness as well as standalone.
 167  */
 168 class Sysout {
 169 
 170     private static TestDialog dialog;
 171 
 172     public static void createDialogWithInstructions(String[] instructions) {
 173         dialog = new TestDialog(new Frame(), "Instructions");
 174         dialog.printInstructions(instructions);
 175         dialog.setVisible(true);
 176         println("Any messages for the tester will display here.");
 177     }
 178 
 179     public static void createDialog() {
 180         dialog = new TestDialog(new Frame(), "Instructions");
 181         String[] defInstr = {"Instructions will appear here. ", ""};
 182         dialog.printInstructions(defInstr);
 183         dialog.setVisible(true);
 184         println("Any messages for the tester will display here.");
 185     }
 186 
 187     public static void printInstructions(String[] instructions) {
 188         dialog.printInstructions(instructions);
 189     }
 190 
 191     public static void println(String messageIn) {
 192         dialog.displayMessage(messageIn);
 193     }
 194 }// Sysout  class
 195 
 196 /**
 197  * This is part of the standard test machinery. It provides a place for the test
 198  * instructions to be displayed, and a place for interactive messages to the
 199  * user to be displayed. To have the test instructions displayed, see Sysout. To
 200  * have a message to the user be displayed, see Sysout. Do not call anything in
 201  * this dialog directly.
 202  */
 203 class TestDialog extends Dialog {
 204 
 205     TextArea instructionsText;
 206     TextArea messageText;
 207     int maxStringLength = 80;
 208 
 209     //DO NOT call this directly, go through Sysout
 210     public TestDialog(Frame frame, String name) {
 211         super(frame, name);
 212         int scrollBoth = TextArea.SCROLLBARS_BOTH;
 213         instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
 214         add("North", instructionsText);
 215 
 216         messageText = new TextArea("", 5, maxStringLength, scrollBoth);
 217         add("Center", messageText);
 218 
 219         pack();
 220 
 221         setVisible(true);
 222     }// TestDialog()
 223 
 224     //DO NOT call this directly, go through Sysout
 225     public void printInstructions(String[] instructions) {
 226         //Clear out any current instructions
 227         instructionsText.setText("");
 228 
 229         //Go down array of instruction strings
 230 
 231         String printStr, remainingStr;
 232         for (int i = 0; i < instructions.length; i++) {
 233             //chop up each into pieces maxSringLength long
 234             remainingStr = instructions[ i];
 235             while (remainingStr.length() > 0) {
 236                 //if longer than max then chop off first max chars to print
 237                 if (remainingStr.length() >= maxStringLength) {
 238                     //Try to chop on a word boundary
 239                     int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1);
 240 
 241                     if (posOfSpace <= 0) {
 242                         posOfSpace = maxStringLength - 1;
 243                     }
 244 
 245                     printStr = remainingStr.substring(0, posOfSpace + 1);
 246                     remainingStr = remainingStr.substring(posOfSpace + 1);
 247                 } //else just print
 248                 else {
 249                     printStr = remainingStr;
 250                     remainingStr = "";
 251                 }
 252 
 253                 instructionsText.append(printStr + "\n");
 254 
 255             }// while
 256 
 257         }// for
 258 
 259     }//printInstructions()
 260 
 261     //DO NOT call this directly, go through Sysout
 262     public void displayMessage(String messageIn) {
 263         messageText.append(messageIn + "\n");
 264         System.out.println(messageIn);
 265     }
 266 }// Te