propane 3.9.0-java → 3.10.0-java

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