propane 2.7.2-java → 2.8.0.pre-java

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