Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/java/awt/Cursor.java
41152 views
1
/*
2
* Copyright (c) 1996, 2021, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.awt;
27
28
import java.beans.ConstructorProperties;
29
import java.io.InputStream;
30
import java.io.Serial;
31
import java.security.AccessController;
32
import java.security.PrivilegedAction;
33
import java.security.PrivilegedExceptionAction;
34
import java.util.Hashtable;
35
import java.util.Properties;
36
import java.util.StringTokenizer;
37
38
import sun.awt.AWTAccessor;
39
import sun.util.logging.PlatformLogger;
40
41
/**
42
* A class to encapsulate the bitmap representation of the mouse cursor.
43
*
44
* @see Component#setCursor
45
* @author Amy Fowler
46
*/
47
public class Cursor implements java.io.Serializable {
48
49
/**
50
* The default cursor type (gets set if no cursor is defined).
51
*/
52
public static final int DEFAULT_CURSOR = 0;
53
54
/**
55
* The crosshair cursor type.
56
*/
57
public static final int CROSSHAIR_CURSOR = 1;
58
59
/**
60
* The text cursor type.
61
*/
62
public static final int TEXT_CURSOR = 2;
63
64
/**
65
* The wait cursor type.
66
*/
67
public static final int WAIT_CURSOR = 3;
68
69
/**
70
* The south-west-resize cursor type.
71
*/
72
public static final int SW_RESIZE_CURSOR = 4;
73
74
/**
75
* The south-east-resize cursor type.
76
*/
77
public static final int SE_RESIZE_CURSOR = 5;
78
79
/**
80
* The north-west-resize cursor type.
81
*/
82
public static final int NW_RESIZE_CURSOR = 6;
83
84
/**
85
* The north-east-resize cursor type.
86
*/
87
public static final int NE_RESIZE_CURSOR = 7;
88
89
/**
90
* The north-resize cursor type.
91
*/
92
public static final int N_RESIZE_CURSOR = 8;
93
94
/**
95
* The south-resize cursor type.
96
*/
97
public static final int S_RESIZE_CURSOR = 9;
98
99
/**
100
* The west-resize cursor type.
101
*/
102
public static final int W_RESIZE_CURSOR = 10;
103
104
/**
105
* The east-resize cursor type.
106
*/
107
public static final int E_RESIZE_CURSOR = 11;
108
109
/**
110
* The hand cursor type.
111
*/
112
public static final int HAND_CURSOR = 12;
113
114
/**
115
* The move cursor type.
116
*/
117
public static final int MOVE_CURSOR = 13;
118
119
/**
120
* @deprecated As of JDK version 1.7, the {@link #getPredefinedCursor(int)}
121
* method should be used instead.
122
*/
123
@Deprecated
124
protected static Cursor[] predefined = new Cursor[14];
125
126
/**
127
* This field is a private replacement for 'predefined' array.
128
*/
129
private static final Cursor[] predefinedPrivate = new Cursor[14];
130
131
/* Localization names and default values */
132
static final String[][] cursorProperties = {
133
{ "AWT.DefaultCursor", "Default Cursor" },
134
{ "AWT.CrosshairCursor", "Crosshair Cursor" },
135
{ "AWT.TextCursor", "Text Cursor" },
136
{ "AWT.WaitCursor", "Wait Cursor" },
137
{ "AWT.SWResizeCursor", "Southwest Resize Cursor" },
138
{ "AWT.SEResizeCursor", "Southeast Resize Cursor" },
139
{ "AWT.NWResizeCursor", "Northwest Resize Cursor" },
140
{ "AWT.NEResizeCursor", "Northeast Resize Cursor" },
141
{ "AWT.NResizeCursor", "North Resize Cursor" },
142
{ "AWT.SResizeCursor", "South Resize Cursor" },
143
{ "AWT.WResizeCursor", "West Resize Cursor" },
144
{ "AWT.EResizeCursor", "East Resize Cursor" },
145
{ "AWT.HandCursor", "Hand Cursor" },
146
{ "AWT.MoveCursor", "Move Cursor" },
147
};
148
149
/**
150
* The chosen cursor type initially set to
151
* the {@code DEFAULT_CURSOR}.
152
*
153
* @serial
154
* @see #getType()
155
*/
156
int type = DEFAULT_CURSOR;
157
158
/**
159
* The type associated with all custom cursors.
160
*/
161
public static final int CUSTOM_CURSOR = -1;
162
163
/*
164
* hashtable, resource prefix, filename, and properties for custom cursors
165
* support
166
*/
167
private static final Hashtable<String,Cursor> systemCustomCursors = new Hashtable<>(1);
168
private static final String RESOURCE_PREFIX = "/sun/awt/resources/cursors/";
169
private static final String PROPERTIES_FILE = RESOURCE_PREFIX + "cursors.properties";
170
171
private static Properties systemCustomCursorProperties = null;
172
173
private static final String CURSOR_DOT_PREFIX = "Cursor.";
174
private static final String DOT_FILE_SUFFIX = ".File";
175
private static final String DOT_HOTSPOT_SUFFIX = ".HotSpot";
176
private static final String DOT_NAME_SUFFIX = ".Name";
177
178
/**
179
* Use serialVersionUID from JDK 1.1 for interoperability.
180
*/
181
@Serial
182
private static final long serialVersionUID = 8028237497568985504L;
183
184
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Cursor");
185
186
static {
187
/* ensure that the necessary native libraries are loaded */
188
Toolkit.loadLibraries();
189
if (!GraphicsEnvironment.isHeadless()) {
190
initIDs();
191
}
192
193
AWTAccessor.setCursorAccessor(
194
new AWTAccessor.CursorAccessor() {
195
public long getPData(Cursor cursor) {
196
return cursor.pData;
197
}
198
199
public void setPData(Cursor cursor, long pData) {
200
cursor.pData = pData;
201
}
202
203
public int getType(Cursor cursor) {
204
return cursor.type;
205
}
206
});
207
}
208
209
/**
210
* Initialize JNI field and method IDs for fields that may be
211
* accessed from C.
212
*/
213
private static native void initIDs();
214
215
/**
216
* Hook into native data.
217
*/
218
private transient long pData;
219
220
private transient Object anchor = new Object();
221
222
static class CursorDisposer implements sun.java2d.DisposerRecord {
223
volatile long pData;
224
public CursorDisposer(long pData) {
225
this.pData = pData;
226
}
227
public void dispose() {
228
if (pData != 0) {
229
finalizeImpl(pData);
230
}
231
}
232
}
233
transient CursorDisposer disposer;
234
private void setPData(long pData) {
235
this.pData = pData;
236
if (GraphicsEnvironment.isHeadless()) {
237
return;
238
}
239
if (disposer == null) {
240
disposer = new CursorDisposer(pData);
241
// anchor is null after deserialization
242
if (anchor == null) {
243
anchor = new Object();
244
}
245
sun.java2d.Disposer.addRecord(anchor, disposer);
246
} else {
247
disposer.pData = pData;
248
}
249
}
250
251
/**
252
* The user-visible name of the cursor.
253
*
254
* @serial
255
* @see #getName()
256
*/
257
protected String name;
258
259
/**
260
* Returns a cursor object with the specified predefined type.
261
*
262
* @param type the type of predefined cursor
263
* @return the specified predefined cursor
264
* @throws IllegalArgumentException if the specified cursor type is
265
* invalid
266
*/
267
public static Cursor getPredefinedCursor(int type) {
268
if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
269
throw new IllegalArgumentException("illegal cursor type");
270
}
271
Cursor c = predefinedPrivate[type];
272
if (c == null) {
273
predefinedPrivate[type] = c = new Cursor(type);
274
}
275
// fill 'predefined' array for backwards compatibility.
276
if (predefined[type] == null) {
277
predefined[type] = c;
278
}
279
return c;
280
}
281
282
/**
283
* Returns a system-specific custom cursor object matching the
284
* specified name. Cursor names are, for example: "Invalid.16x16"
285
*
286
* @param name a string describing the desired system-specific custom cursor
287
* @return the system specific custom cursor named
288
* @exception HeadlessException if
289
* {@code GraphicsEnvironment.isHeadless} returns true
290
* @exception AWTException in case of erroneous retrieving of the cursor
291
*/
292
public static Cursor getSystemCustomCursor(final String name)
293
throws AWTException, HeadlessException {
294
GraphicsEnvironment.checkHeadless();
295
Cursor cursor = systemCustomCursors.get(name);
296
297
if (cursor == null) {
298
synchronized(systemCustomCursors) {
299
if (systemCustomCursorProperties == null)
300
loadSystemCustomCursorProperties();
301
}
302
303
String prefix = CURSOR_DOT_PREFIX + name;
304
String key = prefix + DOT_FILE_SUFFIX;
305
306
if (!systemCustomCursorProperties.containsKey(key)) {
307
if (log.isLoggable(PlatformLogger.Level.FINER)) {
308
log.finer("Cursor.getSystemCustomCursor(" + name + ") returned null");
309
}
310
return null;
311
}
312
313
final String fileName =
314
systemCustomCursorProperties.getProperty(key);
315
316
final String localized = systemCustomCursorProperties.getProperty(
317
prefix + DOT_NAME_SUFFIX, name);
318
319
String hotspot = systemCustomCursorProperties.getProperty(prefix + DOT_HOTSPOT_SUFFIX);
320
321
if (hotspot == null)
322
throw new AWTException("no hotspot property defined for cursor: " + name);
323
324
StringTokenizer st = new StringTokenizer(hotspot, ",");
325
326
if (st.countTokens() != 2)
327
throw new AWTException("failed to parse hotspot property for cursor: " + name);
328
329
final Point hotPoint;
330
try {
331
hotPoint = new Point(Integer.parseInt(st.nextToken()),
332
Integer.parseInt(st.nextToken()));
333
} catch (NumberFormatException nfe) {
334
throw new AWTException("failed to parse hotspot property for cursor: " + name);
335
}
336
final Toolkit toolkit = Toolkit.getDefaultToolkit();
337
final String file = RESOURCE_PREFIX + fileName;
338
@SuppressWarnings("removal")
339
final InputStream in = AccessController.doPrivileged(
340
(PrivilegedAction<InputStream>) () -> {
341
return Cursor.class.getResourceAsStream(file);
342
});
343
try (in) {
344
Image image = toolkit.createImage(in.readAllBytes());
345
cursor = toolkit.createCustomCursor(image, hotPoint, localized);
346
} catch (Exception e) {
347
throw new AWTException(
348
"Exception: " + e.getClass() + " " + e.getMessage() +
349
" occurred while creating cursor " + name);
350
}
351
352
if (cursor == null) {
353
if (log.isLoggable(PlatformLogger.Level.FINER)) {
354
log.finer("Cursor.getSystemCustomCursor(" + name + ") returned null");
355
}
356
} else {
357
systemCustomCursors.put(name, cursor);
358
}
359
}
360
361
return cursor;
362
}
363
364
/**
365
* Return the system default cursor.
366
*
367
* @return the default cursor
368
*/
369
public static Cursor getDefaultCursor() {
370
return getPredefinedCursor(Cursor.DEFAULT_CURSOR);
371
}
372
373
/**
374
* Creates a new cursor object with the specified type.
375
* @param type the type of cursor
376
* @throws IllegalArgumentException if the specified cursor type
377
* is invalid
378
*/
379
@ConstructorProperties({"type"})
380
public Cursor(int type) {
381
if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
382
throw new IllegalArgumentException("illegal cursor type");
383
}
384
this.type = type;
385
386
// Lookup localized name.
387
name = Toolkit.getProperty(cursorProperties[type][0],
388
cursorProperties[type][1]);
389
}
390
391
/**
392
* Creates a new custom cursor object with the specified name.<p>
393
* Note: this constructor should only be used by AWT implementations
394
* as part of their support for custom cursors. Applications should
395
* use Toolkit.createCustomCursor().
396
* @param name the user-visible name of the cursor.
397
* @see java.awt.Toolkit#createCustomCursor
398
*/
399
protected Cursor(String name) {
400
this.type = Cursor.CUSTOM_CURSOR;
401
this.name = name;
402
}
403
404
/**
405
* Returns the type for this cursor.
406
*
407
* @return the cursor type
408
*/
409
public int getType() {
410
return type;
411
}
412
413
/**
414
* Returns the name of this cursor.
415
* @return a localized description of this cursor.
416
* @since 1.2
417
*/
418
public String getName() {
419
return name;
420
}
421
422
/**
423
* Returns a string representation of this cursor.
424
* @return a string representation of this cursor.
425
* @since 1.2
426
*/
427
public String toString() {
428
return getClass().getName() + "[" + getName() + "]";
429
}
430
431
/*
432
* load the cursor.properties file
433
*/
434
@SuppressWarnings("removal")
435
private static void loadSystemCustomCursorProperties() throws AWTException {
436
synchronized(systemCustomCursors) {
437
systemCustomCursorProperties = new Properties();
438
439
try {
440
AccessController.doPrivileged(
441
(PrivilegedExceptionAction<Object>) () -> {
442
try (InputStream is = Cursor.class
443
.getResourceAsStream(PROPERTIES_FILE)) {
444
systemCustomCursorProperties.load(is);
445
}
446
return null;
447
});
448
} catch (Exception e) {
449
systemCustomCursorProperties = null;
450
throw new AWTException("Exception: " + e.getClass() + " " +
451
e.getMessage() + " occurred while loading: " +
452
PROPERTIES_FILE);
453
}
454
}
455
}
456
457
private static native void finalizeImpl(long pData);
458
}
459
460