Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/awt/Cursor.java
38829 views
/*1* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package java.awt;2526import java.io.File;27import java.io.FileInputStream;2829import java.beans.ConstructorProperties;30import java.util.Hashtable;31import java.util.Properties;32import java.util.StringTokenizer;3334import java.security.AccessController;3536import sun.util.logging.PlatformLogger;37import sun.awt.AWTAccessor;3839/**40* A class to encapsulate the bitmap representation of the mouse cursor.41*42* @see Component#setCursor43* @author Amy Fowler44*/45public class Cursor implements java.io.Serializable {4647/**48* The default cursor type (gets set if no cursor is defined).49*/50public static final int DEFAULT_CURSOR = 0;5152/**53* The crosshair cursor type.54*/55public static final int CROSSHAIR_CURSOR = 1;5657/**58* The text cursor type.59*/60public static final int TEXT_CURSOR = 2;6162/**63* The wait cursor type.64*/65public static final int WAIT_CURSOR = 3;6667/**68* The south-west-resize cursor type.69*/70public static final int SW_RESIZE_CURSOR = 4;7172/**73* The south-east-resize cursor type.74*/75public static final int SE_RESIZE_CURSOR = 5;7677/**78* The north-west-resize cursor type.79*/80public static final int NW_RESIZE_CURSOR = 6;8182/**83* The north-east-resize cursor type.84*/85public static final int NE_RESIZE_CURSOR = 7;8687/**88* The north-resize cursor type.89*/90public static final int N_RESIZE_CURSOR = 8;9192/**93* The south-resize cursor type.94*/95public static final int S_RESIZE_CURSOR = 9;9697/**98* The west-resize cursor type.99*/100public static final int W_RESIZE_CURSOR = 10;101102/**103* The east-resize cursor type.104*/105public static final int E_RESIZE_CURSOR = 11;106107/**108* The hand cursor type.109*/110public static final int HAND_CURSOR = 12;111112/**113* The move cursor type.114*/115public static final int MOVE_CURSOR = 13;116117/**118* @deprecated As of JDK version 1.7, the {@link #getPredefinedCursor(int)}119* method should be used instead.120*/121@Deprecated122protected static Cursor predefined[] = new Cursor[14];123124/**125* This field is a private replacement for 'predefined' array.126*/127private final static Cursor[] predefinedPrivate = new Cursor[14];128129/* Localization names and default values */130static final String[][] cursorProperties = {131{ "AWT.DefaultCursor", "Default Cursor" },132{ "AWT.CrosshairCursor", "Crosshair Cursor" },133{ "AWT.TextCursor", "Text Cursor" },134{ "AWT.WaitCursor", "Wait Cursor" },135{ "AWT.SWResizeCursor", "Southwest Resize Cursor" },136{ "AWT.SEResizeCursor", "Southeast Resize Cursor" },137{ "AWT.NWResizeCursor", "Northwest Resize Cursor" },138{ "AWT.NEResizeCursor", "Northeast Resize Cursor" },139{ "AWT.NResizeCursor", "North Resize Cursor" },140{ "AWT.SResizeCursor", "South Resize Cursor" },141{ "AWT.WResizeCursor", "West Resize Cursor" },142{ "AWT.EResizeCursor", "East Resize Cursor" },143{ "AWT.HandCursor", "Hand Cursor" },144{ "AWT.MoveCursor", "Move Cursor" },145};146147/**148* The chosen cursor type initially set to149* the <code>DEFAULT_CURSOR</code>.150*151* @serial152* @see #getType()153*/154int type = DEFAULT_CURSOR;155156/**157* The type associated with all custom cursors.158*/159public static final int CUSTOM_CURSOR = -1;160161/*162* hashtable, filesystem dir prefix, filename, and properties for custom cursors support163*/164165private static final Hashtable<String,Cursor> systemCustomCursors = new Hashtable<>(1);166private static final String systemCustomCursorDirPrefix = initCursorDir();167168private static String initCursorDir() {169String jhome = java.security.AccessController.doPrivileged(170new sun.security.action.GetPropertyAction("java.home"));171return jhome +172File.separator + "lib" + File.separator + "images" +173File.separator + "cursors" + File.separator;174}175176private static final String systemCustomCursorPropertiesFile = systemCustomCursorDirPrefix + "cursors.properties";177178private static Properties systemCustomCursorProperties = null;179180private static final String CursorDotPrefix = "Cursor.";181private static final String DotFileSuffix = ".File";182private static final String DotHotspotSuffix = ".HotSpot";183private static final String DotNameSuffix = ".Name";184185/*186* JDK 1.1 serialVersionUID187*/188private static final long serialVersionUID = 8028237497568985504L;189190private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Cursor");191192static {193/* ensure that the necessary native libraries are loaded */194Toolkit.loadLibraries();195if (!GraphicsEnvironment.isHeadless()) {196initIDs();197}198199AWTAccessor.setCursorAccessor(200new AWTAccessor.CursorAccessor() {201public long getPData(Cursor cursor) {202return cursor.pData;203}204205public void setPData(Cursor cursor, long pData) {206cursor.pData = pData;207}208209public int getType(Cursor cursor) {210return cursor.type;211}212});213}214215/**216* Initialize JNI field and method IDs for fields that may be217* accessed from C.218*/219private static native void initIDs();220221/**222* Hook into native data.223*/224private transient long pData;225226private transient Object anchor = new Object();227228static class CursorDisposer implements sun.java2d.DisposerRecord {229volatile long pData;230public CursorDisposer(long pData) {231this.pData = pData;232}233public void dispose() {234if (pData != 0) {235finalizeImpl(pData);236}237}238}239transient CursorDisposer disposer;240private void setPData(long pData) {241this.pData = pData;242if (GraphicsEnvironment.isHeadless()) {243return;244}245if (disposer == null) {246disposer = new CursorDisposer(pData);247// anchor is null after deserialization248if (anchor == null) {249anchor = new Object();250}251sun.java2d.Disposer.addRecord(anchor, disposer);252} else {253disposer.pData = pData;254}255}256257/**258* The user-visible name of the cursor.259*260* @serial261* @see #getName()262*/263protected String name;264265/**266* Returns a cursor object with the specified predefined type.267*268* @param type the type of predefined cursor269* @return the specified predefined cursor270* @throws IllegalArgumentException if the specified cursor type is271* invalid272*/273static public Cursor getPredefinedCursor(int type) {274if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {275throw new IllegalArgumentException("illegal cursor type");276}277Cursor c = predefinedPrivate[type];278if (c == null) {279predefinedPrivate[type] = c = new Cursor(type);280}281// fill 'predefined' array for backwards compatibility.282if (predefined[type] == null) {283predefined[type] = c;284}285return c;286}287288/**289* Returns a system-specific custom cursor object matching the290* specified name. Cursor names are, for example: "Invalid.16x16"291*292* @param name a string describing the desired system-specific custom cursor293* @return the system specific custom cursor named294* @exception HeadlessException if295* <code>GraphicsEnvironment.isHeadless</code> returns true296*/297static public Cursor getSystemCustomCursor(final String name)298throws AWTException, HeadlessException {299GraphicsEnvironment.checkHeadless();300Cursor cursor = systemCustomCursors.get(name);301302if (cursor == null) {303synchronized(systemCustomCursors) {304if (systemCustomCursorProperties == null)305loadSystemCustomCursorProperties();306}307308String prefix = CursorDotPrefix + name;309String key = prefix + DotFileSuffix;310311if (!systemCustomCursorProperties.containsKey(key)) {312if (log.isLoggable(PlatformLogger.Level.FINER)) {313log.finer("Cursor.getSystemCustomCursor(" + name + ") returned null");314}315return null;316}317318final String fileName =319systemCustomCursorProperties.getProperty(key);320321String localized = systemCustomCursorProperties.getProperty(prefix + DotNameSuffix);322323if (localized == null) localized = name;324325String hotspot = systemCustomCursorProperties.getProperty(prefix + DotHotspotSuffix);326327if (hotspot == null)328throw new AWTException("no hotspot property defined for cursor: " + name);329330StringTokenizer st = new StringTokenizer(hotspot, ",");331332if (st.countTokens() != 2)333throw new AWTException("failed to parse hotspot property for cursor: " + name);334335int x = 0;336int y = 0;337338try {339x = Integer.parseInt(st.nextToken());340y = Integer.parseInt(st.nextToken());341} catch (NumberFormatException nfe) {342throw new AWTException("failed to parse hotspot property for cursor: " + name);343}344345try {346final int fx = x;347final int fy = y;348final String flocalized = localized;349350cursor = java.security.AccessController.<Cursor>doPrivileged(351new java.security.PrivilegedExceptionAction<Cursor>() {352public Cursor run() throws Exception {353Toolkit toolkit = Toolkit.getDefaultToolkit();354Image image = toolkit.getImage(355systemCustomCursorDirPrefix + fileName);356return toolkit.createCustomCursor(357image, new Point(fx,fy), flocalized);358}359});360} catch (Exception e) {361throw new AWTException(362"Exception: " + e.getClass() + " " + e.getMessage() +363" occurred while creating cursor " + name);364}365366if (cursor == null) {367if (log.isLoggable(PlatformLogger.Level.FINER)) {368log.finer("Cursor.getSystemCustomCursor(" + name + ") returned null");369}370} else {371systemCustomCursors.put(name, cursor);372}373}374375return cursor;376}377378/**379* Return the system default cursor.380*/381static public Cursor getDefaultCursor() {382return getPredefinedCursor(Cursor.DEFAULT_CURSOR);383}384385/**386* Creates a new cursor object with the specified type.387* @param type the type of cursor388* @throws IllegalArgumentException if the specified cursor type389* is invalid390*/391@ConstructorProperties({"type"})392public Cursor(int type) {393if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {394throw new IllegalArgumentException("illegal cursor type");395}396this.type = type;397398// Lookup localized name.399name = Toolkit.getProperty(cursorProperties[type][0],400cursorProperties[type][1]);401}402403/**404* Creates a new custom cursor object with the specified name.<p>405* Note: this constructor should only be used by AWT implementations406* as part of their support for custom cursors. Applications should407* use Toolkit.createCustomCursor().408* @param name the user-visible name of the cursor.409* @see java.awt.Toolkit#createCustomCursor410*/411protected Cursor(String name) {412this.type = Cursor.CUSTOM_CURSOR;413this.name = name;414}415416/**417* Returns the type for this cursor.418*/419public int getType() {420return type;421}422423/**424* Returns the name of this cursor.425* @return a localized description of this cursor.426* @since 1.2427*/428public String getName() {429return name;430}431432/**433* Returns a string representation of this cursor.434* @return a string representation of this cursor.435* @since 1.2436*/437public String toString() {438return getClass().getName() + "[" + getName() + "]";439}440441/*442* load the cursor.properties file443*/444private static void loadSystemCustomCursorProperties() throws AWTException {445synchronized(systemCustomCursors) {446systemCustomCursorProperties = new Properties();447448try {449AccessController.<Object>doPrivileged(450new java.security.PrivilegedExceptionAction<Object>() {451public Object run() throws Exception {452FileInputStream fis = null;453try {454fis = new FileInputStream(455systemCustomCursorPropertiesFile);456systemCustomCursorProperties.load(fis);457} finally {458if (fis != null)459fis.close();460}461return null;462}463});464} catch (Exception e) {465systemCustomCursorProperties = null;466throw new AWTException("Exception: " + e.getClass() + " " +467e.getMessage() + " occurred while loading: " +468systemCustomCursorPropertiesFile);469}470}471}472473private native static void finalizeImpl(long pData);474}475476477