Jogamp
Bug 741 HiDPI: Simplify ScalableSurface (2): Add request pixelScale API entry, fixed...
[jogl.git] / src / newt / classes / com / jogamp / newt / awt / NewtCanvasAWT.java
CommitLineData
ea948abf
SG
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:
5e9c02bc 6 *
ea948abf
SG
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
5e9c02bc 9 *
ea948abf
SG
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.
5e9c02bc 13 *
ea948abf
SG
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.
5e9c02bc 23 *
ea948abf
SG
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.
811bd23e 27 */
5e9c02bc 28
811bd23e
SG
29
30package com.jogamp.newt.awt;
31
0c3709ba 32import java.applet.Applet;
3db4e89c 33import java.awt.AWTKeyStroke;
811bd23e 34import java.awt.Canvas;
cb7118fc 35import java.awt.Component;
fb6440fb 36import java.awt.EventQueue;
969e4276 37import java.awt.Graphics;
fb6440fb 38import java.awt.Graphics2D;
0baf1e9f 39import java.awt.GraphicsConfiguration;
b32c65e2 40import java.awt.KeyboardFocusManager;
8a4a64e1 41import java.awt.geom.NoninvertibleTransformException;
af384deb 42import java.beans.Beans;
8a985f86
SG
43import java.beans.PropertyChangeEvent;
44import java.beans.PropertyChangeListener;
46542168
SG
45import java.lang.reflect.Method;
46import java.security.AccessController;
47import java.security.PrivilegedAction;
3db4e89c 48import java.util.Set;
46542168 49
2cbab63b 50import javax.media.nativewindow.NativeWindow;
8e0f3ad5 51import javax.media.nativewindow.OffscreenLayerOption;
2cbab63b 52import javax.media.nativewindow.WindowClosingProtocol;
fb6440fb
SG
53import javax.media.opengl.GLAnimatorControl;
54import javax.media.opengl.GLAutoDrawable;
55import javax.media.opengl.GLCapabilities;
c943c8cf 56import javax.media.opengl.GLDrawable;
fb6440fb 57import javax.media.opengl.GLDrawableFactory;
46542168 58import javax.swing.MenuSelectionManager;
811bd23e 59
46542168 60import jogamp.nativewindow.awt.AWTMisc;
4b5435c6 61import jogamp.nativewindow.jawt.JAWTUtil;
360b6716 62import jogamp.newt.Debug;
808a9a27 63import jogamp.newt.WindowImpl;
8a985f86 64import jogamp.newt.awt.NewtFactoryAWT;
8c894030 65import jogamp.newt.awt.event.AWTParentWindowAdapter;
8a985f86 66import jogamp.newt.driver.DriverClearFocus;
fb6440fb 67import jogamp.opengl.awt.AWTTilePainter;
8c894030 68
57bf60b7 69import com.jogamp.common.util.awt.AWTEDTExecutor;
c2ce31e1 70import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
efa70cd3
SG
71import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
72import com.jogamp.nativewindow.awt.JAWTWindow;
46542168
SG
73import com.jogamp.newt.Display;
74import com.jogamp.newt.Window;
3db4e89c
SG
75import com.jogamp.newt.event.KeyEvent;
76import com.jogamp.newt.event.KeyListener;
46542168
SG
77import com.jogamp.newt.event.WindowAdapter;
78import com.jogamp.newt.event.WindowEvent;
79import com.jogamp.newt.event.WindowListener;
80import com.jogamp.newt.event.awt.AWTAdapter;
81import com.jogamp.newt.event.awt.AWTKeyAdapter;
82import com.jogamp.newt.event.awt.AWTMouseAdapter;
fb6440fb
SG
83import com.jogamp.opengl.util.GLDrawableUtil;
84import com.jogamp.opengl.util.TileRenderer;
811bd23e 85
4dd44b98
SG
86/**
87 * AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting.
5e9c02bc 88 *
4dd44b98 89 * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5>
5e9c02bc 90 *
4dd44b98 91 * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
5e9c02bc 92 * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
4dd44b98
SG
93 * the underlying JAWT mechanism to composite the image, if supported.
94 */
ac49f30c 95@SuppressWarnings("serial")
fb6440fb 96public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle {
63be4a40 97 public static final boolean DEBUG = Debug.debug("Window");
811bd23e 98
d8f7418f 99 private final Object sync = new Object();
8a985f86 100 private JAWTWindow jawtWindow = null;
0c3709ba 101 private boolean isApplet = false;
c84e235b 102 private boolean shallUseOffscreenLayer = false;
8a985f86 103 private Window newtChild = null;
af384deb 104 private boolean newtChildAttached = false;
8a985f86 105 private boolean isOnscreen = true;
935523a8 106 private WindowClosingMode newtChildCloseOp;
ebe980ad 107 private final AWTParentWindowAdapter awtWinAdapter;
b335cf08
SG
108 private final AWTAdapter awtMouseAdapter;
109 private final AWTAdapter awtKeyAdapter;
5e9c02bc 110
1617b3ed 111 /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
0c3709ba 112 private boolean destroyJAWTPending = false;
1617b3ed
SG
113 /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
114 private boolean skipJAWTDestroy = false;
0c3709ba
SG
115
116 /** Safeguard for AWTWindowClosingProtocol and 'removeNotify()' on other thread than AWT-EDT. */
117 private volatile boolean componentAdded = false;
118
7f7a23dd 119 private final AWTWindowClosingProtocol awtWindowClosingProtocol =
2cbab63b 120 new AWTWindowClosingProtocol(this, new Runnable() {
f1ae8ddb 121 @Override
2cbab63b 122 public void run() {
0c3709ba
SG
123 if( componentAdded ) {
124 NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */);
125 }
2cbab63b 126 }
808a9a27 127 }, new Runnable() {
f1ae8ddb 128 @Override
808a9a27 129 public void run() {
0c3709ba 130 if( componentAdded && newtChild != null ) {
808a9a27
SG
131 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
132 }
5e9c02bc 133 }
808a9a27 134 } );
2cbab63b 135
811bd23e
SG
136 /**
137 * Instantiates a NewtCanvas without a NEWT child.<br>
811bd23e
SG
138 */
139 public NewtCanvasAWT() {
140 super();
b335cf08
SG
141 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
142 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
ebe980ad
SG
143 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
144 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
811bd23e
SG
145 }
146
147 /**
0baf1e9f
SG
148 * Instantiates a NewtCanvas without a NEWT child.<br>
149 */
150 public NewtCanvasAWT(GraphicsConfiguration gc) {
151 super(gc);
b335cf08
SG
152 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
153 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
ebe980ad
SG
154 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
155 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
0baf1e9f
SG
156 }
157
158 /**
811bd23e
SG
159 * Instantiates a NewtCanvas with a NEWT child.
160 */
161 public NewtCanvasAWT(Window child) {
162 super();
b335cf08
SG
163 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
164 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
ebe980ad
SG
165 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
166 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
811bd23e
SG
167 setNEWTChild(child);
168 }
969e4276 169
0baf1e9f
SG
170 /**
171 * Instantiates a NewtCanvas with a NEWT child.
172 */
173 public NewtCanvasAWT(GraphicsConfiguration gc, Window child) {
174 super(gc);
b335cf08
SG
175 awtMouseAdapter = new AWTMouseAdapter().addTo(this);
176 awtKeyAdapter = new AWTKeyAdapter().addTo(this);
ebe980ad
SG
177 awtWinAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
178 awtWinAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
0baf1e9f
SG
179 setNEWTChild(child);
180 }
5e9c02bc 181
f1ae8ddb 182 @Override
8a16d590 183 public void setShallUseOffscreenLayer(boolean v) {
c84e235b 184 shallUseOffscreenLayer = v;
8a16d590 185 }
5e9c02bc 186
f1ae8ddb 187 @Override
8e0f3ad5 188 public final boolean getShallUseOffscreenLayer() {
5e9c02bc 189 return shallUseOffscreenLayer;
8a16d590 190 }
5e9c02bc 191
f1ae8ddb 192 @Override
5e9c02bc 193 public final boolean isOffscreenLayerSurfaceEnabled() {
d8f7418f
SG
194 final JAWTWindow w = jawtWindow;
195 return null != w && w.isOffscreenLayerSurfaceEnabled();
8e0f3ad5 196 }
5e9c02bc
HH
197
198 /**
199 * Returns true if the AWT component is parented to an {@link java.applet.Applet},
0c3709ba 200 * otherwise false. This information is valid only after {@link #addNotify()} is issued.
8a16d590 201 */
0c3709ba
SG
202 public final boolean isApplet() {
203 return isApplet;
46542168 204 }
73d6ec97 205
0c3709ba
SG
206 private final boolean isParent() {
207 final Window nw = newtChild;
208 return null!=nw && jawtWindow == nw.getParent();
73d6ec97 209 }
5e9c02bc 210
0c3709ba
SG
211 private final boolean isFullscreen() {
212 final Window nw = newtChild;
213 return null != nw && nw.isFullscreen();
73d6ec97 214 }
5e9c02bc 215
a4b16ad5 216 class FocusAction implements Window.FocusRunnable {
f1ae8ddb 217 @Override
a4b16ad5 218 public boolean run() {
73d6ec97
SG
219 final boolean isParent = isParent();
220 final boolean isFullscreen = isFullscreen();
8a985f86 221 if(DEBUG) {
73d6ec97 222 System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()+", isParent "+isParent+", isFS "+isFullscreen);
a4b16ad5 223 }
23697c79
SG
224 if( isParent && !isFullscreen ) { // must be parent of newtChild _and_ newtChild not fullscreen
225 if( isOnscreen ) {
226 // Remove the AWT focus in favor of the native NEWT focus
d544c839 227 AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
b5b5b0f9 228 } else if( !hasFocus() ) {
23697c79 229 // In offscreen mode we require the focus!
b5b5b0f9
SG
230 // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
231 NewtCanvasAWT.super.requestFocus();
23697c79 232 }
969e4276 233 }
8a985f86 234 return false; // NEWT shall proceed requesting the native focus
969e4276
SG
235 }
236 }
7f7a23dd 237 private final FocusAction focusAction = new FocusAction();
5e9c02bc 238
d544c839
HH
239 private static class ClearFocusOwner implements Runnable {
240 @Override
241 public void run() {
242 KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
243 }
244 }
245 private static final Runnable awtClearGlobalFocusOwner = new ClearFocusOwner();
246
0be87f24
SG
247 /** Must run on AWT-EDT non-blocking, since it invokes tasks on AWT-EDT w/ waiting otherwise. */
248 private final Runnable awtClearSelectedMenuPath = new Runnable() {
41767521 249 @Override
0be87f24
SG
250 public void run() {
251 MenuSelectionManager.defaultManager().clearSelectedPath();
252 }
253 };
254 private final WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
10c696f7 255 @Override
af384deb
SG
256 public void windowResized(WindowEvent e) {
257 updateLayoutSize();
258 }
259 @Override
2cbab63b 260 public void windowGainedFocus(WindowEvent arg0) {
73d6ec97 261 if( isParent() && !isFullscreen() ) {
0be87f24 262 AWTEDTExecutor.singleton.invoke(false, awtClearSelectedMenuPath);
73d6ec97 263 }
2cbab63b
SG
264 }
265 };
266
3db4e89c 267 class FocusTraversalKeyListener implements KeyListener {
f1ae8ddb 268 @Override
3db4e89c 269 public void keyPressed(KeyEvent e) {
73d6ec97
SG
270 if( isParent() && !isFullscreen() ) {
271 handleKey(e, false);
272 }
3db4e89c 273 }
f1ae8ddb 274 @Override
3db4e89c 275 public void keyReleased(KeyEvent e) {
73d6ec97
SG
276 if( isParent() && !isFullscreen() ) {
277 handleKey(e, true);
278 }
3db4e89c 279 }
5e9c02bc
HH
280
281 void handleKey(KeyEvent evt, boolean onRelease) {
8a985f86
SG
282 if(null == keyboardFocusManager) {
283 throw new InternalError("XXX");
284 }
285 final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease);
8b33170e 286 boolean suppress = false;
3db4e89c 287 if(null != ks) {
5e9c02bc 288 final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
8b33170e 289 final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
3db4e89c 290 if(fwdKeys.contains(ks)) {
62f9525a 291 final Component nextFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, true /* forward */);
3db4e89c 292 if(DEBUG) {
cb7118fc 293 System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", nextFocus "+nextFocus);
3db4e89c 294 }
8a985f86 295 // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
cb7118fc 296 nextFocus.requestFocus();
3db4e89c
SG
297 suppress = true;
298 } else if(bwdKeys.contains(ks)) {
62f9525a 299 final Component prevFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, false /* forward */);
3db4e89c 300 if(DEBUG) {
cb7118fc 301 System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", prevFocus "+prevFocus);
3db4e89c 302 }
8a985f86 303 // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
cb7118fc 304 prevFocus.requestFocus();
3db4e89c 305 suppress = true;
3db4e89c 306 }
3db4e89c
SG
307 }
308 if(suppress) {
5e9c02bc 309 evt.setConsumed(true);
8a985f86
SG
310 }
311 if(DEBUG) {
312 System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks);
3db4e89c
SG
313 }
314 }
315 }
5e9c02bc 316 private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener();
8a985f86
SG
317
318 class FocusPropertyChangeListener implements PropertyChangeListener {
f1ae8ddb 319 @Override
8a985f86
SG
320 public void propertyChange(PropertyChangeEvent evt) {
321 final Object oldF = evt.getOldValue();
322 final Object newF = evt.getNewValue();
73d6ec97 323 final boolean isParent = isParent();
5e9c02bc 324 final boolean isFullscreen = isFullscreen();
8a985f86 325 if(DEBUG) {
73d6ec97 326 System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF+", isParent "+isParent+", isFS "+isFullscreen);
8a985f86 327 }
73d6ec97 328 if(isParent && !isFullscreen) {
9997ce1f 329 if(newF == NewtCanvasAWT.this) {
5e9c02bc 330 if(DEBUG) {
9997ce1f
SG
331 System.err.println("NewtCanvasAWT.FocusProperty: AWT focus -> NEWT focus traversal");
332 }
333 requestFocusNEWTChild();
334 } else if(oldF == NewtCanvasAWT.this && newF == null) {
73d6ec97 335 // focus traversal to NEWT - NOP
5e9c02bc 336 if(DEBUG) {
9997ce1f 337 System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus");
73d6ec97
SG
338 }
339 } else if(null != newF && newF != NewtCanvasAWT.this) {
340 // focus traversal to another AWT component
5e9c02bc 341 if(DEBUG) {
73d6ec97
SG
342 System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus");
343 }
344 if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) {
345 ((DriverClearFocus)newtChild.getDelegatedWindow()).clearFocus();
346 }
8a985f86
SG
347 }
348 }
5e9c02bc 349 }
8a985f86
SG
350 }
351 private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener();
352 private volatile KeyboardFocusManager keyboardFocusManager = null;
353
9997ce1f
SG
354 private final void requestFocusNEWTChild() {
355 if(null!=newtChild) {
356 newtChild.setFocusAction(null);
5e9c02bc 357 if(isOnscreen) {
177d0da1 358 AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
9997ce1f
SG
359 }
360 newtChild.requestFocus();
361 newtChild.setFocusAction(focusAction);
362 }
363 }
364
5e9c02bc 365 /**
7bb5885f
SG
366 * Sets a new NEWT child, provoking reparenting.
367 * <p>
368 * A previously detached <code>newChild</code> will be released to top-level status
5e9c02bc 369 * and made invisible.
7bb5885f
SG
370 * </p>
371 * <p>
5e9c02bc
HH
372 * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
373 * produced much cleaner visual results.
7bb5885f 374 * </p>
5e9c02bc 375 * @return the previous attached newt child.
7bb5885f
SG
376 */
377 public Window setNEWTChild(Window newChild) {
d8f7418f
SG
378 synchronized(sync) {
379 final Window prevChild = newtChild;
380 if(DEBUG) {
381 System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
382 }
383 final java.awt.Container cont = AWTMisc.getContainer(this);
384 // remove old one
385 if(null != newtChild) {
386 detachNewtChild( cont );
387 newtChild = null;
388 }
389 // add new one, reparent only if ready
390 newtChild = newChild;
af384deb 391
d8f7418f
SG
392 updateLayoutSize();
393 // will be done later at paint/display/..: attachNewtChild(cont);
5e9c02bc 394
d8f7418f
SG
395 return prevChild;
396 }
811bd23e 397 }
5e9c02bc 398
af384deb 399 private final void updateLayoutSize() {
d8f7418f
SG
400 final Window w = newtChild;
401 if( null != w ) {
af384deb 402 // use NEWT child's size for min/pref size!
d149c554 403 java.awt.Dimension minSize = new java.awt.Dimension(w.getWidth(), w.getHeight());
af384deb
SG
404 setMinimumSize(minSize);
405 setPreferredSize(minSize);
5e9c02bc 406 }
af384deb 407 }
811bd23e
SG
408
409 /** @return the current NEWT child */
410 public Window getNEWTChild() {
411 return newtChild;
412 }
413
0feca163 414 /** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called,
811bd23e 415 * or {@link #addNotify()} hasn't been called yet.*/
8a16d590 416 public NativeWindow getNativeWindow() { return jawtWindow; }
5e9c02bc 417
f1ae8ddb 418 @Override
935523a8 419 public WindowClosingMode getDefaultCloseOperation() {
2cbab63b
SG
420 return awtWindowClosingProtocol.getDefaultCloseOperation();
421 }
422
f1ae8ddb 423 @Override
935523a8 424 public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
2cbab63b
SG
425 return awtWindowClosingProtocol.setDefaultCloseOperation(op);
426 }
427
1617b3ed
SG
428 /**
429 * Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy().
430 * <p>
431 * <code>skipJAWTDestroy</code> defaults to <code>false</code>.
432 * Due to above IcedTea-Web issue the <code>Applet</code> code needs to avoid JAWT destruction before
433 * <code>Applet.destroy()</code> is reached by setting <code>skipJAWTDestroy</code> to <code>true</code>.
434 * Afterwards the value should be reset to <code>false</code> and {@link #destroy()} needs to be called,
435 * which finally will perform the pending JAWT destruction.
436 * </p>
437 */
438 public final void setSkipJAWTDestroy(boolean v) { skipJAWTDestroy = v; }
439 /** See {@link #setSkipJAWTDestroy(boolean)}. */
440 public final boolean getSkipJAWTDestroy() { return skipJAWTDestroy; }
441
0c3709ba
SG
442 private final void determineIfApplet() {
443 isApplet = false;
444 Component c = this;
445 while(!isApplet && null != c) {
446 isApplet = c instanceof Applet;
447 c = c.getParent();
448 }
449 }
450
10c696f7 451 @Override
811bd23e 452 public void addNotify() {
af384deb
SG
453 if( Beans.isDesignTime() ) {
454 super.addNotify();
455 } else {
456 // before native peer is valid: X11
457 disableBackgroundErase();
5e9c02bc 458
af384deb
SG
459 // creates the native peer
460 super.addNotify();
5e9c02bc 461
af384deb
SG
462 // after native peer is valid: Windows
463 disableBackgroundErase();
5e9c02bc 464
d8f7418f 465 synchronized(sync) {
0c3709ba 466 determineIfApplet();
0c3709ba 467 if(DEBUG) {
1617b3ed 468 System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+EventQueue.isDispatchThread()+" @ "+currentThreadName());
0c3709ba
SG
469 Thread.dumpStack();
470 }
471 jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null);
d8f7418f 472 jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
0c3709ba
SG
473 awtWindowClosingProtocol.addClosingListener();
474 componentAdded = true; // Bug 910
d8f7418f
SG
475 if(DEBUG) {
476 // if ( isShowing() == false ) -> Container was not visible yet.
477 // if ( isShowing() == true ) -> Container is already visible.
0c3709ba 478 System.err.println("NewtCanvasAWT.addNotify.X: twin "+newtWinHandleToHexString(newtChild)+
d8f7418f
SG
479 ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+
480 ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this));
481 }
af384deb 482 }
7bb5885f 483 }
811bd23e
SG
484 }
485
10c696f7 486 @Override
811bd23e 487 public void removeNotify() {
af384deb
SG
488 if( Beans.isDesignTime() ) {
489 super.removeNotify();
490 } else {
0c3709ba
SG
491 if(DEBUG) {
492 System.err.println("NewtCanvasAWT.removeNotify.0 - isApplet "+isApplet+" @ "+currentThreadName());
493 Thread.dumpStack();
494 }
495 componentAdded = false; // Bug 910
496 awtWindowClosingProtocol.removeClosingListener();
808a9a27 497 destroyImpl(true /* removeNotify */, false /* windowClosing */);
af384deb 498 super.removeNotify();
0c3709ba
SG
499 if(DEBUG) {
500 System.err.println("NewtCanvasAWT.removeNotify.X @ "+currentThreadName());
501 }
7bb5885f 502 }
ce8c3735
SG
503 }
504
bcad73dc 505 /**
bcad73dc
SG
506 * Destroys this resource:
507 * <ul>
508 * <li> Make the NEWT Child invisible </li>
509 * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
db4d7d19
SG
510 * <li> Issues <code>destroy()</code> on the NEWT Child</li>
511 * <li> Remove reference to the NEWT Child</li>
bcad73dc
SG
512 * </ul>
513 * @see Window#destroy()
bcad73dc 514 */
db4d7d19 515 public final void destroy() {
0c3709ba
SG
516 if(DEBUG) {
517 System.err.println("NewtCanvasAWT.destroy() @ "+currentThreadName());
518 Thread.dumpStack();
519 }
d8f7418f 520 AWTEDTExecutor.singleton.invoke(true, new Runnable() {
41767521 521 @Override
d8f7418f
SG
522 public void run() {
523 destroyImpl(false /* removeNotify */, false /* windowClosing */);
524 } } );
808a9a27 525 }
5e9c02bc 526
808a9a27 527 private final void destroyImpl(boolean removeNotify, boolean windowClosing) {
d8f7418f 528 synchronized(sync) {
0c3709ba 529 final java.awt.Container cont = AWTMisc.getContainer(this);
0c3709ba
SG
530 if(DEBUG) {
531 System.err.println("NewtCanvasAWT.destroyImpl @ "+currentThreadName());
1617b3ed 532 System.err.println("NewtCanvasAWT.destroyImpl.0 - isApplet "+isApplet+", isOnAWTEDT "+EventQueue.isDispatchThread()+", skipJAWTDestroy "+skipJAWTDestroy+
0c3709ba
SG
533 "; removeNotify "+removeNotify+", windowClosing "+windowClosing+", destroyJAWTPending "+destroyJAWTPending+
534 ", hasJAWT "+(null!=jawtWindow)+", hasNEWT "+(null!=newtChild)+
535 "): nw "+newtWinHandleToHexString(newtChild)+", from "+cont);
536 }
d8f7418f 537 if( null !=newtChild ) {
d8f7418f
SG
538 detachNewtChild(cont);
539
540 if( !removeNotify ) {
541 final Window cWin = newtChild;
542 final Window dWin = cWin.getDelegatedWindow();
543 newtChild=null;
544 if( windowClosing && dWin instanceof WindowImpl ) {
545 ((WindowImpl)dWin).windowDestroyNotify(true);
546 } else {
547 cWin.destroy();
548 }
808a9a27 549 }
5e9c02bc 550 }
0c3709ba 551 if( ( destroyJAWTPending || removeNotify || windowClosing ) && null!=jawtWindow ) {
1617b3ed
SG
552 if( skipJAWTDestroy ) {
553 // Bug 910 - See setSkipJAWTDestroy(boolean)
554 destroyJAWTPending = true;
555 } else {
0c3709ba
SG
556 NewtFactoryAWT.destroyNativeWindow(jawtWindow);
557 jawtWindow=null;
558 destroyJAWTPending = false;
0c3709ba 559 }
d8f7418f 560 }
5e9c02bc 561 }
af384deb 562 }
5e9c02bc 563
10c696f7 564 @Override
ce8c3735 565 public void paint(Graphics g) {
d8f7418f
SG
566 synchronized(sync) {
567 if( validateComponent(true) && !printActive ) {
568 newtChild.windowRepaint(0, 0, getWidth(), getHeight());
569 }
969e4276
SG
570 }
571 }
10c696f7 572 @Override
969e4276 573 public void update(Graphics g) {
a27af8dc 574 paint(g);
ce8c3735 575 }
811bd23e 576
af384deb
SG
577 @SuppressWarnings("deprecation")
578 @Override
579 public void reshape(int x, int y, int width, int height) {
580 synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
d8f7418f
SG
581 synchronized(sync) {
582 super.reshape(x, y, width, height);
583 if(DEBUG) {
584 System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height);
585 }
586 if( validateComponent(true) ) {
587 // newtChild.setSize(width, height);
588 }
af384deb
SG
589 }
590 }
591 }
5e9c02bc 592
fb6440fb 593 private volatile boolean printActive = false;
5e9c02bc 594 private GLAnimatorControl printAnimator = null;
fb6440fb
SG
595 private GLAutoDrawable printGLAD = null;
596 private AWTTilePainter printAWTTiles = null;
597
c2ce31e1
SG
598 private final GLAutoDrawable getGLAD() {
599 if( null != newtChild && newtChild instanceof GLAutoDrawable ) {
600 return (GLAutoDrawable)newtChild;
601 }
602 return null;
603 }
5e9c02bc 604
fb6440fb 605 @Override
a05b87a3 606 public void setupPrint(double scaleMatX, double scaleMatY, int numSamples, int tileWidth, int tileHeight) {
5e9c02bc 607 printActive = true;
fb6440fb
SG
608 final int componentCount = isOpaque() ? 3 : 4;
609 final TileRenderer printRenderer = new TileRenderer();
a05b87a3 610 printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
fb6440fb 611 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
5e9c02bc 612 }
fb6440fb
SG
613 private final Runnable setupPrintOnEDT = new Runnable() {
614 @Override
615 public void run() {
d8f7418f
SG
616 synchronized(sync) {
617 if( !validateComponent(true) ) {
618 if(DEBUG) {
0c3709ba 619 System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable not valid yet");
d8f7418f
SG
620 }
621 printActive = false;
622 return; // not yet available ..
988da6f3 623 }
083e430a 624 if( !isVisible() ) {
d8f7418f 625 if(DEBUG) {
083e430a 626 System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, canvas not visible");
d8f7418f
SG
627 }
628 printActive = false;
629 return; // not yet available ..
988da6f3 630 }
d8f7418f
SG
631 final GLAutoDrawable glad = getGLAD();
632 if( null == glad ) {
633 if( DEBUG ) {
634 System.err.println("AWT print.setup exit, newtChild not a GLAutoDrawable: "+newtChild);
635 }
636 printActive = false;
637 return;
638 }
639 printAnimator = glad.getAnimator();
640 if( null != printAnimator ) {
641 printAnimator.remove(glad);
642 }
643 printGLAD = glad; // _not_ default, shall be replaced by offscreen GLAD
644 final GLCapabilities caps = (GLCapabilities)glad.getChosenGLCapabilities().cloneMutable();
645 final int printNumSamples = printAWTTiles.getNumSamples(caps);
646 GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
647 final boolean reqNewGLADSamples = printNumSamples != caps.getNumSamples();
f9a00b91
SG
648 final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
649 printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
d8f7418f
SG
650 final boolean reqNewGLADOnscrn = caps.isOnscreen();
651
652 // It is desired to use a new offscreen GLAD, however Bug 830 forbids this for AA onscreen context.
653 // Bug 830: swapGLContextAndAllGLEventListener and onscreen MSAA w/ NV/GLX
654 final boolean reqNewGLAD = !caps.getSampleBuffers() && ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize );
988da6f3 655 if( DEBUG ) {
d8f7418f 656 System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+"], "+
f9a00b91 657 ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
d8f7418f
SG
658 ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
659 ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
660 ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
988da6f3 661 }
d8f7418f
SG
662 if( reqNewGLAD ) {
663 caps.setDoubleBuffered(false);
664 caps.setOnscreen(false);
665 if( printNumSamples != caps.getNumSamples() ) {
666 caps.setSampleBuffers(0 < printNumSamples);
667 caps.setNumSamples(printNumSamples);
668 }
669 final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
670 printGLAD = factory.createOffscreenAutoDrawable(null, caps, null,
671 printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
672 printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
673 GLDrawableUtil.swapGLContextAndAllGLEventListener(glad, printGLAD);
674 printDrawable = printGLAD.getDelegatedDrawable();
675 }
f8c2a901 676 printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
f9a00b91 677 printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
d8f7418f
SG
678 printAWTTiles.renderer.attachAutoDrawable(printGLAD);
679 if( DEBUG ) {
680 System.err.println("AWT print.setup "+printAWTTiles);
681 System.err.println("AWT print.setup AA "+printNumSamples+", "+caps);
f9a00b91
SG
682 System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
683 System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
fb6440fb 684 }
fb6440fb
SG
685 }
686 }
687 };
688
689 @Override
690 public void releasePrint() {
691 if( !printActive || null == printGLAD ) {
692 throw new IllegalStateException("setupPrint() not called");
693 }
694 // sendReshape = false; // clear reshape flag
695 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
696 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
fb6440fb
SG
697 }
698 private final Runnable releasePrintOnEDT = new Runnable() {
699 @Override
700 public void run() {
d8f7418f
SG
701 synchronized(sync) {
702 if( DEBUG ) {
703 System.err.println("AWT print.release "+printAWTTiles);
704 }
705 final GLAutoDrawable glad = getGLAD();
706 printAWTTiles.dispose();
707 printAWTTiles= null;
708 if( printGLAD != glad ) {
709 GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, glad);
710 printGLAD.destroy();
711 }
712 printGLAD = null;
713 if( null != printAnimator ) {
714 printAnimator.add(glad);
715 printAnimator = null;
716 }
717 printActive = false;
fb6440fb 718 }
fb6440fb
SG
719 }
720 };
721
722 @Override
723 public void print(Graphics graphics) {
d8f7418f
SG
724 synchronized(sync) {
725 if( !printActive || null == printGLAD ) {
726 throw new IllegalStateException("setupPrint() not called");
2634ce35 727 }
d8f7418f 728 if(DEBUG && !EventQueue.isDispatchThread()) {
0c3709ba 729 System.err.println(currentThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
d8f7418f
SG
730 // we cannot dispatch print on AWT-EDT due to printing internal locking ..
731 }
732
733 final Graphics2D g2d = (Graphics2D)graphics;
734 try {
735 printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
736 final TileRenderer tileRenderer = printAWTTiles.renderer;
737 if( DEBUG ) {
738 System.err.println("AWT print.0: "+tileRenderer);
739 }
740 if( !tileRenderer.eot() ) {
741 try {
742 do {
743 tileRenderer.display();
744 } while ( !tileRenderer.eot() );
745 if( DEBUG ) {
746 System.err.println("AWT print.1: "+printAWTTiles);
747 }
748 tileRenderer.reset();
749 } finally {
750 printAWTTiles.resetGraphics2D();
2634ce35 751 }
8a4a64e1 752 }
d8f7418f
SG
753 } catch (NoninvertibleTransformException nte) {
754 System.err.println("Catched: Inversion failed of: "+g2d.getTransform());
755 nte.printStackTrace();
756 }
757 if( DEBUG ) {
758 System.err.println("AWT print.X: "+printAWTTiles);
fb6440fb 759 }
fb6440fb
SG
760 }
761 }
5e9c02bc 762
a27af8dc 763 private final boolean validateComponent(boolean attachNewtChild) {
af384deb
SG
764 if( Beans.isDesignTime() || !isDisplayable() ) {
765 return false;
766 }
767 if ( null == newtChild || null == jawtWindow ) {
768 return false;
769 }
af384deb
SG
770 if( 0 >= getWidth() || 0 >= getHeight() ) {
771 return false;
772 }
5e9c02bc 773
af384deb 774 if( attachNewtChild && !newtChildAttached && null != newtChild ) {
a27af8dc 775 attachNewtChild();
af384deb
SG
776 }
777
778 return true;
779 }
5e9c02bc 780
af384deb 781 private final void configureNewtChild(boolean attach) {
ebe980ad
SG
782 awtWinAdapter.clear();
783 awtKeyAdapter.clear();
b335cf08 784 awtMouseAdapter.clear();
b335cf08 785
af384deb
SG
786 if(null != keyboardFocusManager) {
787 keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
788 keyboardFocusManager = null;
789 }
5e9c02bc 790
af384deb
SG
791 if( null != newtChild ) {
792 newtChild.setKeyboardFocusHandler(null);
793 if(attach) {
794 if(null == jawtWindow.getGraphicsConfiguration()) {
795 throw new InternalError("XXX");
5e9c02bc 796 }
af384deb 797 isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
ebe980ad 798 awtWinAdapter.setDownstream(jawtWindow, newtChild);
af384deb
SG
799 newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
800 newtChild.setFocusAction(focusAction); // enable AWT focus traversal
801 newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
af384deb
SG
802 keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
803 keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
e3beec5a
SG
804 // force this AWT Canvas to be focus-able,
805 // since this it is completely covered by the newtChild (z-order).
806 setFocusable(true);
af384deb
SG
807 if(isOnscreen) {
808 // onscreen newt child needs to fwd AWT focus
809 newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
810 } else {
811 // offscreen newt child requires AWT to fwd AWT key/mouse event
b335cf08
SG
812 awtMouseAdapter.setDownstream(newtChild);
813 // We cannot consume AWT mouse click, since it would disable focus via mouse click!
814 // awtMouseAdapter.setConsumeAWTEvent(true);
815 awtKeyAdapter.setDownstream(newtChild);
816 // We manually transfer the focus via NEWT KeyListener, hence we can mark AWT keys as consumed!
817 awtKeyAdapter.setConsumeAWTEvent(true);
af384deb
SG
818 }
819 } else {
820 newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
821 newtChild.setFocusAction(null);
822 newtChild.setDefaultCloseOperation(newtChildCloseOp);
e3beec5a 823 setFocusable(false);
af384deb
SG
824 }
825 }
826 }
827
ead9d657
SG
828 /**
829 * Returns <code>true</code> if Key and Mouse input events will be passed through AWT,
830 * otherwise only the {@link #getNEWTChild() NEWT child} will receive them.
831 * <p>
832 * Normally only the {@link #getNEWTChild() NEWT child} will receive Key and Mouse input events.
833 * In offscreen mode, e.g. OSX/CALayer, the AWT events will be received and translated into NEWT events
834 * and delivered to the NEWT child window.<br/>
835 * Note: AWT key events will {@link java.awt.event.InputEvent#consume() consumed} in pass-through mode.
836 * </p>
837 */
838 public final boolean isAWTEventPassThrough() {
839 return !isOnscreen;
840 }
841
a27af8dc 842 private final void attachNewtChild() {
af384deb
SG
843 if( null == newtChild || null == jawtWindow || newtChildAttached ) {
844 return; // nop
845 }
846 if(DEBUG) {
847 // if ( isShowing() == false ) -> Container was not visible yet.
848 // if ( isShowing() == true ) -> Container is already visible.
0c3709ba
SG
849 System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+currentThreadName());
850 System.err.println("\twin "+newtWinHandleToHexString(newtChild)+
af384deb
SG
851 ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
852 ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
a27af8dc 853 ", cont "+AWTMisc.getContainer(this));
af384deb
SG
854 }
855
856 newtChildAttached = true;
857 newtChild.setFocusAction(null); // no AWT focus traversal ..
858 if(DEBUG) {
859 System.err.println("NewtCanvasAWT.attachNewtChild.1: newtChild: "+newtChild);
860 }
861 final int w = getWidth();
862 final int h = getHeight();
58153310 863 final boolean isNValid = newtChild.isNativeValid();
ff0d98e2 864 if(DEBUG) {
58153310 865 System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+isNValid);
ff0d98e2 866 }
57bf60b7 867 newtChild.setVisible(false);
af384deb 868 newtChild.setSize(w, h);
58153310
SG
869 final int[] reqSurfaceScale = new int[2];
870 if( isNValid ) {
871 newtChild.getCurrentSurfaceScale(reqSurfaceScale);
872 } else {
873 newtChild.getRequestedSurfaceScale(reqSurfaceScale);
874 }
875 jawtWindow.setSurfaceScale(reqSurfaceScale);
45525950 876 newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
a27af8dc 877 newtChild.addSurfaceUpdatedListener(jawtWindow);
4b5435c6 878 if( jawtWindow.isOffscreenLayerSurfaceEnabled() &&
5e9c02bc 879 0 != ( JAWTUtil.JAWT_OSX_CALAYER_QUIRK_POSITION & JAWTUtil.getOSXCALayerQuirks() ) ) {
57bf60b7
SG
880 AWTEDTExecutor.singleton.invoke(false, forceRelayout);
881 }
af384deb
SG
882 newtChild.setVisible(true);
883 configureNewtChild(true);
884 newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
5e9c02bc 885
af384deb
SG
886 if(DEBUG) {
887 System.err.println("NewtCanvasAWT.attachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
888 }
889 }
57bf60b7 890 private final Runnable forceRelayout = new Runnable() {
f1ae8ddb 891 @Override
57bf60b7
SG
892 public void run() {
893 if(DEBUG) {
894 System.err.println("NewtCanvasAWT.forceRelayout.0");
895 }
896 // Hack to force proper native AWT layout incl. CALayer components on OSX
897 final java.awt.Component component = NewtCanvasAWT.this;
898 final int cW = component.getWidth();
899 final int cH = component.getHeight();
900 component.setSize(cW+1, cH+1);
901 component.setSize(cW, cH);
902 if(DEBUG) {
903 System.err.println("NewtCanvasAWT.forceRelayout.X");
904 }
905 } };
5e9c02bc 906
af384deb
SG
907 private final void detachNewtChild(java.awt.Container cont) {
908 if( null == newtChild || null == jawtWindow || !newtChildAttached ) {
909 return; // nop
910 }
911 if(DEBUG) {
912 // if ( isShowing() == false ) -> Container was not visible yet.
913 // if ( isShowing() == true ) -> Container is already visible.
914 System.err.println("NewtCanvasAWT.detachNewtChild.0: win "+newtWinHandleToHexString(newtChild)+
915 ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
916 ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
917 ", cont "+cont);
918 }
919
5e9c02bc 920 newtChild.removeSurfaceUpdatedListener(jawtWindow);
af384deb
SG
921 newtChildAttached = false;
922 newtChild.setFocusAction(null); // no AWT focus traversal ..
923 configureNewtChild(false);
924 newtChild.setVisible(false);
5e9c02bc 925
45525950 926 newtChild.reparentWindow(null, -1, -1, 0 /* hint */); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer
5e9c02bc 927
af384deb
SG
928 if(DEBUG) {
929 System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
930 }
931 }
932
811bd23e
SG
933 // Disables the AWT's erasing of this Canvas's background on Windows
934 // in Java SE 6. This internal API is not available in previous
935 // releases, but the system property
936 // -Dsun.awt.noerasebackground=true can be specified to get similar
937 // results globally in previous releases.
938 private static boolean disableBackgroundEraseInitialized;
939 private static Method disableBackgroundEraseMethod;
940 private void disableBackgroundErase() {
941 if (!disableBackgroundEraseInitialized) {
942 try {
417b83eb 943 AccessController.doPrivileged(new PrivilegedAction<Object>() {
f1ae8ddb 944 @Override
811bd23e
SG
945 public Object run() {
946 try {
417b83eb 947 Class<?> clazz = getToolkit().getClass();
811bd23e
SG
948 while (clazz != null && disableBackgroundEraseMethod == null) {
949 try {
950 disableBackgroundEraseMethod =
951 clazz.getDeclaredMethod("disableBackgroundErase",
952 new Class[] { Canvas.class });
953 disableBackgroundEraseMethod.setAccessible(true);
954 } catch (Exception e) {
955 clazz = clazz.getSuperclass();
956 }
957 }
958 } catch (Exception e) {
959 }
960 return null;
961 }
962 });
963 } catch (Exception e) {
964 }
965 disableBackgroundEraseInitialized = true;
aaa2b1df
SG
966 if(DEBUG) {
967 System.err.println("NewtCanvasAWT: TK disableBackgroundErase method found: "+
968 (null!=disableBackgroundEraseMethod));
969 }
811bd23e
SG
970 }
971 if (disableBackgroundEraseMethod != null) {
aaa2b1df 972 Throwable t=null;
811bd23e
SG
973 try {
974 disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this });
975 } catch (Exception e) {
aaa2b1df
SG
976 t = e;
977 }
978 if(DEBUG) {
979 System.err.println("NewtCanvasAWT: TK disableBackgroundErase error: "+t);
811bd23e
SG
980 }
981 }
982 }
fb6440fb 983
0c3709ba 984 protected static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
5e9c02bc 985
7bb5885f
SG
986 static String newtWinHandleToHexString(Window w) {
987 return null != w ? toHexString(w.getWindowHandle()) : "nil";
988 }
989 static String toHexString(long l) {
990 return "0x"+Long.toHexString(l);
991 }
811bd23e
SG
992}
993
http://JogAmp.org git info: FAQ, tutorial and man pages.