propane 2.7.2-java → 2.8.0.pre-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/CHANGELOG.md +1 -1
- data/README.md +10 -8
- data/Rakefile +1 -1
- data/lib/propane/app.rb +3 -3
- data/lib/propane/version.rb +1 -1
- data/lib/{processing-core.jar → propane-2.8.0.jar} +0 -0
- data/library/control_panel/control_panel.rb +3 -2
- data/pom.rb +89 -88
- data/pom.xml +75 -46
- data/propane.gemspec +1 -2
- data/src/main/java/japplemenubar/JAppleMenuBar.java +88 -0
- data/src/main/java/japplemenubar/libjAppleMenuBar.jnilib +0 -0
- data/src/{monkstone → main/java/monkstone}/ColorUtil.java +0 -0
- data/src/{monkstone → main/java/monkstone}/MathToolModule.java +0 -0
- data/src/{monkstone → main/java/monkstone}/PropaneLibrary.java +0 -0
- data/src/{monkstone → main/java/monkstone}/core/LibraryProxy.java +0 -0
- data/src/{monkstone → main/java/monkstone}/fastmath/Deglut.java +0 -0
- data/src/{monkstone → main/java/monkstone}/fastmath/package-info.java +0 -0
- data/src/{monkstone → main/java/monkstone}/filechooser/Chooser.java +0 -0
- data/src/{monkstone → main/java/monkstone}/noise/SimplexNoise.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/CustomHorizontalSlider.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/CustomVerticalSlider.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/SimpleHorizontalSlider.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/SimpleSlider.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/SimpleVerticalSlider.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/Slider.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/SliderBar.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/SliderGroup.java +0 -0
- data/src/{monkstone → main/java/monkstone}/slider/WheelHandler.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/AppRender.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/JRender.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/ShapeRender.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/package-info.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/vec2/Vec2.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/vec2/package-info.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/vec3/Vec3.java +0 -0
- data/src/{monkstone → main/java/monkstone}/vecmath/vec3/package-info.java +0 -0
- data/src/{monkstone → main/java/monkstone}/videoevent/VideoInterface.java +0 -0
- data/src/{monkstone → main/java/monkstone}/videoevent/package-info.java +0 -0
- data/src/main/java/processing/awt/PGraphicsJava2D.java +3029 -0
- data/src/main/java/processing/awt/PShapeJava2D.java +377 -0
- data/src/main/java/processing/awt/PSurfaceAWT.java +1567 -0
- data/src/main/java/processing/core/PApplet.java +15709 -0
- data/src/main/java/processing/core/PConstants.java +527 -0
- data/src/main/java/processing/core/PFont.java +1098 -0
- data/src/main/java/processing/core/PGraphics.java +8467 -0
- data/src/main/java/processing/core/PImage.java +3438 -0
- data/src/main/java/processing/core/PMatrix.java +208 -0
- data/src/main/java/processing/core/PMatrix2D.java +534 -0
- data/src/main/java/processing/core/PMatrix3D.java +877 -0
- data/src/main/java/processing/core/PShape.java +3445 -0
- data/src/main/java/processing/core/PShapeOBJ.java +469 -0
- data/src/main/java/processing/core/PShapeSVG.java +1787 -0
- data/src/main/java/processing/core/PStyle.java +63 -0
- data/src/main/java/processing/core/PSurface.java +161 -0
- data/src/main/java/processing/core/PSurfaceNone.java +374 -0
- data/src/main/java/processing/core/PVector.java +1063 -0
- data/src/main/java/processing/data/FloatDict.java +829 -0
- data/src/main/java/processing/data/FloatList.java +912 -0
- data/src/main/java/processing/data/IntDict.java +796 -0
- data/src/main/java/processing/data/IntList.java +913 -0
- data/src/main/java/processing/data/JSONArray.java +1260 -0
- data/src/main/java/processing/data/JSONObject.java +2282 -0
- data/src/main/java/processing/data/JSONTokener.java +435 -0
- data/src/main/java/processing/data/Sort.java +46 -0
- data/src/main/java/processing/data/StringDict.java +601 -0
- data/src/main/java/processing/data/StringList.java +775 -0
- data/src/main/java/processing/data/Table.java +4923 -0
- data/src/main/java/processing/data/TableRow.java +198 -0
- data/src/main/java/processing/data/XML.java +1149 -0
- data/src/main/java/processing/event/Event.java +125 -0
- data/src/main/java/processing/event/KeyEvent.java +70 -0
- data/src/main/java/processing/event/MouseEvent.java +149 -0
- data/src/main/java/processing/event/TouchEvent.java +57 -0
- data/src/main/java/processing/opengl/FontTexture.java +379 -0
- data/src/main/java/processing/opengl/FrameBuffer.java +503 -0
- data/src/main/java/processing/opengl/LinePath.java +623 -0
- data/src/main/java/processing/opengl/LineStroker.java +685 -0
- data/src/main/java/processing/opengl/PGL.java +3366 -0
- data/src/main/java/processing/opengl/PGraphics2D.java +615 -0
- data/src/main/java/processing/opengl/PGraphics3D.java +281 -0
- data/src/main/java/processing/opengl/PGraphicsOpenGL.java +13634 -0
- data/src/main/java/processing/opengl/PJOGL.java +1966 -0
- data/src/main/java/processing/opengl/PShader.java +1478 -0
- data/src/main/java/processing/opengl/PShapeOpenGL.java +5234 -0
- data/src/main/java/processing/opengl/PSurfaceJOGL.java +1315 -0
- data/src/main/java/processing/opengl/Texture.java +1670 -0
- data/src/main/java/processing/opengl/VertexBuffer.java +88 -0
- data/src/main/java/processing/opengl/cursors/arrow.png +0 -0
- data/src/main/java/processing/opengl/cursors/cross.png +0 -0
- data/src/main/java/processing/opengl/cursors/hand.png +0 -0
- data/src/main/java/processing/opengl/cursors/license.txt +27 -0
- data/src/main/java/processing/opengl/cursors/move.png +0 -0
- data/src/main/java/processing/opengl/cursors/text.png +0 -0
- data/src/main/java/processing/opengl/cursors/wait.png +0 -0
- data/src/main/java/processing/opengl/shaders/ColorFrag.glsl +32 -0
- data/src/main/java/processing/opengl/shaders/ColorVert.glsl +34 -0
- data/src/main/java/processing/opengl/shaders/LightFrag.glsl +33 -0
- data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +154 -0
- data/src/main/java/processing/opengl/shaders/LightVert.glsl +151 -0
- data/src/main/java/processing/opengl/shaders/LineFrag.glsl +32 -0
- data/src/main/java/processing/opengl/shaders/LineVert.glsl +100 -0
- data/src/main/java/processing/opengl/shaders/MaskFrag.glsl +40 -0
- data/src/main/java/processing/opengl/shaders/PointFrag.glsl +32 -0
- data/src/main/java/processing/opengl/shaders/PointVert.glsl +56 -0
- data/src/main/java/processing/opengl/shaders/TexFrag.glsl +37 -0
- data/src/main/java/processing/opengl/shaders/TexLightFrag.glsl +37 -0
- data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +160 -0
- data/src/main/java/processing/opengl/shaders/TexLightVert.glsl +157 -0
- data/src/main/java/processing/opengl/shaders/TexVert.glsl +38 -0
- data/src/main/resources/icon/icon-1024.png +0 -0
- data/src/main/resources/icon/icon-128.png +0 -0
- data/src/main/resources/icon/icon-16.png +0 -0
- data/src/main/resources/icon/icon-256.png +0 -0
- data/src/main/resources/icon/icon-32.png +0 -0
- data/src/main/resources/icon/icon-48.png +0 -0
- data/src/main/resources/icon/icon-512.png +0 -0
- data/src/main/resources/icon/icon-64.png +0 -0
- data/src/main/resources/license.txt +508 -0
- data/vendors/Rakefile +5 -20
- metadata +115 -33
- data/lib/propane.jar +0 -0
@@ -0,0 +1,1315 @@
|
|
1
|
+
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
2
|
+
|
3
|
+
/*
|
4
|
+
Part of the Processing project - http://processing.org
|
5
|
+
|
6
|
+
Copyright (c) 2012-15 The Processing Foundation
|
7
|
+
Copyright (c) 2004-12 Ben Fry and Casey Reas
|
8
|
+
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
9
|
+
|
10
|
+
This library is free software; you can redistribute it and/or
|
11
|
+
modify it under the terms of the GNU Lesser General Public
|
12
|
+
License as published by the Free Software Foundation, version 2.1.
|
13
|
+
|
14
|
+
This library is distributed in the hope that it will be useful,
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
17
|
+
Lesser General Public License for more details.
|
18
|
+
|
19
|
+
You should have received a copy of the GNU Lesser General
|
20
|
+
Public License along with this library; if not, write to the
|
21
|
+
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
22
|
+
Boston, MA 02111-1307 USA
|
23
|
+
*/
|
24
|
+
|
25
|
+
package processing.opengl;
|
26
|
+
|
27
|
+
import java.awt.Component;
|
28
|
+
import java.awt.GraphicsDevice;
|
29
|
+
import java.awt.GraphicsEnvironment;
|
30
|
+
import java.awt.Point;
|
31
|
+
import java.awt.Rectangle;
|
32
|
+
import java.awt.image.BufferedImage;
|
33
|
+
import java.awt.image.DataBufferInt;
|
34
|
+
import java.io.File;
|
35
|
+
import java.io.FileInputStream;
|
36
|
+
import java.io.IOException;
|
37
|
+
import java.io.InputStream;
|
38
|
+
import java.nio.ByteBuffer;
|
39
|
+
import java.util.HashMap;
|
40
|
+
import java.util.Map;
|
41
|
+
|
42
|
+
import javax.swing.ImageIcon;
|
43
|
+
|
44
|
+
import com.jogamp.common.util.IOUtil;
|
45
|
+
import com.jogamp.common.util.IOUtil.ClassResources;
|
46
|
+
import com.jogamp.nativewindow.NativeSurface;
|
47
|
+
import com.jogamp.nativewindow.ScalableSurface;
|
48
|
+
import com.jogamp.nativewindow.util.Dimension;
|
49
|
+
import com.jogamp.nativewindow.util.PixelFormat;
|
50
|
+
import com.jogamp.nativewindow.util.PixelRectangle;
|
51
|
+
import com.jogamp.opengl.GLAnimatorControl;
|
52
|
+
import com.jogamp.opengl.GLAutoDrawable;
|
53
|
+
import com.jogamp.opengl.GLCapabilities;
|
54
|
+
import com.jogamp.opengl.GLEventListener;
|
55
|
+
import com.jogamp.opengl.GLException;
|
56
|
+
import com.jogamp.opengl.GLProfile;
|
57
|
+
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
|
58
|
+
import com.jogamp.nativewindow.WindowClosingProtocol;
|
59
|
+
import com.jogamp.newt.Display;
|
60
|
+
import com.jogamp.newt.Display.PointerIcon;
|
61
|
+
import com.jogamp.newt.NewtFactory;
|
62
|
+
import com.jogamp.newt.Screen;
|
63
|
+
import com.jogamp.newt.awt.NewtCanvasAWT;
|
64
|
+
import com.jogamp.newt.event.InputEvent;
|
65
|
+
import com.jogamp.newt.opengl.GLWindow;
|
66
|
+
import com.jogamp.opengl.util.FPSAnimator;
|
67
|
+
|
68
|
+
|
69
|
+
import processing.core.PApplet;
|
70
|
+
import processing.core.PConstants;
|
71
|
+
import processing.core.PGraphics;
|
72
|
+
import processing.core.PImage;
|
73
|
+
import processing.core.PSurface;
|
74
|
+
import processing.event.KeyEvent;
|
75
|
+
import processing.event.MouseEvent;
|
76
|
+
|
77
|
+
|
78
|
+
public class PSurfaceJOGL implements PSurface {
|
79
|
+
/** Selected GL profile */
|
80
|
+
public static GLProfile profile;
|
81
|
+
|
82
|
+
public PJOGL pgl;
|
83
|
+
|
84
|
+
protected GLWindow window;
|
85
|
+
protected FPSAnimator animator;
|
86
|
+
protected Rectangle screenRect;
|
87
|
+
|
88
|
+
private Thread drawExceptionHandler;
|
89
|
+
|
90
|
+
protected PApplet sketch;
|
91
|
+
protected PGraphics graphics;
|
92
|
+
|
93
|
+
protected int sketchWidth0;
|
94
|
+
protected int sketchHeight0;
|
95
|
+
protected int sketchWidth;
|
96
|
+
protected int sketchHeight;
|
97
|
+
|
98
|
+
protected Display display;
|
99
|
+
protected Screen screen;
|
100
|
+
protected Rectangle displayRect;
|
101
|
+
protected Throwable drawException;
|
102
|
+
private final Object drawExceptionMutex = new Object();
|
103
|
+
|
104
|
+
protected NewtCanvasAWT canvas;
|
105
|
+
|
106
|
+
protected int windowScaleFactor;
|
107
|
+
|
108
|
+
protected float[] currentPixelScale = {0, 0};
|
109
|
+
|
110
|
+
protected boolean external = false;
|
111
|
+
|
112
|
+
public PSurfaceJOGL(PGraphics graphics) {
|
113
|
+
this.graphics = graphics;
|
114
|
+
this.pgl = (PJOGL) ((PGraphicsOpenGL)graphics).pgl;
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
public void initOffscreen(PApplet sketch) {
|
119
|
+
this.sketch = sketch;
|
120
|
+
|
121
|
+
sketchWidth = sketch.sketchWidth();
|
122
|
+
sketchHeight = sketch.sketchHeight();
|
123
|
+
|
124
|
+
if (window != null) {
|
125
|
+
canvas = new NewtCanvasAWT(window);
|
126
|
+
canvas.setBounds(0, 0, window.getWidth(), window.getHeight());
|
127
|
+
canvas.setFocusable(true);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
|
132
|
+
public void initFrame(PApplet sketch) {
|
133
|
+
this.sketch = sketch;
|
134
|
+
initIcons();
|
135
|
+
initDisplay();
|
136
|
+
initGL();
|
137
|
+
initWindow();
|
138
|
+
initListeners();
|
139
|
+
initAnimator();
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
public Object getNative() {
|
144
|
+
return window;
|
145
|
+
}
|
146
|
+
|
147
|
+
|
148
|
+
protected void initDisplay() {
|
149
|
+
display = NewtFactory.createDisplay(null);
|
150
|
+
display.addReference();
|
151
|
+
screen = NewtFactory.createScreen(display, 0);
|
152
|
+
screen.addReference();
|
153
|
+
|
154
|
+
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
155
|
+
GraphicsDevice[] awtDevices = environment.getScreenDevices();
|
156
|
+
|
157
|
+
GraphicsDevice awtDisplayDevice = null;
|
158
|
+
int displayNum = sketch.sketchDisplay();
|
159
|
+
if (displayNum > 0) { // if -1, use the default device
|
160
|
+
if (displayNum <= awtDevices.length) {
|
161
|
+
awtDisplayDevice = awtDevices[displayNum-1];
|
162
|
+
} else {
|
163
|
+
System.err.format("Display %d does not exist, " +
|
164
|
+
"using the default display instead.%n", displayNum);
|
165
|
+
for (int i = 0; i < awtDevices.length; i++) {
|
166
|
+
System.err.format("Display %d is %s%n", i+1, awtDevices[i]);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
} else if (0 < awtDevices.length) {
|
170
|
+
awtDisplayDevice = awtDevices[0];
|
171
|
+
}
|
172
|
+
|
173
|
+
if (awtDisplayDevice == null) {
|
174
|
+
awtDisplayDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
|
175
|
+
}
|
176
|
+
|
177
|
+
displayRect = awtDisplayDevice.getDefaultConfiguration().getBounds();
|
178
|
+
}
|
179
|
+
|
180
|
+
|
181
|
+
protected void initGL() {
|
182
|
+
// System.out.println("*******************************");
|
183
|
+
if (profile == null) {
|
184
|
+
if (PJOGL.profile == 1) {
|
185
|
+
try {
|
186
|
+
profile = GLProfile.getGL2ES1();
|
187
|
+
} catch (GLException ex) {
|
188
|
+
profile = GLProfile.getMaxFixedFunc(true);
|
189
|
+
}
|
190
|
+
} else if (PJOGL.profile == 2) {
|
191
|
+
try {
|
192
|
+
profile = GLProfile.getGL2ES2();
|
193
|
+
|
194
|
+
// workaround for https://jogamp.org/bugzilla/show_bug.cgi?id=1347
|
195
|
+
if (!profile.isHardwareRasterizer()) {
|
196
|
+
GLProfile hardware = GLProfile.getMaxProgrammable(true);
|
197
|
+
if (hardware.isGL2ES2()) {
|
198
|
+
profile = hardware;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
} catch (GLException ex) {
|
203
|
+
profile = GLProfile.getMaxProgrammable(true);
|
204
|
+
}
|
205
|
+
} else if (PJOGL.profile == 3) {
|
206
|
+
try {
|
207
|
+
profile = GLProfile.getGL2GL3();
|
208
|
+
} catch (GLException ex) {
|
209
|
+
profile = GLProfile.getMaxProgrammable(true);
|
210
|
+
}
|
211
|
+
if (!profile.isGL3()) {
|
212
|
+
PGraphics.showWarning("Requested profile GL3 but is not available, got: " + profile);
|
213
|
+
}
|
214
|
+
} else if (PJOGL.profile == 4) {
|
215
|
+
try {
|
216
|
+
profile = GLProfile.getGL4ES3();
|
217
|
+
} catch (GLException ex) {
|
218
|
+
profile = GLProfile.getMaxProgrammable(true);
|
219
|
+
}
|
220
|
+
if (!profile.isGL4()) {
|
221
|
+
PGraphics.showWarning("Requested profile GL4 but is not available, got: " + profile);
|
222
|
+
}
|
223
|
+
} else throw new RuntimeException(PGL.UNSUPPORTED_GLPROF_ERROR);
|
224
|
+
}
|
225
|
+
|
226
|
+
// Setting up the desired capabilities;
|
227
|
+
GLCapabilities caps = new GLCapabilities(profile);
|
228
|
+
caps.setAlphaBits(PGL.REQUESTED_ALPHA_BITS);
|
229
|
+
caps.setDepthBits(PGL.REQUESTED_DEPTH_BITS);
|
230
|
+
caps.setStencilBits(PGL.REQUESTED_STENCIL_BITS);
|
231
|
+
|
232
|
+
// caps.setPBuffer(false);
|
233
|
+
// caps.setFBO(false);
|
234
|
+
|
235
|
+
// pgl.reqNumSamples = PGL.smoothToSamples(graphics.smooth);
|
236
|
+
caps.setSampleBuffers(true);
|
237
|
+
caps.setNumSamples(PGL.smoothToSamples(graphics.smooth));
|
238
|
+
caps.setBackgroundOpaque(true);
|
239
|
+
caps.setOnscreen(true);
|
240
|
+
pgl.setCaps(caps);
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
protected void initWindow() {
|
245
|
+
window = GLWindow.create(screen, pgl.getCaps());
|
246
|
+
|
247
|
+
// Make sure that we pass the window close through to exit(), otherwise
|
248
|
+
// we're likely to have OpenGL try to shut down halfway through rendering
|
249
|
+
// a frame. Particularly problematic for complex/slow apps.
|
250
|
+
// https://github.com/processing/processing/issues/4690
|
251
|
+
window.setDefaultCloseOperation(WindowClosingProtocol.WindowClosingMode.DO_NOTHING_ON_CLOSE);
|
252
|
+
|
253
|
+
// if (displayDevice == null) {
|
254
|
+
//
|
255
|
+
//
|
256
|
+
// } else {
|
257
|
+
// window = GLWindow.create(displayDevice.getScreen(), pgl.getCaps());
|
258
|
+
// }
|
259
|
+
|
260
|
+
windowScaleFactor = PApplet.platform == PConstants.MACOSX ?
|
261
|
+
1 : sketch.pixelDensity;
|
262
|
+
|
263
|
+
boolean spanDisplays = sketch.sketchDisplay() == PConstants.SPAN;
|
264
|
+
screenRect = spanDisplays ?
|
265
|
+
new Rectangle(screen.getX(), screen.getY(), screen.getWidth(), screen.getHeight()) :
|
266
|
+
new Rectangle((int) displayRect.getX(), (int) displayRect.getY(),
|
267
|
+
(int) displayRect.getWidth(),
|
268
|
+
(int) displayRect.getHeight());
|
269
|
+
|
270
|
+
// Set the displayWidth/Height variables inside PApplet, so that they're
|
271
|
+
// usable and can even be returned by the sketchWidth()/Height() methods.
|
272
|
+
sketch.displayWidth = screenRect.width;
|
273
|
+
sketch.displayHeight = screenRect.height;
|
274
|
+
|
275
|
+
sketchWidth0 = sketch.sketchWidth();
|
276
|
+
sketchHeight0 = sketch.sketchHeight();
|
277
|
+
|
278
|
+
/*
|
279
|
+
// Trying to fix
|
280
|
+
// https://github.com/processing/processing/issues/3401
|
281
|
+
if (sketch.displayWidth < sketch.width ||
|
282
|
+
sketch.displayHeight < sketch.height) {
|
283
|
+
int w = sketch.width;
|
284
|
+
int h = sketch.height;
|
285
|
+
if (sketch.displayWidth < w) {
|
286
|
+
w = sketch.displayWidth;
|
287
|
+
}
|
288
|
+
if (sketch.displayHeight < h) {
|
289
|
+
h = sketch.displayHeight;
|
290
|
+
}
|
291
|
+
// sketch.setSize(w, h - 22 - 22);
|
292
|
+
// graphics.setSize(w, h - 22 - 22);
|
293
|
+
System.err.println("setting width/height to " + w + " " + h);
|
294
|
+
}
|
295
|
+
*/
|
296
|
+
|
297
|
+
sketchWidth = sketch.sketchWidth();
|
298
|
+
sketchHeight = sketch.sketchHeight();
|
299
|
+
// System.out.println("init: " + sketchWidth + " " + sketchHeight);
|
300
|
+
|
301
|
+
boolean fullScreen = sketch.sketchFullScreen();
|
302
|
+
// Removing the section below because sometimes people want to do the
|
303
|
+
// full screen size in a window, and it also breaks insideSettings().
|
304
|
+
// With 3.x, fullScreen() is so easy, that it's just better that way.
|
305
|
+
// https://github.com/processing/processing/issues/3545
|
306
|
+
/*
|
307
|
+
// Sketch has already requested to be the same as the screen's
|
308
|
+
// width and height, so let's roll with full screen mode.
|
309
|
+
if (screenRect.width == sketchWidth &&
|
310
|
+
screenRect.height == sketchHeight) {
|
311
|
+
fullScreen = true;
|
312
|
+
sketch.fullScreen();
|
313
|
+
}
|
314
|
+
*/
|
315
|
+
|
316
|
+
if (fullScreen || spanDisplays) {
|
317
|
+
sketchWidth = screenRect.width / windowScaleFactor;
|
318
|
+
sketchHeight = screenRect.height / windowScaleFactor;
|
319
|
+
}
|
320
|
+
|
321
|
+
sketch.setSize(sketchWidth, sketchHeight);
|
322
|
+
|
323
|
+
float[] reqSurfacePixelScale;
|
324
|
+
if (graphics.is2X() && PApplet.platform == PConstants.MACOSX) {
|
325
|
+
// Retina
|
326
|
+
reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE,
|
327
|
+
ScalableSurface.AUTOMAX_PIXELSCALE };
|
328
|
+
} else {
|
329
|
+
// Non-retina
|
330
|
+
reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE,
|
331
|
+
ScalableSurface.IDENTITY_PIXELSCALE };
|
332
|
+
}
|
333
|
+
window.setSurfaceScale(reqSurfacePixelScale);
|
334
|
+
window.setSize(sketchWidth * windowScaleFactor, sketchHeight * windowScaleFactor);
|
335
|
+
window.setResizable(false);
|
336
|
+
setSize(sketchWidth, sketchHeight);
|
337
|
+
if (fullScreen) {
|
338
|
+
PApplet.hideMenuBar();
|
339
|
+
if (spanDisplays) {
|
340
|
+
window.setFullscreen(screen.getMonitorDevices());
|
341
|
+
} else {
|
342
|
+
window.setUndecorated(true);
|
343
|
+
window.setTopLevelPosition((int) displayRect.getX(), (int) displayRect.getY());
|
344
|
+
window.setTopLevelSize((int) displayRect.getWidth(), (int) displayRect.getHeight());
|
345
|
+
}
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
|
350
|
+
protected void initListeners() {
|
351
|
+
NEWTMouseListener mouseListener = new NEWTMouseListener();
|
352
|
+
window.addMouseListener(mouseListener);
|
353
|
+
NEWTKeyListener keyListener = new NEWTKeyListener();
|
354
|
+
window.addKeyListener(keyListener);
|
355
|
+
NEWTWindowListener winListener = new NEWTWindowListener();
|
356
|
+
window.addWindowListener(winListener);
|
357
|
+
|
358
|
+
DrawListener drawlistener = new DrawListener();
|
359
|
+
window.addGLEventListener(drawlistener);
|
360
|
+
}
|
361
|
+
|
362
|
+
|
363
|
+
protected void initAnimator() {
|
364
|
+
if (PApplet.platform == PConstants.WINDOWS) {
|
365
|
+
// Force Windows to keep timer resolution high by
|
366
|
+
// sleeping for time which is not a multiple of 10 ms.
|
367
|
+
// See section "Clocks and Timers on Windows":
|
368
|
+
// https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks
|
369
|
+
Thread highResTimerThread = new Thread(() -> {
|
370
|
+
try {
|
371
|
+
Thread.sleep(Long.MAX_VALUE);
|
372
|
+
} catch (InterruptedException ignore) { }
|
373
|
+
}, "HighResTimerThread");
|
374
|
+
highResTimerThread.setDaemon(true);
|
375
|
+
highResTimerThread.start();
|
376
|
+
}
|
377
|
+
|
378
|
+
animator = new FPSAnimator(window, 60);
|
379
|
+
drawException = null;
|
380
|
+
animator.setUncaughtExceptionHandler(new GLAnimatorControl.UncaughtExceptionHandler() {
|
381
|
+
@Override
|
382
|
+
public void uncaughtException(final GLAnimatorControl animator,
|
383
|
+
final GLAutoDrawable drawable,
|
384
|
+
final Throwable cause) {
|
385
|
+
synchronized (drawExceptionMutex) {
|
386
|
+
drawException = cause;
|
387
|
+
drawExceptionMutex.notify();
|
388
|
+
}
|
389
|
+
}
|
390
|
+
});
|
391
|
+
|
392
|
+
drawExceptionHandler = new Thread(new Runnable() {
|
393
|
+
public void run() {
|
394
|
+
synchronized (drawExceptionMutex) {
|
395
|
+
try {
|
396
|
+
while (drawException == null) {
|
397
|
+
drawExceptionMutex.wait();
|
398
|
+
}
|
399
|
+
// System.err.println("Caught exception: " + drawException.getMessage());
|
400
|
+
if (drawException != null) {
|
401
|
+
Throwable cause = drawException.getCause();
|
402
|
+
if (cause instanceof ThreadDeath) {
|
403
|
+
// System.out.println("caught ThreadDeath");
|
404
|
+
// throw (ThreadDeath)cause;
|
405
|
+
} else if (cause instanceof RuntimeException) {
|
406
|
+
throw (RuntimeException) cause;
|
407
|
+
} else if (cause instanceof UnsatisfiedLinkError) {
|
408
|
+
throw new UnsatisfiedLinkError(cause.getMessage());
|
409
|
+
} else if (cause == null) {
|
410
|
+
throw new RuntimeException(drawException.getMessage());
|
411
|
+
} else {
|
412
|
+
throw new RuntimeException(cause);
|
413
|
+
}
|
414
|
+
}
|
415
|
+
} catch (InterruptedException e) {
|
416
|
+
return;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
}
|
420
|
+
});
|
421
|
+
drawExceptionHandler.start();
|
422
|
+
}
|
423
|
+
|
424
|
+
|
425
|
+
@Override
|
426
|
+
public void setTitle(final String title) {
|
427
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
428
|
+
@Override
|
429
|
+
public void run() {
|
430
|
+
window.setTitle(title);
|
431
|
+
}
|
432
|
+
});
|
433
|
+
}
|
434
|
+
|
435
|
+
|
436
|
+
@Override
|
437
|
+
public void setVisible(final boolean visible) {
|
438
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
439
|
+
@Override
|
440
|
+
public void run() {
|
441
|
+
window.setVisible(visible);
|
442
|
+
}
|
443
|
+
});
|
444
|
+
}
|
445
|
+
|
446
|
+
|
447
|
+
@Override
|
448
|
+
public void setResizable(final boolean resizable) {
|
449
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
450
|
+
@Override
|
451
|
+
public void run() {
|
452
|
+
window.setResizable(resizable);
|
453
|
+
}
|
454
|
+
});
|
455
|
+
}
|
456
|
+
|
457
|
+
|
458
|
+
public void setIcon(PImage icon) {
|
459
|
+
PGraphics.showWarning("Window icons for OpenGL sketches can only be set in settings()\n" +
|
460
|
+
"using PJOGL.setIcon(filename).");
|
461
|
+
}
|
462
|
+
|
463
|
+
|
464
|
+
@Override
|
465
|
+
public void setAlwaysOnTop(final boolean always) {
|
466
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
467
|
+
@Override
|
468
|
+
public void run() {
|
469
|
+
window.setAlwaysOnTop(always);
|
470
|
+
}
|
471
|
+
});
|
472
|
+
}
|
473
|
+
|
474
|
+
|
475
|
+
protected void initIcons() {
|
476
|
+
IOUtil.ClassResources res = null;
|
477
|
+
if (PJOGL.icons == null || PJOGL.icons.length == 0) {
|
478
|
+
// Default Processing icons
|
479
|
+
final int[] sizes = { 16, 32, 48, 64, 128, 256, 512 };
|
480
|
+
String[] iconImages = new String[sizes.length];
|
481
|
+
for (int i = 0; i < sizes.length; i++) {
|
482
|
+
iconImages[i] = "/icon/icon-" + sizes[i] + ".png";
|
483
|
+
}
|
484
|
+
res = new ClassResources(iconImages,
|
485
|
+
PApplet.class.getClassLoader(),
|
486
|
+
PApplet.class);
|
487
|
+
} else {
|
488
|
+
// Loading custom icons from user-provided files.
|
489
|
+
String[] iconImages = new String[PJOGL.icons.length];
|
490
|
+
for (int i = 0; i < PJOGL.icons.length; i++) {
|
491
|
+
iconImages[i] = resourceFilename(PJOGL.icons[i]);
|
492
|
+
}
|
493
|
+
|
494
|
+
res = new ClassResources(iconImages,
|
495
|
+
sketch.getClass().getClassLoader(),
|
496
|
+
sketch.getClass());
|
497
|
+
}
|
498
|
+
NewtFactory.setWindowIcons(res);
|
499
|
+
}
|
500
|
+
|
501
|
+
|
502
|
+
@SuppressWarnings("resource")
|
503
|
+
private String resourceFilename(String filename) {
|
504
|
+
// The code below comes from PApplet.createInputRaw() with a few adaptations
|
505
|
+
InputStream stream = null;
|
506
|
+
try {
|
507
|
+
// First see if it's in a data folder. This may fail by throwing
|
508
|
+
// a SecurityException. If so, this whole block will be skipped.
|
509
|
+
File file = new File(sketch.dataPath(filename));
|
510
|
+
if (!file.exists()) {
|
511
|
+
// next see if it's just in the sketch folder
|
512
|
+
file = sketch.sketchFile(filename);
|
513
|
+
}
|
514
|
+
|
515
|
+
if (file.exists() && !file.isDirectory()) {
|
516
|
+
try {
|
517
|
+
// handle case sensitivity check
|
518
|
+
String filePath = file.getCanonicalPath();
|
519
|
+
String filenameActual = new File(filePath).getName();
|
520
|
+
// make sure there isn't a subfolder prepended to the name
|
521
|
+
String filenameShort = new File(filename).getName();
|
522
|
+
// if the actual filename is the same, but capitalized
|
523
|
+
// differently, warn the user.
|
524
|
+
//if (filenameActual.equalsIgnoreCase(filenameShort) &&
|
525
|
+
//!filenameActual.equals(filenameShort)) {
|
526
|
+
if (!filenameActual.equals(filenameShort)) {
|
527
|
+
throw new RuntimeException("This file is named " +
|
528
|
+
filenameActual + " not " +
|
529
|
+
filename + ". Rename the file " +
|
530
|
+
"or change your code.");
|
531
|
+
}
|
532
|
+
} catch (IOException e) { }
|
533
|
+
}
|
534
|
+
|
535
|
+
stream = new FileInputStream(file);
|
536
|
+
if (stream != null) {
|
537
|
+
stream.close();
|
538
|
+
return file.getCanonicalPath();
|
539
|
+
}
|
540
|
+
|
541
|
+
// have to break these out because a general Exception might
|
542
|
+
// catch the RuntimeException being thrown above
|
543
|
+
} catch (IOException ioe) {
|
544
|
+
} catch (SecurityException se) { }
|
545
|
+
|
546
|
+
ClassLoader cl = sketch.getClass().getClassLoader();
|
547
|
+
|
548
|
+
try {
|
549
|
+
// by default, data files are exported to the root path of the jar.
|
550
|
+
// (not the data folder) so check there first.
|
551
|
+
stream = cl.getResourceAsStream("data/" + filename);
|
552
|
+
if (stream != null) {
|
553
|
+
String cn = stream.getClass().getName();
|
554
|
+
// this is an irritation of sun's java plug-in, which will return
|
555
|
+
// a non-null stream for an object that doesn't exist. like all good
|
556
|
+
// things, this is probably introduced in java 1.5. awesome!
|
557
|
+
// http://dev.processing.org/bugs/show_bug.cgi?id=359
|
558
|
+
if (!cn.equals("sun.plugin.cache.EmptyInputStream")) {
|
559
|
+
stream.close();
|
560
|
+
return "data/" + filename;
|
561
|
+
}
|
562
|
+
}
|
563
|
+
|
564
|
+
// When used with an online script, also need to check without the
|
565
|
+
// data folder, in case it's not in a subfolder called 'data'.
|
566
|
+
// http://dev.processing.org/bugs/show_bug.cgi?id=389
|
567
|
+
stream = cl.getResourceAsStream(filename);
|
568
|
+
if (stream != null) {
|
569
|
+
String cn = stream.getClass().getName();
|
570
|
+
if (!cn.equals("sun.plugin.cache.EmptyInputStream")) {
|
571
|
+
stream.close();
|
572
|
+
return filename;
|
573
|
+
}
|
574
|
+
}
|
575
|
+
} catch (IOException e) { }
|
576
|
+
|
577
|
+
try {
|
578
|
+
// attempt to load from a local file, used when running as
|
579
|
+
// an application, or as a signed applet
|
580
|
+
try { // first try to catch any security exceptions
|
581
|
+
try {
|
582
|
+
String path = sketch.dataPath(filename);
|
583
|
+
stream = new FileInputStream(path);
|
584
|
+
if (stream != null) {
|
585
|
+
stream.close();
|
586
|
+
return path;
|
587
|
+
}
|
588
|
+
} catch (IOException e2) { }
|
589
|
+
|
590
|
+
try {
|
591
|
+
String path = sketch.sketchPath(filename);
|
592
|
+
stream = new FileInputStream(path);
|
593
|
+
if (stream != null) {
|
594
|
+
stream.close();
|
595
|
+
return path;
|
596
|
+
}
|
597
|
+
} catch (Exception e) { } // ignored
|
598
|
+
|
599
|
+
try {
|
600
|
+
stream = new FileInputStream(filename);
|
601
|
+
if (stream != null) {
|
602
|
+
stream.close();
|
603
|
+
return filename;
|
604
|
+
}
|
605
|
+
} catch (IOException e1) { }
|
606
|
+
|
607
|
+
} catch (SecurityException se) { } // online, whups
|
608
|
+
|
609
|
+
} catch (Exception e) {
|
610
|
+
//die(e.getMessage(), e);
|
611
|
+
e.printStackTrace();
|
612
|
+
}
|
613
|
+
|
614
|
+
return "";
|
615
|
+
}
|
616
|
+
|
617
|
+
|
618
|
+
@Override
|
619
|
+
public void placeWindow(int[] location, int[] editorLocation) {
|
620
|
+
|
621
|
+
if (sketch.sketchFullScreen()) {
|
622
|
+
return;
|
623
|
+
}
|
624
|
+
|
625
|
+
int x = window.getX() - window.getInsets().getLeftWidth();
|
626
|
+
int y = window.getY() - window.getInsets().getTopHeight();
|
627
|
+
int w = window.getWidth() + window.getInsets().getTotalWidth();
|
628
|
+
int h = window.getHeight() + window.getInsets().getTotalHeight();
|
629
|
+
|
630
|
+
if (location != null) {
|
631
|
+
// System.err.println("place window at " + location[0] + ", " + location[1]);
|
632
|
+
window.setTopLevelPosition(location[0], location[1]);
|
633
|
+
|
634
|
+
} else if (editorLocation != null) {
|
635
|
+
// System.err.println("place window at editor location " + editorLocation[0] + ", " + editorLocation[1]);
|
636
|
+
int locationX = editorLocation[0] - 20;
|
637
|
+
int locationY = editorLocation[1];
|
638
|
+
|
639
|
+
if (locationX - w > 10) {
|
640
|
+
// if it fits to the left of the window
|
641
|
+
window.setTopLevelPosition(locationX - w, locationY);
|
642
|
+
|
643
|
+
} else { // doesn't fit
|
644
|
+
/*
|
645
|
+
// if it fits inside the editor window,
|
646
|
+
// offset slightly from upper lefthand corner
|
647
|
+
// so that it's plunked inside the text area
|
648
|
+
locationX = editorLocation[0] + 66;
|
649
|
+
locationY = editorLocation[1] + 66;
|
650
|
+
|
651
|
+
if ((locationX + w > sketch.displayWidth - 33) ||
|
652
|
+
(locationY + h > sketch.displayHeight - 33)) {
|
653
|
+
// otherwise center on screen
|
654
|
+
*/
|
655
|
+
locationX = (sketch.displayWidth - w) / 2;
|
656
|
+
locationY = (sketch.displayHeight - h) / 2;
|
657
|
+
/*
|
658
|
+
}
|
659
|
+
*/
|
660
|
+
window.setTopLevelPosition(locationX, locationY);
|
661
|
+
}
|
662
|
+
} else { // just center on screen
|
663
|
+
// Can't use frame.setLocationRelativeTo(null) because it sends the
|
664
|
+
// frame to the main display, which undermines the --display setting.
|
665
|
+
window.setTopLevelPosition(screenRect.x + (screenRect.width - sketchWidth) / 2,
|
666
|
+
screenRect.y + (screenRect.height - sketchHeight) / 2);
|
667
|
+
}
|
668
|
+
|
669
|
+
Point frameLoc = new Point(x, y);
|
670
|
+
if (frameLoc.y < 0) {
|
671
|
+
// Windows actually allows you to place frames where they can't be
|
672
|
+
// closed. Awesome. http://dev.processing.org/bugs/show_bug.cgi?id=1508
|
673
|
+
window.setTopLevelPosition(frameLoc.x, 30);
|
674
|
+
}
|
675
|
+
}
|
676
|
+
|
677
|
+
|
678
|
+
public void placePresent(int stopColor) {
|
679
|
+
float scale = getPixelScale();
|
680
|
+
pgl.initPresentMode(0.5f * (screenRect.width/scale - sketchWidth),
|
681
|
+
0.5f * (screenRect.height/scale - sketchHeight), stopColor);
|
682
|
+
PApplet.hideMenuBar();
|
683
|
+
|
684
|
+
window.setUndecorated(true);
|
685
|
+
window.setTopLevelPosition((int) displayRect.getX(), (int) displayRect.getY());
|
686
|
+
window.setTopLevelSize((int) displayRect.getWidth(), (int) displayRect.getHeight());
|
687
|
+
}
|
688
|
+
|
689
|
+
|
690
|
+
public void setupExternalMessages() {
|
691
|
+
external = true;
|
692
|
+
}
|
693
|
+
|
694
|
+
|
695
|
+
public void startThread() {
|
696
|
+
if (animator != null) {
|
697
|
+
animator.start();
|
698
|
+
}
|
699
|
+
}
|
700
|
+
|
701
|
+
|
702
|
+
public void pauseThread() {
|
703
|
+
if (animator != null) {
|
704
|
+
animator.pause();
|
705
|
+
}
|
706
|
+
}
|
707
|
+
|
708
|
+
|
709
|
+
public void resumeThread() {
|
710
|
+
if (animator != null) {
|
711
|
+
animator.resume();
|
712
|
+
}
|
713
|
+
}
|
714
|
+
|
715
|
+
|
716
|
+
public boolean stopThread() {
|
717
|
+
if (drawExceptionHandler != null) {
|
718
|
+
drawExceptionHandler.interrupt();
|
719
|
+
drawExceptionHandler = null;
|
720
|
+
}
|
721
|
+
if (animator != null) {
|
722
|
+
return animator.stop();
|
723
|
+
} else {
|
724
|
+
return false;
|
725
|
+
}
|
726
|
+
}
|
727
|
+
|
728
|
+
|
729
|
+
public boolean isStopped() {
|
730
|
+
if (animator != null) {
|
731
|
+
return !animator.isAnimating();
|
732
|
+
} else {
|
733
|
+
return true;
|
734
|
+
}
|
735
|
+
}
|
736
|
+
|
737
|
+
|
738
|
+
public void setLocation(final int x, final int y) {
|
739
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
740
|
+
@Override
|
741
|
+
public void run() {
|
742
|
+
window.setTopLevelPosition(x, y);
|
743
|
+
}
|
744
|
+
});
|
745
|
+
}
|
746
|
+
|
747
|
+
|
748
|
+
public void setSize(int wide, int high) {
|
749
|
+
if (pgl.presentMode()) return;
|
750
|
+
|
751
|
+
// When the surface is set to resizable via surface.setResizable(true),
|
752
|
+
// a crash may occur if the user sets the window to size zero.
|
753
|
+
// https://github.com/processing/processing/issues/5052
|
754
|
+
if (high <= 0) {
|
755
|
+
high = 1;
|
756
|
+
}
|
757
|
+
if (wide <= 0) {
|
758
|
+
wide = 1;
|
759
|
+
}
|
760
|
+
|
761
|
+
boolean changed = sketch.width != wide || sketch.height != high;
|
762
|
+
|
763
|
+
sketchWidth = wide;
|
764
|
+
sketchHeight = high;
|
765
|
+
|
766
|
+
sketch.setSize(wide, high);
|
767
|
+
graphics.setSize(wide, high);
|
768
|
+
|
769
|
+
if (changed) {
|
770
|
+
window.setSize(wide * windowScaleFactor, high * windowScaleFactor);
|
771
|
+
}
|
772
|
+
}
|
773
|
+
|
774
|
+
|
775
|
+
public float getPixelScale() {
|
776
|
+
if (graphics.pixelDensity == 1) {
|
777
|
+
return 1;
|
778
|
+
}
|
779
|
+
|
780
|
+
if (PApplet.platform == PConstants.MACOSX) {
|
781
|
+
return getCurrentPixelScale();
|
782
|
+
}
|
783
|
+
|
784
|
+
return 2;
|
785
|
+
}
|
786
|
+
|
787
|
+
private float getCurrentPixelScale() {
|
788
|
+
// Even if the graphics are retina, the user might have moved the window
|
789
|
+
// into a non-retina monitor, so we need to check
|
790
|
+
window.getCurrentSurfaceScale(currentPixelScale);
|
791
|
+
return currentPixelScale[0];
|
792
|
+
}
|
793
|
+
|
794
|
+
|
795
|
+
public Component getComponent() {
|
796
|
+
return canvas;
|
797
|
+
}
|
798
|
+
|
799
|
+
|
800
|
+
public void setSmooth(int level) {
|
801
|
+
pgl.reqNumSamples = level;
|
802
|
+
GLCapabilities caps = new GLCapabilities(profile);
|
803
|
+
caps.setAlphaBits(PGL.REQUESTED_ALPHA_BITS);
|
804
|
+
caps.setDepthBits(PGL.REQUESTED_DEPTH_BITS);
|
805
|
+
caps.setStencilBits(PGL.REQUESTED_STENCIL_BITS);
|
806
|
+
caps.setSampleBuffers(true);
|
807
|
+
caps.setNumSamples(pgl.reqNumSamples);
|
808
|
+
caps.setBackgroundOpaque(true);
|
809
|
+
caps.setOnscreen(true);
|
810
|
+
NativeSurface target = window.getNativeSurface();
|
811
|
+
MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
|
812
|
+
config.setChosenCapabilities(caps);
|
813
|
+
}
|
814
|
+
|
815
|
+
|
816
|
+
public void setFrameRate(float fps) {
|
817
|
+
if (fps < 1) {
|
818
|
+
PGraphics.showWarning(
|
819
|
+
"The OpenGL renderer cannot have a frame rate lower than 1.\n" +
|
820
|
+
"Your sketch will run at 1 frame per second.");
|
821
|
+
fps = 1;
|
822
|
+
} else if (fps > 1000) {
|
823
|
+
PGraphics.showWarning(
|
824
|
+
"The OpenGL renderer cannot have a frame rate higher than 1000.\n" +
|
825
|
+
"Your sketch will run at 1000 frames per second.");
|
826
|
+
fps = 1000;
|
827
|
+
}
|
828
|
+
if (animator != null) {
|
829
|
+
animator.stop();
|
830
|
+
animator.setFPS((int)fps);
|
831
|
+
pgl.setFps(fps);
|
832
|
+
animator.start();
|
833
|
+
}
|
834
|
+
}
|
835
|
+
|
836
|
+
|
837
|
+
public void requestFocus() {
|
838
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
839
|
+
@Override
|
840
|
+
public void run() {
|
841
|
+
window.requestFocus();
|
842
|
+
}
|
843
|
+
});
|
844
|
+
}
|
845
|
+
|
846
|
+
|
847
|
+
class DrawListener implements GLEventListener {
|
848
|
+
public void display(GLAutoDrawable drawable) {
|
849
|
+
if (display.getEDTUtil().isCurrentThreadEDT()) {
|
850
|
+
// For some reason, the first two frames of the animator are run on the
|
851
|
+
// EDT, skipping rendering Processing's frame in that case.
|
852
|
+
return;
|
853
|
+
}
|
854
|
+
|
855
|
+
if (sketch.frameCount == 0) {
|
856
|
+
if (sketchWidth < sketchWidth0 || sketchHeight < sketchHeight0) {
|
857
|
+
PGraphics.showWarning("The sketch has been automatically resized to fit the screen resolution");
|
858
|
+
}
|
859
|
+
// System.out.println("display: " + window.getWidth() + " "+ window.getHeight() + " - " + sketchWidth + " " + sketchHeight);
|
860
|
+
requestFocus();
|
861
|
+
}
|
862
|
+
|
863
|
+
if (!sketch.finished) {
|
864
|
+
pgl.getGL(drawable);
|
865
|
+
int pframeCount = sketch.frameCount;
|
866
|
+
sketch.handleDraw();
|
867
|
+
if (pframeCount == sketch.frameCount || sketch.finished) {
|
868
|
+
// This hack allows the FBO layer to be swapped normally even if
|
869
|
+
// the sketch is no looping or finished because it does not call draw(),
|
870
|
+
// otherwise background artifacts may occur (depending on the hardware/drivers).
|
871
|
+
pgl.beginRender();
|
872
|
+
pgl.endRender(sketch.sketchWindowColor());
|
873
|
+
}
|
874
|
+
PGraphicsOpenGL.completeFinishedPixelTransfers();
|
875
|
+
}
|
876
|
+
|
877
|
+
if (sketch.exitCalled()) {
|
878
|
+
PGraphicsOpenGL.completeAllPixelTransfers();
|
879
|
+
|
880
|
+
sketch.dispose(); // calls stopThread(), which stops the animator.
|
881
|
+
sketch.exitActual();
|
882
|
+
}
|
883
|
+
}
|
884
|
+
public void dispose(GLAutoDrawable drawable) {
|
885
|
+
// sketch.dispose();
|
886
|
+
}
|
887
|
+
public void init(GLAutoDrawable drawable) {
|
888
|
+
pgl.getGL(drawable);
|
889
|
+
pgl.init(drawable);
|
890
|
+
sketch.start();
|
891
|
+
|
892
|
+
int c = graphics.backgroundColor;
|
893
|
+
pgl.clearColor(((c >> 16) & 0xff) / 255f,
|
894
|
+
((c >> 8) & 0xff) / 255f,
|
895
|
+
((c >> 0) & 0xff) / 255f,
|
896
|
+
((c >> 24) & 0xff) / 255f);
|
897
|
+
pgl.clear(PGL.COLOR_BUFFER_BIT);
|
898
|
+
}
|
899
|
+
|
900
|
+
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
|
901
|
+
pgl.resetFBOLayer();
|
902
|
+
pgl.getGL(drawable);
|
903
|
+
float scale = PApplet.platform == PConstants.MACOSX ?
|
904
|
+
getCurrentPixelScale() : getPixelScale();
|
905
|
+
setSize((int) (w / scale), (int) (h / scale));
|
906
|
+
}
|
907
|
+
}
|
908
|
+
|
909
|
+
|
910
|
+
protected class NEWTWindowListener implements com.jogamp.newt.event.WindowListener {
|
911
|
+
public NEWTWindowListener() {
|
912
|
+
super();
|
913
|
+
}
|
914
|
+
@Override
|
915
|
+
public void windowGainedFocus(com.jogamp.newt.event.WindowEvent arg0) {
|
916
|
+
sketch.focused = true;
|
917
|
+
sketch.focusGained();
|
918
|
+
}
|
919
|
+
|
920
|
+
@Override
|
921
|
+
public void windowLostFocus(com.jogamp.newt.event.WindowEvent arg0) {
|
922
|
+
sketch.focused = false;
|
923
|
+
sketch.focusLost();
|
924
|
+
}
|
925
|
+
|
926
|
+
@Override
|
927
|
+
public void windowDestroyNotify(com.jogamp.newt.event.WindowEvent arg0) {
|
928
|
+
sketch.exit();
|
929
|
+
}
|
930
|
+
|
931
|
+
@Override
|
932
|
+
public void windowDestroyed(com.jogamp.newt.event.WindowEvent arg0) {
|
933
|
+
sketch.exit();
|
934
|
+
}
|
935
|
+
|
936
|
+
@Override
|
937
|
+
public void windowMoved(com.jogamp.newt.event.WindowEvent arg0) {
|
938
|
+
if (external) {
|
939
|
+
sketch.frameMoved(window.getX(), window.getY());
|
940
|
+
}
|
941
|
+
}
|
942
|
+
|
943
|
+
@Override
|
944
|
+
public void windowRepaint(com.jogamp.newt.event.WindowUpdateEvent arg0) {
|
945
|
+
}
|
946
|
+
|
947
|
+
@Override
|
948
|
+
public void windowResized(com.jogamp.newt.event.WindowEvent arg0) {
|
949
|
+
}
|
950
|
+
}
|
951
|
+
|
952
|
+
|
953
|
+
// NEWT mouse listener
|
954
|
+
protected class NEWTMouseListener extends com.jogamp.newt.event.MouseAdapter {
|
955
|
+
public NEWTMouseListener() {
|
956
|
+
super();
|
957
|
+
}
|
958
|
+
@Override
|
959
|
+
public void mousePressed(com.jogamp.newt.event.MouseEvent e) {
|
960
|
+
nativeMouseEvent(e, MouseEvent.PRESS);
|
961
|
+
}
|
962
|
+
@Override
|
963
|
+
public void mouseReleased(com.jogamp.newt.event.MouseEvent e) {
|
964
|
+
nativeMouseEvent(e, MouseEvent.RELEASE);
|
965
|
+
}
|
966
|
+
@Override
|
967
|
+
public void mouseClicked(com.jogamp.newt.event.MouseEvent e) {
|
968
|
+
nativeMouseEvent(e, MouseEvent.CLICK);
|
969
|
+
}
|
970
|
+
@Override
|
971
|
+
public void mouseDragged(com.jogamp.newt.event.MouseEvent e) {
|
972
|
+
nativeMouseEvent(e, MouseEvent.DRAG);
|
973
|
+
}
|
974
|
+
@Override
|
975
|
+
public void mouseMoved(com.jogamp.newt.event.MouseEvent e) {
|
976
|
+
nativeMouseEvent(e, MouseEvent.MOVE);
|
977
|
+
}
|
978
|
+
@Override
|
979
|
+
public void mouseWheelMoved(com.jogamp.newt.event.MouseEvent e) {
|
980
|
+
nativeMouseEvent(e, MouseEvent.WHEEL);
|
981
|
+
}
|
982
|
+
@Override
|
983
|
+
public void mouseEntered(com.jogamp.newt.event.MouseEvent e) {
|
984
|
+
// System.out.println("enter");
|
985
|
+
nativeMouseEvent(e, MouseEvent.ENTER);
|
986
|
+
}
|
987
|
+
@Override
|
988
|
+
public void mouseExited(com.jogamp.newt.event.MouseEvent e) {
|
989
|
+
// System.out.println("exit");
|
990
|
+
nativeMouseEvent(e, MouseEvent.EXIT);
|
991
|
+
}
|
992
|
+
}
|
993
|
+
|
994
|
+
|
995
|
+
// NEWT key listener
|
996
|
+
protected class NEWTKeyListener extends com.jogamp.newt.event.KeyAdapter {
|
997
|
+
public NEWTKeyListener() {
|
998
|
+
super();
|
999
|
+
}
|
1000
|
+
@Override
|
1001
|
+
public void keyPressed(com.jogamp.newt.event.KeyEvent e) {
|
1002
|
+
nativeKeyEvent(e, KeyEvent.PRESS);
|
1003
|
+
}
|
1004
|
+
@Override
|
1005
|
+
public void keyReleased(com.jogamp.newt.event.KeyEvent e) {
|
1006
|
+
nativeKeyEvent(e, KeyEvent.RELEASE);
|
1007
|
+
}
|
1008
|
+
public void keyTyped(com.jogamp.newt.event.KeyEvent e) {
|
1009
|
+
nativeKeyEvent(e, KeyEvent.TYPE);
|
1010
|
+
}
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
|
1014
|
+
protected void nativeMouseEvent(com.jogamp.newt.event.MouseEvent nativeEvent,
|
1015
|
+
int peAction) {
|
1016
|
+
int modifiers = nativeEvent.getModifiers();
|
1017
|
+
int peModifiers = modifiers &
|
1018
|
+
(InputEvent.SHIFT_MASK |
|
1019
|
+
InputEvent.CTRL_MASK |
|
1020
|
+
InputEvent.META_MASK |
|
1021
|
+
InputEvent.ALT_MASK);
|
1022
|
+
|
1023
|
+
int peButton = 0;
|
1024
|
+
switch (nativeEvent.getButton()) {
|
1025
|
+
case com.jogamp.newt.event.MouseEvent.BUTTON1:
|
1026
|
+
peButton = PConstants.LEFT;
|
1027
|
+
break;
|
1028
|
+
case com.jogamp.newt.event.MouseEvent.BUTTON2:
|
1029
|
+
peButton = PConstants.CENTER;
|
1030
|
+
break;
|
1031
|
+
case com.jogamp.newt.event.MouseEvent.BUTTON3:
|
1032
|
+
peButton = PConstants.RIGHT;
|
1033
|
+
break;
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
if (PApplet.platform == PConstants.MACOSX) {
|
1037
|
+
//if (nativeEvent.isPopupTrigger()) {
|
1038
|
+
if ((modifiers & InputEvent.CTRL_MASK) != 0) {
|
1039
|
+
peButton = PConstants.RIGHT;
|
1040
|
+
}
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
int peCount = 0;
|
1044
|
+
if (peAction == MouseEvent.WHEEL) {
|
1045
|
+
// Invert wheel rotation count so it matches JAVA2D's
|
1046
|
+
// https://github.com/processing/processing/issues/3840
|
1047
|
+
peCount = -(nativeEvent.isShiftDown() ? (int)nativeEvent.getRotation()[0]:
|
1048
|
+
(int)nativeEvent.getRotation()[1]);
|
1049
|
+
} else {
|
1050
|
+
peCount = nativeEvent.getClickCount();
|
1051
|
+
}
|
1052
|
+
|
1053
|
+
int scale;
|
1054
|
+
if (PApplet.platform == PConstants.MACOSX) {
|
1055
|
+
scale = (int) getCurrentPixelScale();
|
1056
|
+
} else {
|
1057
|
+
scale = (int) getPixelScale();
|
1058
|
+
}
|
1059
|
+
int sx = nativeEvent.getX() / scale;
|
1060
|
+
int sy = nativeEvent.getY() / scale;
|
1061
|
+
int mx = sx;
|
1062
|
+
int my = sy;
|
1063
|
+
|
1064
|
+
if (pgl.presentMode()) {
|
1065
|
+
mx -= (int)pgl.presentX;
|
1066
|
+
my -= (int)pgl.presentY;
|
1067
|
+
if (peAction == KeyEvent.RELEASE &&
|
1068
|
+
pgl.insideStopButton(sx, sy - screenRect.height / windowScaleFactor)) {
|
1069
|
+
sketch.exit();
|
1070
|
+
}
|
1071
|
+
if (mx < 0 || sketchWidth < mx || my < 0 || sketchHeight < my) {
|
1072
|
+
return;
|
1073
|
+
}
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
MouseEvent me = new MouseEvent(nativeEvent, nativeEvent.getWhen(),
|
1077
|
+
peAction, peModifiers,
|
1078
|
+
mx, my,
|
1079
|
+
peButton,
|
1080
|
+
peCount);
|
1081
|
+
|
1082
|
+
sketch.postEvent(me);
|
1083
|
+
}
|
1084
|
+
|
1085
|
+
|
1086
|
+
protected void nativeKeyEvent(com.jogamp.newt.event.KeyEvent nativeEvent,
|
1087
|
+
int peAction) {
|
1088
|
+
int peModifiers = nativeEvent.getModifiers() &
|
1089
|
+
(InputEvent.SHIFT_MASK |
|
1090
|
+
InputEvent.CTRL_MASK |
|
1091
|
+
InputEvent.META_MASK |
|
1092
|
+
InputEvent.ALT_MASK);
|
1093
|
+
|
1094
|
+
short code = nativeEvent.getKeyCode();
|
1095
|
+
char keyChar;
|
1096
|
+
int keyCode;
|
1097
|
+
if (isPCodedKey(code)) {
|
1098
|
+
keyCode = mapToPConst(code);
|
1099
|
+
keyChar = PConstants.CODED;
|
1100
|
+
} else if (isHackyKey(code)) {
|
1101
|
+
// we can return only one char for ENTER, let it be \n everywhere
|
1102
|
+
keyCode = code == com.jogamp.newt.event.KeyEvent.VK_ENTER ?
|
1103
|
+
PConstants.ENTER : code;
|
1104
|
+
keyChar = hackToChar(code, nativeEvent.getKeyChar());
|
1105
|
+
} else {
|
1106
|
+
keyCode = code;
|
1107
|
+
keyChar = nativeEvent.getKeyChar();
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
// From http://jogamp.org/deployment/v2.1.0/javadoc/jogl/javadoc/com/jogamp/newt/event/KeyEvent.html
|
1111
|
+
// public final short getKeySymbol()
|
1112
|
+
// Returns the virtual key symbol reflecting the current keyboard layout.
|
1113
|
+
// public final short getKeyCode()
|
1114
|
+
// Returns the virtual key code using a fixed mapping to the US keyboard layout.
|
1115
|
+
// In contrast to key symbol, key code uses a fixed US keyboard layout and therefore is keyboard layout independent.
|
1116
|
+
// E.g. virtual key code VK_Y denotes the same physical key regardless whether keyboard layout QWERTY or QWERTZ is active. The key symbol of the former is VK_Y, where the latter produces VK_Y.
|
1117
|
+
KeyEvent ke = new KeyEvent(nativeEvent, nativeEvent.getWhen(),
|
1118
|
+
peAction, peModifiers,
|
1119
|
+
keyChar,
|
1120
|
+
keyCode,
|
1121
|
+
nativeEvent.isAutoRepeat());
|
1122
|
+
|
1123
|
+
sketch.postEvent(ke);
|
1124
|
+
|
1125
|
+
if (!isPCodedKey(code) && !isHackyKey(code)) {
|
1126
|
+
if (peAction == KeyEvent.PRESS) {
|
1127
|
+
// Create key typed event
|
1128
|
+
// TODO: combine dead keys with the following key
|
1129
|
+
KeyEvent tke = new KeyEvent(nativeEvent, nativeEvent.getWhen(),
|
1130
|
+
KeyEvent.TYPE, peModifiers,
|
1131
|
+
keyChar,
|
1132
|
+
0,
|
1133
|
+
nativeEvent.isAutoRepeat());
|
1134
|
+
|
1135
|
+
sketch.postEvent(tke);
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
|
1141
|
+
private static boolean isPCodedKey(short code) {
|
1142
|
+
return code == com.jogamp.newt.event.KeyEvent.VK_UP ||
|
1143
|
+
code == com.jogamp.newt.event.KeyEvent.VK_DOWN ||
|
1144
|
+
code == com.jogamp.newt.event.KeyEvent.VK_LEFT ||
|
1145
|
+
code == com.jogamp.newt.event.KeyEvent.VK_RIGHT ||
|
1146
|
+
code == com.jogamp.newt.event.KeyEvent.VK_ALT ||
|
1147
|
+
code == com.jogamp.newt.event.KeyEvent.VK_CONTROL ||
|
1148
|
+
code == com.jogamp.newt.event.KeyEvent.VK_SHIFT ||
|
1149
|
+
code == com.jogamp.newt.event.KeyEvent.VK_WINDOWS;
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
|
1153
|
+
// Why do we need this mapping?
|
1154
|
+
// Relevant discussion and links here:
|
1155
|
+
// http://forum.jogamp.org/Newt-wrong-keycode-for-key-td4033690.html#a4033697
|
1156
|
+
// (I don't think this is a complete solution).
|
1157
|
+
private static int mapToPConst(short code) {
|
1158
|
+
switch (code) {
|
1159
|
+
case com.jogamp.newt.event.KeyEvent.VK_UP:
|
1160
|
+
return PConstants.UP;
|
1161
|
+
case com.jogamp.newt.event.KeyEvent.VK_DOWN:
|
1162
|
+
return PConstants.DOWN;
|
1163
|
+
case com.jogamp.newt.event.KeyEvent.VK_LEFT:
|
1164
|
+
return PConstants.LEFT;
|
1165
|
+
case com.jogamp.newt.event.KeyEvent.VK_RIGHT:
|
1166
|
+
return PConstants.RIGHT;
|
1167
|
+
case com.jogamp.newt.event.KeyEvent.VK_ALT:
|
1168
|
+
return PConstants.ALT;
|
1169
|
+
case com.jogamp.newt.event.KeyEvent.VK_CONTROL:
|
1170
|
+
return PConstants.CONTROL;
|
1171
|
+
case com.jogamp.newt.event.KeyEvent.VK_SHIFT:
|
1172
|
+
return PConstants.SHIFT;
|
1173
|
+
case com.jogamp.newt.event.KeyEvent.VK_WINDOWS:
|
1174
|
+
return java.awt.event.KeyEvent.VK_META;
|
1175
|
+
default:
|
1176
|
+
return code;
|
1177
|
+
}
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
|
1181
|
+
private static boolean isHackyKey(short code) {
|
1182
|
+
switch (code) {
|
1183
|
+
case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE:
|
1184
|
+
case com.jogamp.newt.event.KeyEvent.VK_TAB:
|
1185
|
+
case com.jogamp.newt.event.KeyEvent.VK_ENTER:
|
1186
|
+
case com.jogamp.newt.event.KeyEvent.VK_ESCAPE:
|
1187
|
+
case com.jogamp.newt.event.KeyEvent.VK_DELETE:
|
1188
|
+
return true;
|
1189
|
+
}
|
1190
|
+
return false;
|
1191
|
+
}
|
1192
|
+
|
1193
|
+
|
1194
|
+
private static char hackToChar(short code, char def) {
|
1195
|
+
switch (code) {
|
1196
|
+
case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE:
|
1197
|
+
return PConstants.BACKSPACE;
|
1198
|
+
case com.jogamp.newt.event.KeyEvent.VK_TAB:
|
1199
|
+
return PConstants.TAB;
|
1200
|
+
case com.jogamp.newt.event.KeyEvent.VK_ENTER:
|
1201
|
+
return PConstants.ENTER;
|
1202
|
+
case com.jogamp.newt.event.KeyEvent.VK_ESCAPE:
|
1203
|
+
return PConstants.ESC;
|
1204
|
+
case com.jogamp.newt.event.KeyEvent.VK_DELETE:
|
1205
|
+
return PConstants.DELETE;
|
1206
|
+
}
|
1207
|
+
return def;
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
|
1211
|
+
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
1212
|
+
|
1213
|
+
|
1214
|
+
class CursorInfo {
|
1215
|
+
PImage image;
|
1216
|
+
int x, y;
|
1217
|
+
|
1218
|
+
CursorInfo(PImage image, int x, int y) {
|
1219
|
+
this.image = image;
|
1220
|
+
this.x = x;
|
1221
|
+
this.y = y;
|
1222
|
+
}
|
1223
|
+
|
1224
|
+
void set() {
|
1225
|
+
setCursor(image, x, y);
|
1226
|
+
}
|
1227
|
+
}
|
1228
|
+
|
1229
|
+
static Map<Integer, CursorInfo> cursors = new HashMap<>();
|
1230
|
+
static Map<Integer, String> cursorNames = new HashMap<>();
|
1231
|
+
static {
|
1232
|
+
cursorNames.put(PConstants.ARROW, "arrow");
|
1233
|
+
cursorNames.put(PConstants.CROSS, "cross");
|
1234
|
+
cursorNames.put(PConstants.WAIT, "wait");
|
1235
|
+
cursorNames.put(PConstants.MOVE, "move");
|
1236
|
+
cursorNames.put(PConstants.HAND, "hand");
|
1237
|
+
cursorNames.put(PConstants.TEXT, "text");
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
|
1241
|
+
public void setCursor(int kind) {
|
1242
|
+
if (!cursorNames.containsKey(kind)) {
|
1243
|
+
PGraphics.showWarning("Unknown cursor type: " + kind);
|
1244
|
+
return;
|
1245
|
+
}
|
1246
|
+
CursorInfo cursor = cursors.get(kind);
|
1247
|
+
if (cursor == null) {
|
1248
|
+
String name = cursorNames.get(kind);
|
1249
|
+
if (name != null) {
|
1250
|
+
ImageIcon icon =
|
1251
|
+
new ImageIcon(getClass().getResource("cursors/" + name + ".png"));
|
1252
|
+
PImage img = new PImage(icon.getImage());
|
1253
|
+
// Most cursors just use the center as the hotspot...
|
1254
|
+
int x = img.width / 2;
|
1255
|
+
int y = img.height / 2;
|
1256
|
+
// ...others are more specific
|
1257
|
+
if (kind == PConstants.ARROW) {
|
1258
|
+
x = 10; y = 7;
|
1259
|
+
} else if (kind == PConstants.HAND) {
|
1260
|
+
x = 12; y = 8;
|
1261
|
+
} else if (kind == PConstants.TEXT) {
|
1262
|
+
x = 16; y = 22;
|
1263
|
+
}
|
1264
|
+
cursor = new CursorInfo(img, x, y);
|
1265
|
+
cursors.put(kind, cursor);
|
1266
|
+
}
|
1267
|
+
}
|
1268
|
+
if (cursor != null) {
|
1269
|
+
cursor.set();
|
1270
|
+
} else {
|
1271
|
+
PGraphics.showWarning("Cannot load cursor type: " + kind);
|
1272
|
+
}
|
1273
|
+
}
|
1274
|
+
|
1275
|
+
|
1276
|
+
public void setCursor(PImage image, int hotspotX, int hotspotY) {
|
1277
|
+
Display disp = window.getScreen().getDisplay();
|
1278
|
+
BufferedImage bimg = (BufferedImage)image.getNative();
|
1279
|
+
DataBufferInt dbuf = (DataBufferInt)bimg.getData().getDataBuffer();
|
1280
|
+
int[] ipix = dbuf.getData();
|
1281
|
+
ByteBuffer pixels = ByteBuffer.allocate(ipix.length * 4);
|
1282
|
+
pixels.asIntBuffer().put(ipix);
|
1283
|
+
PixelFormat format = PixelFormat.ARGB8888;
|
1284
|
+
final Dimension size = new Dimension(bimg.getWidth(), bimg.getHeight());
|
1285
|
+
PixelRectangle pixelrect = new PixelRectangle.GenericPixelRect(format, size, 0, false, pixels);
|
1286
|
+
final PointerIcon pi = disp.createPointerIcon(pixelrect, hotspotX, hotspotY);
|
1287
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
1288
|
+
@Override
|
1289
|
+
public void run() {
|
1290
|
+
window.setPointerVisible(true);
|
1291
|
+
window.setPointerIcon(pi);
|
1292
|
+
}
|
1293
|
+
});
|
1294
|
+
}
|
1295
|
+
|
1296
|
+
|
1297
|
+
public void showCursor() {
|
1298
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
1299
|
+
@Override
|
1300
|
+
public void run() {
|
1301
|
+
window.setPointerVisible(true);
|
1302
|
+
}
|
1303
|
+
});
|
1304
|
+
}
|
1305
|
+
|
1306
|
+
|
1307
|
+
public void hideCursor() {
|
1308
|
+
display.getEDTUtil().invoke(false, new Runnable() {
|
1309
|
+
@Override
|
1310
|
+
public void run() {
|
1311
|
+
window.setPointerVisible(false);
|
1312
|
+
}
|
1313
|
+
});
|
1314
|
+
}
|
1315
|
+
}
|