picrate 0.8.0-java → 0.9.0-java

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