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