Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/awt/GlobalCursorManager.java
41152 views
1
/*
2
* Copyright (c) 1999, 2013, 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 sun.awt;
27
28
import java.awt.*;
29
import java.awt.event.InputEvent;
30
import java.awt.event.InvocationEvent;
31
32
/**
33
* A stateless class which responds to native mouse moves, Component resizes,
34
* Component moves, showing and hiding of Components, minimizing and
35
* maximizing of top level Windows, addition and removal of Components,
36
* and calls to setCursor().
37
*/
38
public abstract class GlobalCursorManager {
39
40
class NativeUpdater implements Runnable {
41
boolean pending = false;
42
43
public void run() {
44
boolean shouldUpdate = false;
45
synchronized (this) {
46
if (pending) {
47
pending = false;
48
shouldUpdate = true;
49
}
50
}
51
if (shouldUpdate) {
52
_updateCursor(false);
53
}
54
}
55
56
public void postIfNotPending(Component heavy, InvocationEvent in) {
57
boolean shouldPost = false;
58
synchronized (this) {
59
if (!pending) {
60
pending = shouldPost = true;
61
}
62
}
63
if (shouldPost) {
64
SunToolkit.postEvent(SunToolkit.targetToAppContext(heavy), in);
65
}
66
}
67
}
68
69
/**
70
* Use a singleton NativeUpdater for better performance. We cannot use
71
* a singleton InvocationEvent because we want each event to have a fresh
72
* timestamp.
73
*/
74
private final NativeUpdater nativeUpdater = new NativeUpdater();
75
76
/**
77
* The last time the cursor was updated, in milliseconds.
78
*/
79
private long lastUpdateMillis;
80
81
/**
82
* Locking object for synchronizing access to lastUpdateMillis. The VM
83
* does not guarantee atomicity of longs.
84
*/
85
private final Object lastUpdateLock = new Object();
86
87
/**
88
* Should be called for any activity at the Java level which may affect
89
* the global cursor, except for Java MOUSE_MOVED events.
90
*/
91
public void updateCursorImmediately() {
92
synchronized (nativeUpdater) {
93
nativeUpdater.pending = false;
94
}
95
_updateCursor(false);
96
}
97
98
/**
99
* Should be called in response to Java MOUSE_MOVED events. The update
100
* will be discarded if the InputEvent is outdated.
101
*
102
* @param e the InputEvent which triggered the cursor update.
103
*/
104
public void updateCursorImmediately(InputEvent e) {
105
boolean shouldUpdate;
106
synchronized (lastUpdateLock) {
107
shouldUpdate = (e.getWhen() >= lastUpdateMillis);
108
}
109
if (shouldUpdate) {
110
_updateCursor(true);
111
}
112
}
113
114
/**
115
* Should be called in response to a native mouse enter or native mouse
116
* button released message. Should not be called during a mouse drag.
117
*/
118
public void updateCursorLater(Component heavy) {
119
nativeUpdater.postIfNotPending(heavy, new InvocationEvent
120
(Toolkit.getDefaultToolkit(), nativeUpdater));
121
}
122
123
protected GlobalCursorManager() { }
124
125
/**
126
* Set the global cursor to the specified cursor. The component over
127
* which the Cursor current resides is provided as a convenience. Not
128
* all platforms may require the Component.
129
*/
130
protected abstract void setCursor(Component comp, Cursor cursor,
131
boolean useCache);
132
/**
133
* Returns the global cursor position, in screen coordinates.
134
*/
135
protected abstract void getCursorPos(Point p);
136
137
protected abstract Point getLocationOnScreen(Component com);
138
139
/**
140
* Returns the most specific, visible, heavyweight Component
141
* under the cursor. This method should return null iff the cursor is
142
* not over any Java Window.
143
*
144
* @param useCache If true, the implementation is free to use caching
145
* mechanisms because the Z-order, visibility, and enabled state of the
146
* Components has not changed. If false, the implementation should not
147
* make these assumptions.
148
*/
149
protected abstract Component findHeavyweightUnderCursor(boolean useCache);
150
151
/**
152
* Updates the global cursor. We apply a three-step scheme to cursor
153
* updates:<p>
154
*
155
* (1) InputEvent updates which are outdated are discarded by
156
* {@code updateCursorImmediately(InputEvent)}.<p>
157
*
158
* (2) If 'useCache' is true, the native code is free to use a cached
159
* value to determine the most specific, visible, enabled heavyweight
160
* because this update is occurring in response to a mouse move. If
161
* 'useCache' is false, the native code must perform a new search given
162
* the current mouse coordinates.
163
*
164
* (3) Once we have determined the most specific, visible, enabled
165
* heavyweight, we use findComponentAt to find the most specific, visible,
166
* enabled Component.
167
*/
168
private void _updateCursor(boolean useCache) {
169
170
synchronized (lastUpdateLock) {
171
lastUpdateMillis = System.currentTimeMillis();
172
}
173
174
Point queryPos = null, p = null;
175
Component comp;
176
177
try {
178
comp = findHeavyweightUnderCursor(useCache);
179
if (comp == null) {
180
updateCursorOutOfJava();
181
return;
182
}
183
184
if (comp instanceof Window) {
185
p = AWTAccessor.getComponentAccessor().getLocation(comp);
186
} else if (comp instanceof Container) {
187
p = getLocationOnScreen(comp);
188
}
189
if (p != null) {
190
queryPos = new Point();
191
getCursorPos(queryPos);
192
Component c = AWTAccessor.getContainerAccessor().
193
findComponentAt((Container) comp,
194
queryPos.x - p.x, queryPos.y - p.y, false);
195
196
// If findComponentAt returns null, then something bad has
197
// happened. For example, the heavyweight Component may
198
// have been hidden or disabled by another thread. In that
199
// case, we'll just use the originial heavyweight.
200
if (c != null) {
201
comp = c;
202
}
203
}
204
205
setCursor(comp, AWTAccessor.getComponentAccessor().getCursor(comp), useCache);
206
207
} catch (IllegalComponentStateException e) {
208
// Shouldn't happen, but if it does, abort.
209
}
210
}
211
212
protected void updateCursorOutOfJava() {
213
// Cursor is not over a Java Window. Do nothing...usually
214
// But we need to update it in case of grab on X.
215
}
216
}
217
218