aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-04-03 18:35:19 +0200
committerSven Gothel <[email protected]>2012-04-03 18:35:19 +0200
commitc9066a6df7a0b8612a8a0b3e5c8977268a1257e8 (patch)
tree21ddd6bdab7d8af6cd5aa9c4e732e53b9d990eb9
parent3c5a509ef1e6be2ae7542901e6fbe5a0035fb3f7 (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.java101
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java162
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()) {