picrate 0.8.0-java → 0.9.0-java

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