diff options
author | Sven Gothel <[email protected]> | 2012-04-03 18:35:19 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2012-04-03 18:35:19 +0200 |
commit | c9066a6df7a0b8612a8a0b3e5c8977268a1257e8 (patch) | |
tree | 21ddd6bdab7d8af6cd5aa9c4e732e53b9d990eb9 | |
parent | 3c5a509ef1e6be2ae7542901e6fbe5a0035fb3f7 (diff) |
AndroidWindow/NewtBaseActivity: Properly split functionality, remove android.view.Window reference and use from AndroidWindow; Force transparency flag; Multiple NEWT Windows in Activity.
AndroidWindow:
- Force transparency flag to EGL Capabilities chooser (see commit 0d12af05128da433aa7b6767ba5a7f6ee9bce6c4)
- Keep androidFormat besides nativeFormat, used to determine transparency flag and recreation.
- Move transparency style selection from AndroidWindow.instantiationFinished() -> NewtBaseActivity.setContentView(..)
- Remove AndroidWindow.becomeContentViewOf(..) and add it's fullscreen layout features to NewtBaseActivity.setContentView(..)
NewtBaseActivity:
- General support for multiple NEWT windows.
- Adding functionality removed from AndroidWindow - see above
- Adding 'addContentView(..)' and 'registerNEWTWindow(..)' which, besides 'setContentView(..)'
performs registration of the NEWT window for the 'onDestroy()' method.
The 'add*' and 'set*' variant also handle layout etc.
- Add direct methods to set fullscreen feature and transparency theme.
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java | 101 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java | 162 |
2 files changed, 182 insertions, 81 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java index e747b9ea7..8d1b21db1 100644 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java +++ b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java @@ -61,8 +61,6 @@ import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback2; import android.view.SurfaceView; import android.view.View; -import android.view.Window; -import android.view.WindowManager; public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { private static final String[] androidWindowImplClassNames = { "android.policy.PhoneWindow", "com.android.internal.policy.impl.PhoneWindow" }; @@ -158,6 +156,15 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { return fmt; } + public static boolean isAndroidFormatTransparent(int aFormat) { + switch (aFormat) { + case PixelFormat.TRANSLUCENT: + case PixelFormat.TRANSPARENT: + return true; + } + return false; + } + class AndroidEvents implements /* View.OnKeyListener, */ View.OnTouchListener, View.OnFocusChangeListener { public boolean onTouch(View v, MotionEvent event) { @@ -193,20 +200,16 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { reset(); } - public AndroidWindow(android.view.Window awin) { - reset(); - androidWindow = awin; - } - private void reset() { - androidWindow = null; ownAndroidWindow = false; androidView = null; - format = VisualIDHolder.VID_UNDEFINED; + nativeFormat = VisualIDHolder.VID_UNDEFINED; + androidFormat = VisualIDHolder.VID_UNDEFINED; capsByFormat = null; surface = null; surfaceHandle = 0; - eglSurface = 0; + eglSurface = 0; + definePosition(0, 0); // default to 0/0 } @Override @@ -215,17 +218,6 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { if(null == ctx) { throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first."); } - if(!getRequestedCapabilities().isBackgroundOpaque()) { - // FIXME: doesn't work, even though resource is avail, happens before creating the view and setContentView() ! - final String frn = ctx.getPackageName()+":style/Theme.Transparent"; - final int resID = ctx.getResources().getIdentifier("Theme.Transparent", "style", ctx.getPackageName()); - if(0 == resID) { - Log.d(MD.TAG, "Resource n/a: "+frn); - } else { - Log.d(MD.TAG, "Setting style: "+frn+": 0x"+Integer.toHexString(resID)); - ctx.setTheme(resID); - } - } androidView = new MSurfaceView(ctx); final AndroidEvents ae = new AndroidEvents(); androidView.setOnTouchListener(ae); @@ -252,47 +244,8 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { public SurfaceView getAndroidView() { return androidView; } - public void becomeContentViewOf(android.view.Window window) { - if(null != androidWindow) { - throw new NativeWindowException("Android Window already set"); - } - androidWindow = window; - ownAndroidWindow = null == androidWindow; - if(ownAndroidWindow) { - if(null == androidWindowImplCtor) { - throw new NativeWindowException("Android Window contructor n/a"); - } - try { - androidWindow = (android.view.Window) androidWindowImplCtor.newInstance(new Object[]{StaticContext.getContext()}); - } catch (Exception e) { - throw new NativeWindowException("Error while instantiating new Android Window", e); - } - } - Log.d(MD.TAG, "setAndroidWindow: own: "+ownAndroidWindow+", "+androidWindow+", "+getWidth()+"x"+getHeight()); - - if( isFullscreen() || isUndecorated() ) { - androidWindow.requestFeature(Window.FEATURE_NO_TITLE); - } - if( isFullscreen() ) { - androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - } else { - androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - if(getWidth()>0 && getHeight()>0 && !isFullscreen()) { - androidWindow.setLayout(getWidth(), getHeight()); - } - androidWindow.setContentView(androidView); - } - public android.view.Window getAndroidWindow() { return androidWindow; } - @Override protected boolean canCreateNativeImpl() { - if(null == androidWindow) { - becomeContentViewOf(null); // make own window - } final boolean b = 0 != surfaceHandle; Log.d(MD.TAG, "canCreateNativeImpl: "+b); return b; @@ -301,7 +254,9 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { @Override protected void createNativeImpl() { Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ - ", format "+format+", "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName()); + ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName()); + androidView.bringToFront(); + if(0!=getParentWindowHandle()) { throw new NativeWindowException("Window parenting not supported (yet)"); } @@ -312,7 +267,8 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice(); final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(), - (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), format); + (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat, + isAndroidFormatTransparent(androidFormat)); if (eglConfig == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } @@ -349,6 +305,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { protected void requestFocusImpl(boolean reparented) { if(null != androidView) { + androidView.bringToFront(); androidView.requestFocus(); } } @@ -391,8 +348,8 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { } public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) { - Log.d(MD.TAG, "surfaceChanged: f "+format+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)); - if(0!=surfaceHandle && format != aFormat) { + Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)); + if(0!=surfaceHandle && ( androidFormat != aFormat || getWidth()!=aWidth || getHeight()!=aHeight) ) { // re-create Log.d(MD.TAG, "surfaceChanged (destroy old)"); windowDestroyNotify(); @@ -411,23 +368,19 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { } if(0 == surfaceHandle) { + androidFormat = aFormat; surface = aHolder.getSurface(); surfaceHandle = getSurfaceHandle0(surface); acquire0(surfaceHandle); - final int nFormat = getSurfaceVisualID0(surfaceHandle); - if(PixelFormat.UNKNOWN == aFormat || 0 >= aFormat) { - format = nFormat; - } else { - format = aFormat; - } + nativeFormat = getSurfaceVisualID0(surfaceHandle); final int nWidth = getWidth0(surfaceHandle); final int nHeight = getHeight0(surfaceHandle); - capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, format, getRequestedCapabilities()); + capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities()); sizeChanged(false, nWidth, nHeight, false); Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+ ", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ - ", format: "+format+"(a "+aFormat+"/n "+nFormat+"), "+ + ", format [a "+androidFormat+"/n "+nativeFormat+"], "+ getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); if(isVisible()) { @@ -450,10 +403,10 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { windowRepaint(0, 0, getWidth(), getHeight()); } - private android.view.Window androidWindow; private boolean ownAndroidWindow; private MSurfaceView androidView; - private int format; // stored current PixelFormat + private int nativeFormat; // chosen current native PixelFormat (suitable for EGL) + private int androidFormat; // chosen current android PixelFormat (-1, -2 ..) private GLCapabilitiesImmutable capsByFormat; // fixed requestedCaps by PixelFormat private Surface surface; private volatile long surfaceHandle; diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java index dc14ca347..c7918d38d 100644 --- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java +++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java @@ -27,22 +27,30 @@ */ package jogamp.newt.driver.android; +import java.util.ArrayList; +import java.util.List; + +import javax.media.nativewindow.CapabilitiesImmutable; + import com.jogamp.newt.Window; import com.jogamp.opengl.util.Animator; import jogamp.newt.driver.android.AndroidWindow; import android.app.Activity; +import android.content.Context; import android.os.Bundle; import android.util.Log; +import android.view.WindowManager; public class NewtBaseActivity extends Activity { - AndroidWindow newtWindow = null; + List<Window> newtWindows = new ArrayList<Window>(); Animator animator = null; boolean isDelegatedActivity; Activity rootActivity; - + boolean setThemeCalled = false; + public NewtBaseActivity() { super(); isDelegatedActivity = false; @@ -62,13 +70,153 @@ public class NewtBaseActivity extends Activity { return rootActivity; } + /** + * This is one of the three registration methods (see below). + * <p> + * This methods issues {@link android.view.Window#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) androidWindow.setContenView(newtWindow.getAndroidView())} + * and finally calls {@link #registerNEWTWindow(Window)}. + * </p> + * @param androidWindow + * @param newtWindow + * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams) + */ public void setContentView(android.view.Window androidWindow, Window newtWindow) { newtWindow = newtWindow.getDelegatedWindow(); if(newtWindow instanceof AndroidWindow) { - this.newtWindow = (AndroidWindow)newtWindow; - this.newtWindow.becomeContentViewOf(androidWindow); + adaptTheme4Transparency(newtWindow.getRequestedCapabilities()); + layoutForNEWTWindow(androidWindow, newtWindow); + AndroidWindow newtAWindow = (AndroidWindow)newtWindow; + androidWindow.setContentView(newtAWindow.getAndroidView()); + registerNEWTWindow(newtAWindow); + } else { + throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass()); + } + } + /** + * This is one of the three registration methods (see below). + * <p> + * This methods issues {@link android.view.Window#addContentView(android.view.View, android.view.ViewGroup.LayoutParams) androidWindow.addContenView(newtWindow.getAndroidView(), params)} + * and finally calls {@link #registerNEWTWindow(Window)}. + * </p> + * @param androidWindow + * @param newtWindow + * @param params + * @see #setContentView(android.view.Window, Window) + * @see #registerNEWTWindow(Window) + */ + public void addContentView(android.view.Window androidWindow, Window newtWindow, android.view.ViewGroup.LayoutParams params) { + newtWindow = newtWindow.getDelegatedWindow(); + if(newtWindow instanceof AndroidWindow) { + AndroidWindow newtAWindow = (AndroidWindow)newtWindow; + androidWindow.addContentView(newtAWindow.getAndroidView(), params); + registerNEWTWindow(newtAWindow); } else { throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass()); + } + } + /** + * This is one of the three registration methods (see below). + * <p> + * This methods simply registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}. + * </p> + * + * @param newtWindow + * @see #setContentView(android.view.Window, Window) + * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams) + */ + public void registerNEWTWindow(Window newtWindow) { + newtWindows.add(newtWindow); + } + + /** + * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window. + * <p> + * Must be called before creating the view and adding any content, i.e. setContentView() ! + * </p> + * @param androidWindow + * @param newtWindow + */ + public void layoutForNEWTWindow(android.view.Window androidWindow, Window newtWindow) { + if(null == androidWindow || null == newtWindow) { + throw new IllegalArgumentException("Android or NEWT Window null"); + } + + if( newtWindow.isFullscreen() || newtWindow.isUndecorated() ) { + androidWindow.requestFeature(android.view.Window.FEATURE_NO_TITLE); + } + if( newtWindow.isFullscreen() ) { + androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } else { + androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + if(newtWindow.getWidth()>0 && newtWindow.getHeight()>0 && !newtWindow.isFullscreen()) { + androidWindow.setLayout(newtWindow.getWidth(), newtWindow.getHeight()); + } + } + + /** + * Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window. + * <p> + * Must be called before creating the view and adding any content, i.e. setContentView() ! + * </p> + * @param androidWindow + * @param newtWindow + */ + public void setFullscreenFeature(android.view.Window androidWindow, boolean fullscreen) { + if(null == androidWindow) { + throw new IllegalArgumentException("Android or Window null"); + } + + if( fullscreen ) { + androidWindow.requestFeature(android.view.Window.FEATURE_NO_TITLE); + androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } else { + androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + } + + /** + * Convenient method to set this context's theme to transparency depending on {@link CapabilitiesImmutable#isBackgroundOpaque()}. + * <p> + * Must be called before creating the view and adding any content, i.e. setContentView() ! + * </p> + */ + protected void adaptTheme4Transparency(CapabilitiesImmutable caps) { + if(!caps.isBackgroundOpaque()) { + setTransparencyTheme(); + } + } + + /** + * Convenient method to set this context's theme to transparency. + * <p> + * Must be called before creating the view and adding any content, i.e. setContentView() ! + * </p> + * <p> + * Is normally issued by {@link #setContentView(android.view.Window, Window)} + * if the requested NEWT Capabilities ask for transparency. + * </p> + * <p> + * Can be called only once. + * </p> + */ + public void setTransparencyTheme() { + if(!setThemeCalled) { + setThemeCalled = true; + final Context ctx = getActivity().getApplicationContext(); + final String frn = ctx.getPackageName()+":style/Theme.Transparent"; + final int resID = ctx.getResources().getIdentifier("Theme.Transparent", "style", ctx.getPackageName()); + if(0 == resID) { + Log.d(MD.TAG, "SetTransparencyTheme: Resource n/a: "+frn); + } else { + Log.d(MD.TAG, "SetTransparencyTheme: Setting style: "+frn+": 0x"+Integer.toHexString(resID)); + ctx.setTheme(resID); + } } } @@ -147,9 +295,9 @@ public class NewtBaseActivity extends Activity { animator.stop(); animator = null; } - if(null != newtWindow) { - newtWindow.destroy(); - newtWindow = null; + while(newtWindows.size()>0) { + final Window win = newtWindows.remove(newtWindows.size()-1); + win.destroy(); } jogamp.common.os.android.StaticContext.clear(); if(!isDelegatedActivity()) { |