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