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