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