propane 3.4.2-java → 3.5.0-java

Sign up to get free protection for your applications and to get access to all the features.
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
  }