From 46542168d64b37f544f61802693f15b59b224e4e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 9 Nov 2011 07:42:20 +0100 Subject: OS X Layered View: Part5 NEWT/AWT Interaction ; Fix NSOpenGLLayer pos ; Cleanup Better JAWT* name for offscreen layer surface: - MacOSXCGLDrawableFactory, JAWTUtil, JAWTWindow, MacOSXJAWTWindow - FIXME: Need to get rid of the cached JAWT instance, in case we like to have dual usage of offscreenLayerSurface and onscreen. This would be done implicit by using NEWT .. hence low prio. AWTGraphicsConfiguration: - Fix create(): Use capsRequested for AWT aligned caps if capsChosen is null. (was capsChosen .. which is null) - Add updateGraphicsConfiguration() which allows to update the AWTGraphicsConfiguration. NewtFactoryAWT: - Add updateGraphicsConfiguration() .. entrypoint for AWTGraphicsConfiguration.updateGraphicsConfiguration() NSOpenGLLayer Impl: - For 'some reason' the layer's position is initially negative, fix it @ 1st 'draw' - Re-add CVDisplayLink OpenGL setting .. for what it's worth .. I don't know JAWTWindow: - Remove test setting: Only enable offscreenLayerSurface for applets if avail. (New unit test enables it seperatly) NewtCanvasAWT: - If NEWT child is offscreen, attach AWTMouseAdapter and AWTKeyAdapter to route these AWT input events to NEWT. - Don't loose-focus if NEWT child is offscreen. - Impl. NativeSurfaceHolder, NativeWindowHolder - NativeWindow is created at construction and it's GraphicsConfiguration updated at addNotify(..). - At addNotify/reparent: try harder to determine proper NEWT child size: - use preferred size if set - use minimum size if set - subtract insets from container size OffscreenWindow/WindowImpl: - Allow setSize() .. currently NOP for offscreen. - WindowImpl: Commented out recreate case for offscreen-setSize .. TEST: com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT Passed tests: - GLCanvas - NewtCanvasAWT/OffscreenWindow --- src/newt/classes/com/jogamp/newt/NewtFactory.java | 46 ++++--- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 151 ++++++++++++++++----- src/newt/classes/jogamp/newt/OffscreenWindow.java | 7 - src/newt/classes/jogamp/newt/WindowImpl.java | 49 +++++-- .../jogamp/newt/awt/event/NewtFactoryAWT.java | 16 ++- 5 files changed, 191 insertions(+), 78 deletions(-) (limited to 'src/newt') diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index d3be098c0..f38876128 100644 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -34,14 +34,19 @@ package com.jogamp.newt; -import javax.media.nativewindow.*; - -import com.jogamp.common.os.Platform; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowFactory; +import jogamp.newt.Debug; import jogamp.newt.DisplayImpl; import jogamp.newt.ScreenImpl; import jogamp.newt.WindowImpl; -import jogamp.newt.Debug; + +import com.jogamp.common.os.Platform; public class NewtFactory { public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); @@ -141,35 +146,34 @@ public class NewtFactory { * * @param parentWindowObject either a NativeWindow instance */ - public static Window createWindow(NativeWindow nParentWindow, CapabilitiesImmutable caps) { + public static Window createWindow(NativeWindow parentWindow, CapabilitiesImmutable caps) { final String type = NativeWindowFactory.getNativeWindowType(true); - Screen screen = null; - Window parentWindow = null; + Window newtParentWindow = null; - if ( nParentWindow instanceof Window ) { + if ( parentWindow instanceof Window ) { // use parent NEWT Windows Display/Screen - parentWindow = (Window) nParentWindow ; - screen = parentWindow.getScreen(); + newtParentWindow = (Window) parentWindow ; + screen = newtParentWindow.getScreen(); } else { // create a Display/Screen compatible to the NativeWindow - AbstractGraphicsConfiguration nParentConfig = nParentWindow.getGraphicsConfiguration(); - if(null!=nParentConfig) { - AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); - AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); - Display display = NewtFactory.createDisplay(type, nParentDevice.getHandle(), true); - screen = NewtFactory.createScreen(display, nParentScreen.getIndex()); + AbstractGraphicsConfiguration parentConfig = parentWindow.getGraphicsConfiguration(); + if(null!=parentConfig) { + AbstractGraphicsScreen parentScreen = parentConfig.getScreen(); + AbstractGraphicsDevice parentDevice = parentScreen.getDevice(); + Display display = NewtFactory.createDisplay(type, parentDevice.getHandle(), true); + screen = NewtFactory.createScreen(display, parentScreen.getIndex()); } else { Display display = NewtFactory.createDisplay(type, null, true); // local display screen = NewtFactory.createScreen(display, 0); // screen 0 } } - final Window win = createWindowImpl(nParentWindow, screen, caps); + final Window win = createWindowImpl(parentWindow, screen, caps); - win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); - if ( null != parentWindow ) { - parentWindow.addChild(win); - win.setVisible(parentWindow.isVisible()); + win.setSize(parentWindow.getWidth(), parentWindow.getHeight()); + if ( null != newtParentWindow ) { + newtParentWindow.addChild(win); + win.setVisible(newtParentWindow.isVisible()); } return win; } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 31d42d21b..4aaffb61f 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -29,42 +29,52 @@ package com.jogamp.newt.awt; -import com.jogamp.newt.Display; -import java.lang.reflect.*; -import java.security.*; - import java.awt.Canvas; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; - +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.media.nativewindow.Capabilities; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeSurfaceHolder; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.NativeWindowHolder; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.awt.AWTWindowClosingProtocol; -import jogamp.nativewindow.awt.AWTMisc; +import javax.swing.MenuSelectionManager; -import com.jogamp.newt.event.awt.AWTAdapter; -import com.jogamp.newt.event.WindowEvent; -import com.jogamp.newt.Window; -import com.jogamp.newt.event.WindowAdapter; -import com.jogamp.newt.event.WindowListener; +import jogamp.nativewindow.awt.AWTMisc; import jogamp.newt.Debug; import jogamp.newt.awt.event.AWTParentWindowAdapter; import jogamp.newt.awt.event.NewtFactoryAWT; -import javax.swing.MenuSelectionManager; +import com.jogamp.newt.Display; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowListener; +import com.jogamp.newt.event.awt.AWTAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTMouseAdapter; @SuppressWarnings("serial") -public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol { +public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, NativeSurfaceHolder, NativeWindowHolder { public static final boolean DEBUG = Debug.debug("Window"); NativeWindow nativeWindow = null; Window newtChild = null; + boolean isNewtChildOnscreen = true; int newtChildCloseOp; AWTAdapter awtAdapter = null; - + AWTAdapter awtMouseAdapter = null; + AWTAdapter awtKeyAdapter = null; + private AWTWindowClosingProtocol awtWindowClosingProtocol = new AWTWindowClosingProtocol(this, new Runnable() { public void run() { @@ -77,6 +87,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto */ public NewtCanvasAWT() { super(); + createNativeWindow(new Capabilities()); } /** @@ -84,6 +95,23 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto */ public NewtCanvasAWT(GraphicsConfiguration gc) { super(gc); + createNativeWindow(new Capabilities()); + } + + /** + * Instantiates a NewtCanvas without a NEWT child.
+ */ + public NewtCanvasAWT(CapabilitiesImmutable caps) { + super(); + createNativeWindow(caps); + } + + /** + * Instantiates a NewtCanvas without a NEWT child.
+ */ + public NewtCanvasAWT(GraphicsConfiguration gc, CapabilitiesImmutable caps) { + super(gc); + createNativeWindow(caps); } /** @@ -91,6 +119,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto */ public NewtCanvasAWT(Window child) { super(); + createNativeWindow(child.getRequestedCapabilities()); setNEWTChild(child); } @@ -99,9 +128,14 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto */ public NewtCanvasAWT(GraphicsConfiguration gc, Window child) { super(gc); + createNativeWindow(child.getRequestedCapabilities()); setNEWTChild(child); } + private final void createNativeWindow(CapabilitiesImmutable caps) { + nativeWindow = NewtFactoryAWT.getNativeWindow(this, caps); + } + class FocusAction implements Window.FocusRunnable { public boolean run() { if ( EventQueue.isDispatchThread() ) { @@ -128,7 +162,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto System.err.println("FocusActionImpl.run() "+Display.getThreadName()); } NewtCanvasAWT.this.requestFocusAWTParent(); - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + if(isNewtChildOnscreen) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } } } FocusActionImpl focusActionImpl = new FocusActionImpl(); @@ -142,13 +178,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } }; - /** sets a new NEWT child, provoking reparenting on the NEWT level. */ - /*package */ NewtCanvasAWT setNEWTChild(Window child) { + /** sets a new NEWT child, provoking reparenting. */ + private NewtCanvasAWT setNEWTChild(Window child) { if(newtChild!=child) { newtChild = child; - if(null!=nativeWindow) { - java.awt.Container cont = AWTMisc.getContainer(this); + if(isDisplayable()) { // reparent right away, addNotify has been called already + final java.awt.Container cont = AWTMisc.getContainer(this); reparentWindow( (null!=child) ? true : false, cont ); } } @@ -163,6 +199,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto /** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called, * or {@link #addNotify()} hasn't been called yet.*/ public NativeWindow getNativeWindow() { return nativeWindow; } + + /** See {@link #getNativeWindow()} */ + public NativeSurface getNativeSurface() { return nativeWindow; } public int getDefaultCloseOperation() { return awtWindowClosingProtocol.getDefaultCloseOperation(); @@ -172,11 +211,31 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto return awtWindowClosingProtocol.setDefaultCloseOperation(op); } + private final void configureNewtChildInputEventHandler() { + if(null==awtMouseAdapter && null != newtChild.getGraphicsConfiguration()) { + isNewtChildOnscreen = newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + if(!isNewtChildOnscreen) { + // offscreen childs require AWT event fwd for key/mouse + awtMouseAdapter = new AWTMouseAdapter(newtChild).addTo(this); + awtKeyAdapter = new AWTKeyAdapter(newtChild).addTo(this); + } + } + } + /* package */ void configureNewtChild(boolean attach) { if(null!=awtAdapter) { awtAdapter.removeFrom(this); awtAdapter=null; } + if(null!=awtMouseAdapter) { + awtMouseAdapter.removeFrom(this); + awtMouseAdapter = null; + } + if(null!=awtKeyAdapter) { + awtKeyAdapter.removeFrom(this); + awtKeyAdapter = null; + } + if( null != newtChild ) { if(attach) { awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); @@ -232,21 +291,34 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto newtChild.setFocusAction(null); // no AWT focus traversal .. if(add) { - nativeWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); - if(null!=nativeWindow) { - if(DEBUG) { - System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild); - } - final int w = cont.getWidth(); - final int h = cont.getHeight(); - setSize(w, h); - newtChild.setSize(w, h); - newtChild.reparentWindow(nativeWindow); - newtChild.setVisible(true); - configureNewtChild(true); - newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener - newtChild.windowRepaint(0, 0, w, h); + NewtFactoryAWT.updateGraphicsConfiguration(nativeWindow, this); + if(DEBUG) { + System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild); + } + final int w; + final int h; + if(isPreferredSizeSet()) { + java.awt.Dimension d = getPreferredSize(); + w = d.width; + h = d.height; + } else { + final java.awt.Dimension min; + if(this.isMinimumSizeSet()) { + min = getMinimumSize(); + } else { + min = new java.awt.Dimension(0, 0); + } + java.awt.Insets ins = cont.getInsets(); + w = Math.max(min.width, cont.getWidth() - ins.left - ins.right); + h = Math.max(min.height, cont.getHeight() - ins.top - ins.bottom); } + setSize(w, h); + newtChild.setSize(w, h); + newtChild.reparentWindow(nativeWindow); + newtChild.setVisible(true); + configureNewtChild(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + newtChild.windowRepaint(0, 0, w, h); } else { configureNewtChild(false); nativeWindow = null; @@ -273,7 +345,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont); } configureNewtChild(false); - nativeWindow = null; + nativeWindow.destroy(); + nativeWindow=null; newtChild.setVisible(false); newtChild.reparentWindow(null); newtChild.destroy(); @@ -288,6 +361,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto public void paint(Graphics g) { awtWindowClosingProtocol.addClosingListenerOneShot(); if(null!=newtChild) { + configureNewtChildInputEventHandler(); newtChild.windowRepaint(0, 0, getWidth(), getHeight()); } } @@ -295,18 +369,21 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto public void update(Graphics g) { awtWindowClosingProtocol.addClosingListenerOneShot(); if(null!=newtChild) { + configureNewtChildInputEventHandler(); newtChild.windowRepaint(0, 0, getWidth(), getHeight()); } } - final void requestFocusAWTParent() { + private final void requestFocusAWTParent() { super.requestFocusInWindow(); } - final void requestFocusNEWTChild() { + private final void requestFocusNEWTChild() { if(null!=newtChild) { newtChild.setFocusAction(null); - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + if(isNewtChildOnscreen) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } newtChild.requestFocus(); newtChild.setFocusAction(focusAction); } diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index a7a930691..d6402c6bb 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -85,13 +85,6 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { protected void requestFocusImpl(boolean reparented) { } - @Override - public void setSize(int width, int height) { - if(!isNativeValid()) { - super.setSize(width, height); - } - } - @Override public void setPosition(int x, int y) { // nop diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 919c32f13..823868f2b 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -308,6 +308,30 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return isNativeValid() ; } + private void recreate(boolean skipCreate) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.recreate() START ("+getThreadName()+", "+this+")"); + } + if(!isNativeValid()) { + throw new InternalError("XXX"); + } + ScreenImpl retainedScreen = screen; + retainedScreen.addReference(); // +1 - retain over destroy + destroy(); + setScreen(retainedScreen); + retainedScreen.removeReference(); // -1 - release + if(!skipCreate) { + setVisible(true); // native creation + } + } + + private void setScreen(ScreenImpl newScreen) { // never null ! + removeScreenReference(); + screen = newScreen; + screen.addReference(); + screenReferenceAdded = false; + } + private void removeScreenReference() { if(screenReferenceAdded) { // be nice, probably already called recursive via @@ -821,6 +845,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public void setSize(int width, int height) { + /** FIXME: freezes due to many resize events by eg AWT + if( isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen() ) { + recreate(true); // skip create, create is done here .. + } + */ runOnEDTIfAvail(true, new SetSizeActionImpl(width, height)); } @@ -927,7 +956,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private ReparentActionImpl(NativeWindow newParentWindow, boolean forceDestroyCreate) { this.newParentWindow = newParentWindow; - this.forceDestroyCreate = forceDestroyCreate; + this.forceDestroyCreate = forceDestroyCreate | DEBUG_TEST_REPARENT_INCOMPATIBLE; this.reparentAction = -1; // ensure it's set } @@ -935,13 +964,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return reparentAction; } - private void setScreen(ScreenImpl newScreen) { // never null ! - WindowImpl.this.removeScreenReference(); - screen = newScreen; - screen.addReference(); - screenReferenceAdded = false; - } - public final void run() { boolean animatorPaused = false; if(null!=lifecycleHook) { @@ -973,7 +995,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer long newParentWindowHandle = 0 ; if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE+" "+x+"/"+y+" "+width+"x"+height); + System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", "+x+"/"+y+" "+width+"x"+height); } if(null!=lifecycleHook) { @@ -1024,8 +1046,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } else { reparentAction = ACTION_NATIVE_CREATION_PENDING; } - } else if ( DEBUG_TEST_REPARENT_INCOMPATIBLE || forceDestroyCreate || - !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) { + } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) { // Destroy this window, may create a new compatible Screen/Display, // and mark it for creation. destroy(); @@ -1056,7 +1077,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( 0 == parentWindowHandle ) { // Already Top Window reparentAction = ACTION_UNCHANGED; - } else if( !isNativeValid() || DEBUG_TEST_REPARENT_INCOMPATIBLE || forceDestroyCreate ) { + } else if( !isNativeValid() || forceDestroyCreate ) { // Destroy this window and mark it for [pending] creation. destroy(); if( 0 "+awtNative); } return awtNative; } + + public static void updateGraphicsConfiguration(NativeWindow nw, java.awt.Component awtComp) { + if(! ( nw instanceof JAWTWindow ) ) { + throw new NativeWindowException("Not an AWT NativeWindow: "+nw); + } + final AWTGraphicsConfiguration awtConfig = (AWTGraphicsConfiguration) nw.getGraphicsConfiguration(); + awtConfig.updateGraphicsConfiguration(awtComp); + if(DEBUG_IMPLEMENTATION) { + System.err.println("NewtFactoryAWT.updateGraphicsConfiguration: "+awtComp+" -> "+nw); + } + } + } -- cgit v1.2.3