JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
NewtCanvasAWT.java
Go to the documentation of this file.
1/**
2 * Copyright 2010 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29
30package com.jogamp.newt.awt;
31
32import java.awt.AWTKeyStroke;
33import java.awt.Component;
34import java.awt.EventQueue;
35import java.awt.Graphics;
36import java.awt.Graphics2D;
37import java.awt.GraphicsConfiguration;
38import java.awt.GraphicsDevice;
39import java.awt.KeyboardFocusManager;
40import java.awt.geom.NoninvertibleTransformException;
41import java.beans.Beans;
42import java.beans.PropertyChangeEvent;
43import java.beans.PropertyChangeListener;
44import java.util.Set;
45
46import com.jogamp.nativewindow.CapabilitiesImmutable;
47import com.jogamp.nativewindow.NativeSurface;
48import com.jogamp.nativewindow.NativeWindow;
49import com.jogamp.nativewindow.NativeWindowHolder;
50import com.jogamp.nativewindow.OffscreenLayerOption;
51import com.jogamp.nativewindow.WindowClosingProtocol;
52import com.jogamp.opengl.GLAnimatorControl;
53import com.jogamp.opengl.GLAutoDrawable;
54import com.jogamp.opengl.GLCapabilities;
55import com.jogamp.opengl.GLCapabilitiesImmutable;
56import com.jogamp.opengl.GLDrawable;
57import com.jogamp.opengl.GLDrawableFactory;
58import com.jogamp.opengl.GLException;
59import com.jogamp.opengl.GLOffscreenAutoDrawable;
60import javax.swing.MenuSelectionManager;
61
62import jogamp.nativewindow.awt.AWTMisc;
63import jogamp.nativewindow.jawt.JAWTUtil;
64import jogamp.newt.Debug;
65import jogamp.newt.WindowImpl;
66import jogamp.newt.awt.NewtFactoryAWT;
67import jogamp.newt.awt.event.AWTParentWindowAdapter;
68import jogamp.newt.driver.DriverClearFocus;
69import jogamp.opengl.awt.AWTTilePainter;
70
71import com.jogamp.common.ExceptionUtils;
72import com.jogamp.common.os.Platform;
73import com.jogamp.common.os.Platform.OSType;
74import com.jogamp.common.util.awt.AWTEDTExecutor;
75import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
76import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
77import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
78import com.jogamp.nativewindow.awt.JAWTWindow;
79import com.jogamp.newt.Display;
80import com.jogamp.newt.Window;
81import com.jogamp.newt.event.KeyEvent;
82import com.jogamp.newt.event.KeyListener;
83import com.jogamp.newt.event.WindowAdapter;
84import com.jogamp.newt.event.WindowEvent;
85import com.jogamp.newt.event.WindowListener;
86import com.jogamp.newt.event.awt.AWTAdapter;
87import com.jogamp.newt.event.awt.AWTKeyAdapter;
88import com.jogamp.newt.event.awt.AWTMouseAdapter;
89import com.jogamp.opengl.util.GLDrawableUtil;
90import com.jogamp.opengl.util.TileRenderer;
91
92/**
93 * AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting.
94 *
95 * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5>
96 *
97 * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
98 * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
99 * the underlying JAWT mechanism to composite the image, if supported.
100 */
101@SuppressWarnings("serial")
103 public static final boolean DEBUG = Debug.debug("Window");
104
105 private static JAWTUtil.BackgroundEraseControl backgroundEraseControl = new JAWTUtil.BackgroundEraseControl();
106
107 private final Object sync = new Object();
108 private volatile JAWTWindow jawtWindow = null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
109 private boolean isApplet = false;
110 private boolean shallUseOffscreenLayer = false;
111 private Window newtChild = null;
112 private boolean newtChildAttached = false;
113 private boolean isOnscreen = true;
114 private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
115 private final AWTParentWindowAdapter awtWinAdapter;
116 private final AWTAdapter awtMouseAdapter;
117 private final AWTAdapter awtKeyAdapter;
118
119 private volatile AWTGraphicsConfiguration awtConfig;
120
121 /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
122 private boolean destroyJAWTPending = false;
123 /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
124 private boolean skipJAWTDestroy = false;
125
126 /** Safeguard for AWTWindowClosingProtocol and 'removeNotify()' on other thread than AWT-EDT. */
127 private volatile boolean componentAdded = false;
128
129 private final AWTWindowClosingProtocol awtWindowClosingProtocol =
130 new AWTWindowClosingProtocol(this, new Runnable() {
131 @Override
132 public void run() {
133 if( componentAdded ) {
134 NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */);
135 }
136 }
137 }, new Runnable() {
138 @Override
139 public void run() {
140 if( componentAdded && newtChild != null ) {
141 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
142 }
143 }
144 } );
145
146 /**
147 * Instantiates a NewtCanvas without a NEWT child.<br>
148 */
149 public NewtCanvasAWT() {
150 super();
151 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
152 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
153 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
154 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
155 }
156
157 /**
158 * Instantiates a NewtCanvas without a NEWT child.<br>
159 */
160 public NewtCanvasAWT(final GraphicsConfiguration gc) {
161 super(gc);
162 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
163 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
164 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
165 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
166 }
167
168 /**
169 * Instantiates a NewtCanvas with a NEWT child.
170 */
171 public NewtCanvasAWT(final Window child) {
172 super();
173 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
174 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
175 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
176 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
177 setNEWTChild(child);
178 }
179
180 /**
181 * Instantiates a NewtCanvas with a NEWT child.
182 */
183 public NewtCanvasAWT(final GraphicsConfiguration gc, final Window child) {
184 super(gc);
185 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
186 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
187 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
188 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
189 setNEWTChild(child);
190 }
191
192 @Override
193 public void setShallUseOffscreenLayer(final boolean v) {
194 shallUseOffscreenLayer = v;
195 }
196
197 @Override
198 public final boolean getShallUseOffscreenLayer() {
199 return shallUseOffscreenLayer;
200 }
201
202 @Override
203 public final boolean isOffscreenLayerSurfaceEnabled() {
204 final JAWTWindow w = jawtWindow;
205 return null != w && w.isOffscreenLayerSurfaceEnabled();
206 }
207
208 /**
209 * Returns true if the AWT component is parented to an {@link java.applet.Applet},
210 * otherwise false. This information is valid only after {@link #addNotify()} is issued.
211 */
212 public final boolean isApplet() {
213 return isApplet;
214 }
215
216 private final boolean isParent() {
217 final Window nw = newtChild;
218 return null!=nw && jawtWindow == nw.getParent();
219 }
220
221 private final boolean isFullscreen() {
222 final Window nw = newtChild;
223 return null != nw && nw.isFullscreen();
224 }
225
226 class FocusAction implements Window.FocusRunnable {
227 @Override
228 public boolean run() {
229 final boolean isParent = isParent();
230 final boolean isFullscreen = isFullscreen();
231 if(DEBUG) {
232 System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()+", isParent "+isParent+", isFS "+isFullscreen);
233 }
234 if( isParent && !isFullscreen ) { // must be parent of newtChild _and_ newtChild not fullscreen
235 if( isOnscreen ) {
236 // Remove the AWT focus in favor of the native NEWT focus
237 AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
238 } else if( !hasFocus() ) {
239 // In offscreen mode we require the focus!
240 // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
241 NewtCanvasAWT.super.requestFocus();
242 }
243 }
244 return false; // NEWT shall proceed requesting the native focus
245 }
246 }
247 private final FocusAction focusAction = new FocusAction();
248
249 private static class ClearFocusOwner implements Runnable {
250 @Override
251 public void run() {
252 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
253 }
254 }
255 private static final Runnable awtClearGlobalFocusOwner = new ClearFocusOwner();
256
257 /** Must run on AWT-EDT non-blocking, since it invokes tasks on AWT-EDT w/ waiting otherwise. */
258 private final Runnable awtClearSelectedMenuPath = new Runnable() {
259 @Override
260 public void run() {
261 MenuSelectionManager.defaultManager().clearSelectedPath();
262 }
263 };
264 private final WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
265 @Override
266 public void windowResized(final WindowEvent e) {
267 updateLayoutSize();
268 }
269 @Override
270 public void windowGainedFocus(final WindowEvent arg0) {
271 if( isParent() && !isFullscreen() ) {
272 AWTEDTExecutor.singleton.invoke(false, awtClearSelectedMenuPath);
273 }
274 }
275 };
276
277 class FocusTraversalKeyListener implements KeyListener {
278 @Override
279 public void keyPressed(final KeyEvent e) {
280 if( isParent() && !isFullscreen() ) {
281 handleKey(e, false);
282 }
283 }
284 @Override
285 public void keyReleased(final KeyEvent e) {
286 if( isParent() && !isFullscreen() ) {
287 handleKey(e, true);
288 }
289 }
290
291 void handleKey(final KeyEvent evt, final boolean onRelease) {
292 if(null == keyboardFocusManager) {
293 throw new InternalError("XXX");
294 }
295 final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease);
296 boolean suppress = false;
297 if(null != ks) {
298 final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
299 final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
300 if(fwdKeys.contains(ks)) {
301 final Component nextFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, true /* forward */);
302 if(DEBUG) {
303 System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", nextFocus "+nextFocus);
304 }
305 // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
306 nextFocus.requestFocus();
307 suppress = true;
308 } else if(bwdKeys.contains(ks)) {
309 final Component prevFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, false /* forward */);
310 if(DEBUG) {
311 System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", prevFocus "+prevFocus);
312 }
313 // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
314 prevFocus.requestFocus();
315 suppress = true;
316 }
317 }
318 if(suppress) {
319 evt.setConsumed(true);
320 }
321 if(DEBUG) {
322 System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks);
323 }
324 }
325 }
326 private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener();
327
328 class FocusPropertyChangeListener implements PropertyChangeListener {
329 @Override
330 public void propertyChange(final PropertyChangeEvent evt) {
331 final Object oldF = evt.getOldValue();
332 final Object newF = evt.getNewValue();
333 final boolean isParent = isParent();
334 final boolean isFullscreen = isFullscreen();
335 if(DEBUG) {
336 System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF+", isParent "+isParent+", isFS "+isFullscreen);
337 }
338 if(isParent && !isFullscreen) {
339 if(newF == NewtCanvasAWT.this) {
340 if(DEBUG) {
341 System.err.println("NewtCanvasAWT.FocusProperty: AWT focus -> NEWT focus traversal");
342 }
343 requestFocusNEWTChild();
344 } else if(oldF == NewtCanvasAWT.this && newF == null) {
345 // focus traversal to NEWT - NOP
346 if(DEBUG) {
347 System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus");
348 }
349 } else if(null != newF && newF != NewtCanvasAWT.this) {
350 // focus traversal to another AWT component
351 if(DEBUG) {
352 System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus");
353 }
354 if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) {
355 ((DriverClearFocus)newtChild.getDelegatedWindow()).clearFocus();
356 }
357 }
358 }
359 }
360 }
361 private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener();
362 private volatile KeyboardFocusManager keyboardFocusManager = null;
363
364 private final void requestFocusNEWTChild() {
365 if(null!=newtChild) {
366 newtChild.setFocusAction(null);
367 if(isOnscreen) {
368 AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
369 }
370 newtChild.requestFocus();
371 newtChild.setFocusAction(focusAction);
372 }
373 }
374
375 /**
376 * Sets a new NEWT child, provoking reparenting.
377 * <p>
378 * A previously detached <code>newChild</code> will be released to top-level status
379 * and made invisible.
380 * </p>
381 * <p>
382 * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
383 * produced much cleaner visual results.
384 * </p>
385 * @return the previous attached newt child.
386 */
387 public Window setNEWTChild(final Window newChild) {
388 synchronized(sync) {
389 final Window prevChild = newtChild;
390 if(DEBUG) {
391 System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
392 }
393 final java.awt.Container cont = AWTMisc.getContainer(this);
394 // remove old one
395 if(null != newtChild) {
396 detachNewtChild( cont );
397 newtChild = null;
398 }
399 // add new one, reparent only if ready
400 newtChild = newChild;
401
402 updateLayoutSize();
403 // will be done later at paint/display/..: attachNewtChild(cont);
404
405 return prevChild;
406 }
407 }
408
409 private final void updateLayoutSize() {
410 final Window w = newtChild;
411 if( null != w ) {
412 // use NEWT child's size for min/pref size!
413 final java.awt.Dimension minSize = new java.awt.Dimension(w.getWidth(), w.getHeight());
414 setMinimumSize(minSize);
415 setPreferredSize(minSize);
416 }
417 }
418
419 /** @return the current NEWT child */
421 return newtChild;
422 }
423
424 /**
425 * {@inheritDoc}
426 * @return this AWT Canvas {@link NativeWindow} representation, may be null in case {@link #removeNotify()} has been called,
427 * or {@link #addNotify()} hasn't been called yet.
428 */
429 @Override
430 public NativeWindow getNativeWindow() { return jawtWindow; }
431
432 /**
433 * {@inheritDoc}
434 * @return this AWT Canvas {@link NativeSurface} representation, may be null in case {@link #removeNotify()} has been called,
435 * or {@link #addNotify()} hasn't been called yet.
436 */
437 @Override
438 public NativeSurface getNativeSurface() { return jawtWindow; }
439
440 @Override
442 return awtWindowClosingProtocol.getDefaultCloseOperation();
443 }
444
445 @Override
447 return awtWindowClosingProtocol.setDefaultCloseOperation(op);
448 }
449
450 /**
451 * Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy().
452 * <p>
453 * <code>skipJAWTDestroy</code> defaults to <code>false</code>.
454 * Due to above IcedTea-Web issue the <code>Applet</code> code needs to avoid JAWT destruction before
455 * <code>Applet.destroy()</code> is reached by setting <code>skipJAWTDestroy</code> to <code>true</code>.
456 * Afterwards the value should be reset to <code>false</code> and {@link #destroy()} needs to be called,
457 * which finally will perform the pending JAWT destruction.
458 * </p>
459 */
460 public final void setSkipJAWTDestroy(final boolean v) { skipJAWTDestroy = v; }
461 /** See {@link #setSkipJAWTDestroy(boolean)}. */
462 public final boolean getSkipJAWTDestroy() { return skipJAWTDestroy; }
463
464 @SuppressWarnings("removal")
465 private final void determineIfApplet() {
466 isApplet = false;
467 Component c = this;
468 while(!isApplet && null != c) {
469 isApplet = c instanceof java.applet.Applet;
470 c = c.getParent();
471 }
472 }
473
474 private void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) {
475 // Cache awtConfig
476 awtConfig = config;
477 if( null != jawtWindow ) {
478 // Notify JAWTWindow ..
479 jawtWindow.setAWTGraphicsConfiguration(config);
480 }
481 }
482
483 /**
484 * {@inheritDoc}
485 * <p>
486 * Overridden to choose a {@link GraphicsConfiguration} from a parent container's
487 * {@link GraphicsDevice}.
488 * </p>
489 * <p>
490 * Method also intercepts {@link GraphicsConfiguration} changes regarding to
491 * its capabilities and its {@link GraphicsDevice}. This may happen in case
492 * the display changes its configuration or the component is moved to another screen.
493 * </p>
494 */
495 @Override
496 public GraphicsConfiguration getGraphicsConfiguration() {
497 /**
498 * parentGC will be null unless:
499 * - A native peer has assigned it. This means we have a native
500 * peer, and are already committed to a graphics configuration.
501 * - This canvas has been added to a component hierarchy and has
502 * an ancestor with a non-null GC, but the native peer has not
503 * yet been created. This means we can still choose the GC on
504 * all platforms since the peer hasn't been created.
505 */
506 final GraphicsConfiguration parentGC = super.getGraphicsConfiguration();
507
508 if( Beans.isDesignTime() ) {
509 return parentGC;
510 }
511 final GraphicsConfiguration oldGC = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
512
513 if ( null != parentGC && null != oldGC && !oldGC.equals(parentGC) ) {
514 // Previous oldGC != parentGC of native peer
515
516 if ( !oldGC.getDevice().getIDstring().equals(parentGC.getDevice().getIDstring()) ) {
517 // Previous oldGC's GraphicsDevice != parentGC's GraphicsDevice of native peer
518
519 /**
520 * Here we select a GraphicsConfiguration on the alternate device.
521 * In case the new configuration differs (-> !equalCaps),
522 * we might need a reconfiguration,
523 */
525 awtConfig.getChosenCapabilities(),
526 awtConfig.getRequestedCapabilities());
527 final GraphicsConfiguration newGC = newConfig.getAWTGraphicsConfiguration();
528 final boolean equalCaps = newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
529 if(DEBUG) {
530 System.err.println(getThreadName()+": getGraphicsConfiguration() Info: Changed GC and GD");
531 System.err.println("Created Config (n): Old GC "+oldGC);
532 System.err.println("Created Config (n): Old GD "+oldGC.getDevice().getIDstring());
533 System.err.println("Created Config (n): Parent GC "+parentGC);
534 System.err.println("Created Config (n): Parent GD "+parentGC.getDevice().getIDstring());
535 System.err.println("Created Config (n): New GC "+newGC);
536 System.err.println("Created Config (n): Old CF "+awtConfig);
537 System.err.println("Created Config (n): New CF "+newConfig);
538 System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
539 // Thread.dumpStack();
540 }
541 if ( null != newGC ) {
542 setAWTGraphicsConfiguration(newConfig);
543 /**
544 * Return the newGC, which covers the desired capabilities and is compatible
545 * with the available GC's of its devices.
546 */
547 if(DEBUG) {
548 System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.01: newGC "+newGC);
549 }
550 return newGC;
551 } else {
552 if(DEBUG) {
553 System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.00: oldGC "+oldGC);
554 }
555 }
556 }
557 /**
558 * If a new GC was _not_ found/defined above,
559 * method returns oldGC as selected in the constructor or first addNotify().
560 * This may cause an exception in Component.checkGD when adding to a
561 * container, and is the desired behavior.
562 */
563 return oldGC;
564 } else if (null == parentGC) {
565 /**
566 * The parentGC is null, which means we have no native peer, and are not
567 * part of a (realized) component hierarchy. So we return the
568 * desired visual that was selected in the constructor (possibly
569 * null).
570 */
571 return oldGC;
572 } else {
573 /**
574 * Otherwise we have not explicitly selected a GC in the constructor, so
575 * just return what Canvas would have.
576 */
577 return parentGC;
578 }
579 }
580 private static String getThreadName() { return Thread.currentThread().getName(); }
581
582 @Override
583 public void addNotify() {
584 if( Beans.isDesignTime() ) {
585 super.addNotify();
586 } else {
587 /**
588 * 'super.addNotify()' determines the GraphicsConfiguration,
589 * while calling this class's overridden 'getGraphicsConfiguration()' method
590 * after which it creates the native peer.
591 * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
592 * is being used in getGraphicsConfiguration().
593 * This code order also allows recreation, ie re-adding the GLCanvas.
594 */
595 // before native peer is valid: X11
596 if( OSType.WINDOWS != Platform.getOSType() ) {
597 backgroundEraseControl.disable(this);
598 }
599
600 // Query AWT GraphicsDevice from parent tree, default
601 final GraphicsConfiguration gc = super.getGraphicsConfiguration();
602 if(null==gc) {
603 throw new GLException("Error: NULL AWT GraphicsConfiguration");
604 }
605 final CapabilitiesImmutable capsReq = null != newtChild ? newtChild.getRequestedCapabilities() : null;
606 final AWTGraphicsConfiguration awtConfig = AWTGraphicsConfiguration.create(gc, null, capsReq);
607 if(null==awtConfig) {
608 throw new GLException("Error: NULL AWTGraphicsConfiguration");
609 }
610 setAWTGraphicsConfiguration(awtConfig);
611
612 // creates the native peer
613 super.addNotify();
614
615 // after native peer is valid: Windows
616 if( OSType.WINDOWS == Platform.getOSType() ) {
617 backgroundEraseControl.disable(this);
618 }
619
620 synchronized(sync) {
621 determineIfApplet();
622 if(DEBUG) {
623 System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+EventQueue.isDispatchThread()+" @ "+currentThreadName());
624 ExceptionUtils.dumpStack(System.err);
625 }
626 jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, awtConfig);
627 jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
628 // enforce initial lock on AWT-EDT, allowing acquisition of pixel-scale
629 jawtWindow.lockSurface();
630 try {
631 // attachNewtChild sets surface scale!
632 } finally {
633 jawtWindow.unlockSurface();
634 }
635 awtWindowClosingProtocol.addClosingListener();
636 componentAdded = true; // Bug 910
637 if(DEBUG) {
638 // if ( isShowing() == false ) -> Container was not visible yet.
639 // if ( isShowing() == true ) -> Container is already visible.
640 System.err.println("NewtCanvasAWT.addNotify.X: twin "+newtWinHandleToHexString(newtChild)+
641 ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+
642 ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this));
643 }
644 }
645 }
646 }
647
648 /** Propagates AWT pixelScale to NEWT */
649 private final boolean updatePixelScale(final GraphicsConfiguration gc, final boolean force) {
650 if( jawtWindow.updatePixelScale(gc, false) || jawtWindow.hasPixelScaleChanged() || force ) {
651 jawtWindow.hasPixelScaleChanged(); // clear
652 final float[] hasPixelScale = jawtWindow.getCurrentSurfaceScale(new float[2]);
653 final Window cWin = newtChild;
654 final Window dWin = cWin.getDelegatedWindow();
655 if( dWin instanceof WindowImpl ) {
656 ((WindowImpl)dWin).setSurfaceScale(hasPixelScale);
657 }
658 return true;
659 }
660 return false;
661 }
662
663 @Override
664 public void removeNotify() {
665 if( Beans.isDesignTime() ) {
666 super.removeNotify();
667 } else {
668 if(DEBUG) {
669 System.err.println("NewtCanvasAWT.removeNotify.0 - isApplet "+isApplet+" @ "+currentThreadName());
670 ExceptionUtils.dumpStack(System.err);
671 }
672 componentAdded = false; // Bug 910
673 awtWindowClosingProtocol.removeClosingListener();
674 destroyImpl(true /* removeNotify */, false /* windowClosing */);
675 super.removeNotify();
676 if(DEBUG) {
677 System.err.println("NewtCanvasAWT.removeNotify.X @ "+currentThreadName());
678 }
679 }
680 }
681
682 /**
683 * Destroys this resource:
684 * <ul>
685 * <li> Make the NEWT Child invisible </li>
686 * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
687 * <li> Issues <code>destroy()</code> on the NEWT Child</li>
688 * <li> Remove reference to the NEWT Child</li>
689 * </ul>
690 * @see Window#destroy()
691 */
692 public final void destroy() {
693 if(DEBUG) {
694 System.err.println("NewtCanvasAWT.destroy() @ "+currentThreadName());
695 ExceptionUtils.dumpStack(System.err);
696 }
697 AWTEDTExecutor.singleton.invoke(true, new Runnable() {
698 @Override
699 public void run() {
700 destroyImpl(false /* removeNotify */, false /* windowClosing */);
701 } } );
702 }
703
704 private final void destroyImpl(final boolean removeNotify, final boolean windowClosing) {
705 synchronized(sync) {
706 final java.awt.Container cont = AWTMisc.getContainer(this);
707 if(DEBUG) {
708 System.err.println("NewtCanvasAWT.destroyImpl @ "+currentThreadName());
709 System.err.println("NewtCanvasAWT.destroyImpl.0 - isApplet "+isApplet+", isOnAWTEDT "+EventQueue.isDispatchThread()+", skipJAWTDestroy "+skipJAWTDestroy+
710 "; removeNotify "+removeNotify+", windowClosing "+windowClosing+", destroyJAWTPending "+destroyJAWTPending+
711 ", hasJAWT "+(null!=jawtWindow)+", hasNEWT "+(null!=newtChild)+
712 "): nw "+newtWinHandleToHexString(newtChild)+", from "+cont);
713 }
714 if( null !=newtChild ) {
715 detachNewtChild(cont);
716
717 if( !removeNotify ) {
718 final Window cWin = newtChild;
719 final Window dWin = cWin.getDelegatedWindow();
720 newtChild=null;
721 if( windowClosing && dWin instanceof WindowImpl ) {
722 ((WindowImpl)dWin).windowDestroyNotify(true);
723 } else {
724 cWin.destroy();
725 }
726 }
727 }
728 if( ( destroyJAWTPending || removeNotify || windowClosing ) && null!=jawtWindow ) {
729 if( skipJAWTDestroy ) {
730 // Bug 910 - See setSkipJAWTDestroy(boolean)
731 destroyJAWTPending = true;
732 } else {
733 NewtFactoryAWT.destroyNativeWindow(jawtWindow);
734 jawtWindow=null;
735 awtConfig=null;
736 destroyJAWTPending = false;
737 }
738 }
739 }
740 }
741
742 @Override
743 public void paint(final Graphics g) {
744 synchronized(sync) {
745 if( validateComponent(true) && !printActive ) {
746 newtChild.windowRepaint(0, 0, getWidth(), getHeight());
747 }
748 }
749 }
750 @Override
751 public void update(final Graphics g) {
752 paint(g);
753 }
754
755 @SuppressWarnings("deprecation")
756 @Override
757 public void reshape(final int x, final int y, final int width, final int height) {
758 synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
759 synchronized(sync) {
760 super.reshape(x, y, width, height);
761 if(DEBUG) {
762 System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height);
763 }
764 if( validateComponent(true) ) {
765 if( !printActive && updatePixelScale(getGraphicsConfiguration(), false /* force */) ) {
766 // NOP
767 } else {
768 // newtChild.setSize(width, height);
769 }
770 }
771 }
772 }
773 }
774
775 private volatile boolean printActive = false;
776 private GLAnimatorControl printAnimator = null;
777 private GLAutoDrawable printGLAD = null;
778 private AWTTilePainter printAWTTiles = null;
779
780 private final GLAutoDrawable getGLAD() {
781 if( null != newtChild && newtChild instanceof GLAutoDrawable ) {
782 return (GLAutoDrawable)newtChild;
783 }
784 return null;
785 }
786
787 @Override
788 public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
789 printActive = true;
790 final int componentCount = isOpaque() ? 3 : 4;
791 final TileRenderer printRenderer = new TileRenderer();
792 printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
793 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
794 }
795 private final Runnable setupPrintOnEDT = new Runnable() {
796 @Override
797 public void run() {
798 synchronized(sync) {
799 if( !validateComponent(true) ) {
800 if(DEBUG) {
801 System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable not valid yet");
802 }
803 printActive = false;
804 return; // not yet available ..
805 }
806 if( !isVisible() ) {
807 if(DEBUG) {
808 System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, canvas not visible");
809 }
810 printActive = false;
811 return; // not yet available ..
812 }
813 final GLAutoDrawable glad = getGLAD();
814 if( null == glad ) {
815 if( DEBUG ) {
816 System.err.println("AWT print.setup exit, newtChild not a GLAutoDrawable: "+newtChild);
817 }
818 printActive = false;
819 return;
820 }
821 printAnimator = glad.getAnimator();
822 if( null != printAnimator ) {
823 printAnimator.remove(glad);
824 }
825 printGLAD = glad; // _not_ default, shall be replaced by offscreen GLAD
826 final GLCapabilitiesImmutable gladCaps = glad.getChosenGLCapabilities();
827 final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
828 GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
829 final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
830 final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
831 printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
832 final boolean reqNewGLADOnscrn = gladCaps.isOnscreen();
833
834 final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
835 newGLADCaps.setDoubleBuffered(false);
836 newGLADCaps.setOnscreen(false);
837 if( printNumSamples != newGLADCaps.getNumSamples() ) {
838 newGLADCaps.setSampleBuffers(0 < printNumSamples);
839 newGLADCaps.setNumSamples(printNumSamples);
840 }
841 final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(glad.getRequestedGLCapabilities(), gladCaps, newGLADCaps);
842
843 final boolean reqNewGLAD = ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
844
845 if( DEBUG ) {
846 System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
847 ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
848 ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
849 ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
850 ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
851 }
852 if( reqNewGLAD ) {
853 final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
854 GLOffscreenAutoDrawable offGLAD = null;
855 try {
856 offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
857 printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
858 printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
859 } catch (final GLException gle) {
860 if( DEBUG ) {
861 System.err.println("Caught: "+gle.getMessage());
862 gle.printStackTrace();
863 }
864 }
865 if( null != offGLAD ) {
866 printGLAD = offGLAD;
867 GLDrawableUtil.swapGLContextAndAllGLEventListener(glad, printGLAD);
868 printDrawable = printGLAD.getDelegatedDrawable();
869 }
870 }
871 printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
872 printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
873 printAWTTiles.renderer.attachAutoDrawable(printGLAD);
874 if( DEBUG ) {
875 System.err.println("AWT print.setup "+printAWTTiles);
876 System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
877 System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
878 System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
879 }
880 }
881 }
882 };
883
884 @Override
885 public void releasePrint() {
886 if( !printActive || null == printGLAD ) {
887 throw new IllegalStateException("setupPrint() not called");
888 }
889 // sendReshape = false; // clear reshape flag
890 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
891 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
892 }
893 private final Runnable releasePrintOnEDT = new Runnable() {
894 @Override
895 public void run() {
896 synchronized(sync) {
897 if( DEBUG ) {
898 System.err.println("AWT print.release "+printAWTTiles);
899 }
900 final GLAutoDrawable glad = getGLAD();
901 printAWTTiles.dispose();
902 printAWTTiles= null;
903 if( printGLAD != glad ) {
904 GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, glad);
905 printGLAD.destroy();
906 }
907 printGLAD = null;
908 if( null != printAnimator ) {
909 printAnimator.add(glad);
910 printAnimator = null;
911 }
912 printActive = false;
913 }
914 }
915 };
916
917 @Override
918 public void print(final Graphics graphics) {
919 synchronized(sync) {
920 if( !printActive || null == printGLAD ) {
921 throw new IllegalStateException("setupPrint() not called");
922 }
923 if(DEBUG && !EventQueue.isDispatchThread()) {
924 System.err.println(currentThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
925 // we cannot dispatch print on AWT-EDT due to printing internal locking ..
926 }
927
928 final Graphics2D g2d = (Graphics2D)graphics;
929 try {
930 printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
931 final TileRenderer tileRenderer = printAWTTiles.renderer;
932 if( DEBUG ) {
933 System.err.println("AWT print.0: "+tileRenderer);
934 }
935 if( !tileRenderer.eot() ) {
936 try {
937 do {
938 tileRenderer.display();
939 } while ( !tileRenderer.eot() );
940 if( DEBUG ) {
941 System.err.println("AWT print.1: "+printAWTTiles);
942 }
943 tileRenderer.reset();
944 } finally {
945 printAWTTiles.resetGraphics2D();
946 }
947 }
948 } catch (final NoninvertibleTransformException nte) {
949 System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
950 nte.printStackTrace();
951 }
952 if( DEBUG ) {
953 System.err.println("AWT print.X: "+printAWTTiles);
954 }
955 }
956 }
957
958 private final boolean validateComponent(final boolean attachNewtChild) {
959 if( Beans.isDesignTime() || !isDisplayable() ) {
960 return false;
961 }
962 if ( null == newtChild || null == jawtWindow ) {
963 return false;
964 }
965 if( 0 >= getWidth() || 0 >= getHeight() ) {
966 return false;
967 }
968
969 if( attachNewtChild && !newtChildAttached && null != newtChild ) {
970 attachNewtChild();
971 }
972
973 return true;
974 }
975
976 private final void configureNewtChild(final boolean attach) {
977 awtWinAdapter.clear();
978 awtKeyAdapter.clear();
979 awtMouseAdapter.clear();
980
981 if(null != keyboardFocusManager) {
982 keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
983 keyboardFocusManager = null;
984 }
985
986 if( null != newtChild ) {
987 newtChild.setKeyboardFocusHandler(null);
988 if(attach) {
989 if(null == jawtWindow.getGraphicsConfiguration()) {
990 throw new InternalError("XXX");
991 }
992 isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
993 awtWinAdapter.setDownstream(jawtWindow, newtChild);
994 newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
995 newtChild.setFocusAction(focusAction); // enable AWT focus traversal
996 newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
997 keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
998 keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
999 // force this AWT Canvas to be focus-able,
1000 // since this it is completely covered by the newtChild (z-order).
1001 setFocusable(true);
1002 if(isOnscreen) {
1003 // onscreen newt child needs to fwd AWT focus
1004 newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
1005 } else {
1006 // offscreen newt child requires AWT to fwd AWT key/mouse event
1007 awtMouseAdapter.setDownstream(newtChild);
1008 // We cannot consume AWT mouse click, since it would disable focus via mouse click!
1009 // awtMouseAdapter.setConsumeAWTEvent(true);
1010 awtKeyAdapter.setDownstream(newtChild);
1011 // We manually transfer the focus via NEWT KeyListener, hence we can mark AWT keys as consumed!
1012 awtKeyAdapter.setConsumeAWTEvent(true);
1013 }
1014 } else {
1015 newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
1016 newtChild.setFocusAction(null);
1017 newtChild.setDefaultCloseOperation(newtChildCloseOp);
1018 setFocusable(false);
1019 }
1020 }
1021 }
1022
1023 /**
1024 * Returns <code>true</code> if Key and Mouse input events will be passed through AWT,
1025 * otherwise only the {@link #getNEWTChild() NEWT child} will receive them.
1026 * <p>
1027 * Normally only the {@link #getNEWTChild() NEWT child} will receive Key and Mouse input events.
1028 * In offscreen mode, e.g. OSX/CALayer, the AWT events will be received and translated into NEWT events
1029 * and delivered to the NEWT child window.<br/>
1030 * Note: AWT key events will {@link java.awt.event.InputEvent#consume() consumed} in pass-through mode.
1031 * </p>
1032 */
1033 public final boolean isAWTEventPassThrough() {
1034 return !isOnscreen;
1035 }
1036
1037 private final void attachNewtChild() {
1038 if( null == newtChild || null == jawtWindow || newtChildAttached ) {
1039 return; // nop
1040 }
1041 if(DEBUG) {
1042 // if ( isShowing() == false ) -> Container was not visible yet.
1043 // if ( isShowing() == true ) -> Container is already visible.
1044 System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+currentThreadName());
1045 System.err.println("\twin "+newtWinHandleToHexString(newtChild)+
1046 ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
1047 ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
1048 ", cont "+AWTMisc.getContainer(this));
1049 }
1050
1051 newtChildAttached = true;
1052 newtChild.setFocusAction(null); // no AWT focus traversal ..
1053 if(DEBUG) {
1054 System.err.println("NewtCanvasAWT.attachNewtChild.1: newtChild: "+newtChild);
1055 }
1056 final int w = getWidth();
1057 final int h = getHeight();
1058 if(DEBUG) {
1059 System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+newtChild.isNativeValid());
1060 }
1061 newtChild.setVisible(false);
1062 newtChild.setSize(w, h);
1063 updatePixelScale(getGraphicsConfiguration(), true /* force */); // AWT -> NEWT
1064 newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
1065 newtChild.addSurfaceUpdatedListener(jawtWindow);
1066 if( jawtWindow.isOffscreenLayerSurfaceEnabled() &&
1067 0 != ( JAWTUtil.JAWT_OSX_CALAYER_QUIRK_POSITION & JAWTUtil.getOSXCALayerQuirks() ) ) {
1068 AWTEDTExecutor.singleton.invoke(false, forceRelayout);
1069 }
1070 newtChild.setVisible(true);
1071 configureNewtChild(true);
1072 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
1073
1074 if(DEBUG) {
1075 System.err.println("NewtCanvasAWT.attachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
1076 }
1077 }
1078 private final Runnable forceRelayout = new Runnable() {
1079 @Override
1080 public void run() {
1081 if(DEBUG) {
1082 System.err.println("NewtCanvasAWT.forceRelayout.0");
1083 }
1084 // Hack to force proper native AWT layout incl. CALayer components on OSX
1085 final java.awt.Component component = NewtCanvasAWT.this;
1086 final int cW = component.getWidth();
1087 final int cH = component.getHeight();
1088 component.setSize(cW+1, cH+1);
1089 component.setSize(cW, cH);
1090 if(DEBUG) {
1091 System.err.println("NewtCanvasAWT.forceRelayout.X");
1092 }
1093 } };
1094
1095 private final void detachNewtChild(final java.awt.Container cont) {
1096 if( null == newtChild || null == jawtWindow || !newtChildAttached ) {
1097 return; // nop
1098 }
1099 if(DEBUG) {
1100 // if ( isShowing() == false ) -> Container was not visible yet.
1101 // if ( isShowing() == true ) -> Container is already visible.
1102 System.err.println("NewtCanvasAWT.detachNewtChild.0: win "+newtWinHandleToHexString(newtChild)+
1103 ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
1104 ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
1105 ", cont "+cont);
1106 }
1107
1108 newtChild.removeSurfaceUpdatedListener(jawtWindow);
1109 newtChildAttached = false;
1110 newtChild.setFocusAction(null); // no AWT focus traversal ..
1111 configureNewtChild(false);
1112 newtChild.setVisible(false);
1113
1114 newtChild.reparentWindow(null, -1, -1, 0 /* hint */); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer
1115
1116 if(DEBUG) {
1117 System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
1118 }
1119 }
1120
1121 protected static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
1122
1123 static String newtWinHandleToHexString(final Window w) {
1124 return null != w ? toHexString(w.getWindowHandle()) : "nil";
1125 }
1126 static String toHexString(final long l) {
1127 return "0x"+Long.toHexString(l);
1128 }
1129}
1130
final CapabilitiesImmutable getRequestedCapabilities()
Return the capabilities used to choose this graphics configuration.
final CapabilitiesImmutable getChosenCapabilities()
Return the capabilities reflecting this graphics configuration, which may differ from the capabilitie...
A wrapper for an AWT GraphicsConfiguration allowing it to be handled in a toolkit-independent manner.
GraphicsConfiguration getAWTGraphicsConfiguration()
Return the AWT GraphicsConfiguration.
static AWTGraphicsConfiguration create(final GraphicsConfiguration gc, CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested)
Method constructs a new AWTGraphicsConfiguration primarily based on the given GraphicsConfiguration.
final WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
final boolean addClosingListener()
Adds this closing listener to the components Window if exist and only one time.
final boolean isOffscreenLayerSurfaceEnabled()
Returns true if this instance uses an offscreen layer, otherwise false.
abstract EDTUtil getEDTUtil()
abstract Display getDisplay()
AWT Canvas containing a NEWT Window using native parenting.
final boolean isApplet()
Returns true if the AWT component is parented to an java.applet.Applet, otherwise false.
NewtCanvasAWT(final GraphicsConfiguration gc)
Instantiates a NewtCanvas without a NEWT child.
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.
final boolean isAWTEventPassThrough()
Returns true if Key and Mouse input events will be passed through AWT, otherwise only the NEWT child ...
final boolean isOffscreenLayerSurfaceEnabled()
Returns true if this instance uses an offscreen layer, otherwise false.
final boolean getSkipJAWTDestroy()
See setSkipJAWTDestroy(boolean).
void print(final Graphics graphics)
WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
WindowClosingMode getDefaultCloseOperation()
Window setNEWTChild(final Window newChild)
Sets a new NEWT child, provoking reparenting.
NewtCanvasAWT(final Window child)
Instantiates a NewtCanvas with a NEWT child.
NewtCanvasAWT()
Instantiates a NewtCanvas without a NEWT child.
final void destroy()
Destroys this resource:
void reshape(final int x, final int y, final int width, final int height)
final void setSkipJAWTDestroy(final boolean v)
Mitigates Bug 910 (IcedTea-Web), i.e.
NativeWindow getNativeWindow()
Returns the associated NativeWindow of this NativeWindowHolder, which is identical to getNativeSurfac...
void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight)
Shall be called before PrinterJob#print().
void releasePrint()
Shall be called after PrinterJob#print().
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
NewtCanvasAWT(final GraphicsConfiguration gc, final Window child)
Instantiates a NewtCanvas with a NEWT child.
GraphicsConfiguration getGraphicsConfiguration()
final boolean getShallUseOffscreenLayer()
Returns the property set by setShallUseOffscreenLayer(boolean).
NEWT Window events are provided for notification purposes ONLY.
static final short EVENT_WINDOW_RESIZED
Convenient adapter forwarding AWT events to NEWT via the event listener model.
final synchronized void setConsumeAWTEvent(final boolean v)
synchronized AWTAdapter setDownstream(final com.jogamp.newt.Window downstream)
Setup a pipeline adapter, AWT EventListener.
abstract AWTAdapter addTo(java.awt.Component awtComponent)
Due to the fact that some NEWT com.jogamp.newt.event.NEWTEventListener are mapped to more than one ja...
synchronized AWTAdapter clear()
Removes all references, downstream and NEWT-EventListener.
AWT: printable: PRESSED (t0), TYPED (t0), RELEASED (t1) non-printable: PRESSED (t0),...
synchronized AWTAdapter addTo(final java.awt.Component awtComponent)
Due to the fact that some NEWT com.jogamp.newt.event.NEWTEventListener are mapped to more than one ja...
synchronized AWTAdapter addTo(final java.awt.Component awtComponent)
Due to the fact that some NEWT com.jogamp.newt.event.NEWTEventListener are mapped to more than one ja...
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
final void display()
Rendering one tile, by simply calling GLAutoDrawable#display().
A fairly direct port of Brian Paul's tile rendering library, found at http://www.mesa3d....
final boolean eot()
Returns true if end of tiling has been reached, otherwise false.end of tiling criteria is implementat...
final void reset()
Method resets implementation's internal state to start of tiling as required for beginTile(GL) if end...
Window closing mode if triggered by toolkit close operation.
DISPOSE_ON_CLOSE
Dispose resources on native window close operation.
Specifies an immutable set of capabilities that a window's rendering context must support,...
boolean equals(Object obj)
Equality over the immutable attributes of both objects.
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
void addSurfaceUpdatedListener(SurfaceUpdatedListener l)
Appends the given SurfaceUpdatedListener to the end of the list.
void removeSurfaceUpdatedListener(SurfaceUpdatedListener l)
Remove the specified SurfaceUpdatedListener from the list.
Accessor interface for implementing classes with ownership of a NativeWindow via an is-a or has-a rel...
Extend the NativeSurface interface with windowing information such as window-handle,...
int getHeight()
Returns the height of the client area excluding insets (window decorations) in window units.
int getWidth()
Returns the width of the client area excluding insets (window decorations) in window units.
long getWindowHandle()
Returns the window handle for this NativeWindow.
Handling requests for using an OffscreenLayerSurface within the implementation.
boolean setSurfaceScale(final float[] pixelScale)
Request a pixel scale in x- and y-direction for the associated NativeSurface, where size_in_pixel_uni...
Protocol for handling window closing events.
WindowClosingMode setDefaultCloseOperation(WindowClosingMode op)
Interface describing print lifecycle to support AWT printing, e.g.
Specifying NEWT's Window functionality:
Definition: Window.java:115
Window getDelegatedWindow()
If the implementation uses delegation, return the delegated Window instance, otherwise return this in...
void sendWindowEvent(int eventType)
Send a WindowEvent to all WindowListener.
void setKeyboardFocusHandler(KeyListener l)
Sets a KeyListener allowing focus traversal with a covered window toolkit like AWT.
ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints)
Change this window's parent window.
void addWindowListener(WindowListener l)
Appends the given com.jogamp.newt.event.WindowListener to the end of the list.
boolean windowRepaint(int x, int y, int width, int height)
Trigger window repaint while passing the dirty region in pixel units.
void requestFocus()
Request focus for this native window.
void setFocusAction(FocusRunnable focusAction)
Sets a FocusRunnable, which FocusRunnable#run() method is executed before the native focus is request...
void setSize(int width, int height)
Sets the size of the window's client area in window units, excluding decorations.
void setVisible(boolean visible)
Calls setVisible(true, visible), i.e.
CapabilitiesImmutable getRequestedCapabilities()
Gets an immutable set of requested capabilities.
void removeWindowListener(WindowListener l)
void destroy()
Destroys this window incl.releasing all related resources.
An animator control interface, which implementation may drive a com.jogamp.opengl....
void remove(GLAutoDrawable drawable)
Removes a drawable from the animator's list of rendering drawables.
void add(GLAutoDrawable drawable)
Adds a drawable to this animator's list of rendering drawables.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
int getNumSamples()
Returns the number of sample buffers to be allocated if sample buffers are enabled,...
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
boolean isGLOriented()
Returns true if the drawable is rendered in OpenGL's coordinate system, origin at bottom left.
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.