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