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