summaryrefslogtreecommitdiff
path: root/android/android_studio_project/app/src/main/java
diff options
context:
space:
mode:
authorTriang3l <triang3l@yandex.ru>2022-02-01 22:18:04 +0300
committerTriang3l <triang3l@yandex.ru>2022-02-01 22:18:04 +0300
commit413d7ded490e1244311993d8e8546a753473c044 (patch)
treefc70a9ddd974114238dfdd741e7a7ed7c2e3632e /android/android_studio_project/app/src/main/java
parentc6fc8f706a122a597787c5c35eaa5c69cfa26b67 (diff)
[UI] Android surface [skip appveyor]
Diffstat (limited to 'android/android_studio_project/app/src/main/java')
-rw-r--r--android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java6
-rw-r--r--android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java10
-rw-r--r--android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java42
-rw-r--r--android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java123
4 files changed, 174 insertions, 7 deletions
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java b/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java
index 93a046dfb..e5d324e78 100644
--- a/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java
+++ b/android/android_studio_project/app/src/main/java/jp/xenia/XeniaRuntimeException.java
@@ -7,15 +7,15 @@ public class XeniaRuntimeException extends RuntimeException {
public XeniaRuntimeException() {
}
- public XeniaRuntimeException(String name) {
+ public XeniaRuntimeException(final String name) {
super(name);
}
- public XeniaRuntimeException(String name, Throwable cause) {
+ public XeniaRuntimeException(final String name, final Throwable cause) {
super(name, cause);
}
- public XeniaRuntimeException(Exception cause) {
+ public XeniaRuntimeException(final Exception cause) {
super(cause);
}
}
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java
index a0dd36f0e..d03a07788 100644
--- a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java
+++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowDemoActivity.java
@@ -1,8 +1,18 @@
package jp.xenia.emulator;
+import android.os.Bundle;
+
public class WindowDemoActivity extends WindowedAppActivity {
@Override
protected String getWindowedAppIdentifier() {
return "xenia_ui_window_vulkan_demo";
}
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.activity_window_demo);
+ setWindowSurfaceView(findViewById(R.id.window_demo_surface_view));
+ }
}
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java
new file mode 100644
index 000000000..23b014632
--- /dev/null
+++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowSurfaceView.java
@@ -0,0 +1,42 @@
+package jp.xenia.emulator;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.SurfaceView;
+
+public class WindowSurfaceView extends SurfaceView {
+ public WindowSurfaceView(final Context context) {
+ super(context);
+ // Native drawing is invoked from onDraw.
+ setWillNotDraw(false);
+ }
+
+ public WindowSurfaceView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ setWillNotDraw(false);
+ }
+
+ public WindowSurfaceView(
+ final Context context, final AttributeSet attrs, final int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setWillNotDraw(false);
+ }
+
+ public WindowSurfaceView(
+ final Context context, final AttributeSet attrs, final int defStyleAttr,
+ final int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setWillNotDraw(false);
+ }
+
+ @Override
+ protected void onDraw(final Canvas canvas) {
+ final Context context = getContext();
+ if (!(context instanceof WindowedAppActivity)) {
+ return;
+ }
+ final WindowedAppActivity activity = (WindowedAppActivity) context;
+ activity.onWindowSurfaceDraw(false);
+ }
+}
diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java
index 9deb60358..073283529 100644
--- a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java
+++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java
@@ -3,6 +3,11 @@ package jp.xenia.emulator;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.View;
+
+import org.jetbrains.annotations.Nullable;
import jp.xenia.XeniaRuntimeException;
@@ -12,21 +17,87 @@ public abstract class WindowedAppActivity extends Activity {
System.loadLibrary("xenia-ui-window-vulkan-demo");
}
- private long mAppContext;
+ private final WindowSurfaceOnLayoutChangeListener mWindowSurfaceOnLayoutChangeListener =
+ new WindowSurfaceOnLayoutChangeListener();
+ private final WindowSurfaceHolderCallback mWindowSurfaceHolderCallback =
+ new WindowSurfaceHolderCallback();
+
+ // May be 0 while destroying (mainly while the superclass is).
+ private long mAppContext = 0;
+
+ @Nullable
+ private WindowSurfaceView mWindowSurfaceView = null;
- private native long initializeWindowedAppOnCreateNative(
+ private native long initializeWindowedAppOnCreate(
String windowedAppIdentifier, AssetManager assetManager);
private native void onDestroyNative(long appContext);
+ private native void onWindowSurfaceLayoutChange(
+ long appContext, int left, int top, int right, int bottom);
+
+ private native void onWindowSurfaceChanged(long appContext, Surface windowSurface);
+
+ private native void paintWindow(long appContext, boolean forcePaint);
+
protected abstract String getWindowedAppIdentifier();
+ protected void setWindowSurfaceView(@Nullable final WindowSurfaceView windowSurfaceView) {
+ if (mWindowSurfaceView == windowSurfaceView) {
+ return;
+ }
+
+ // Detach from the old surface.
+ if (mWindowSurfaceView != null) {
+ mWindowSurfaceView.getHolder().removeCallback(mWindowSurfaceHolderCallback);
+ mWindowSurfaceView.removeOnLayoutChangeListener(mWindowSurfaceOnLayoutChangeListener);
+ mWindowSurfaceView = null;
+ if (mAppContext != 0) {
+ onWindowSurfaceChanged(mAppContext, null);
+ }
+ }
+
+ if (windowSurfaceView == null) {
+ return;
+ }
+
+ mWindowSurfaceView = windowSurfaceView;
+ // The native window code assumes that, when the surface exists, it covers the entire
+ // window.
+ // FIXME(Triang3l): This doesn't work if the layout has already been performed.
+ mWindowSurfaceView.addOnLayoutChangeListener(mWindowSurfaceOnLayoutChangeListener);
+ final SurfaceHolder windowSurfaceHolder = mWindowSurfaceView.getHolder();
+ windowSurfaceHolder.addCallback(mWindowSurfaceHolderCallback);
+ // If setting after the creation of the surface.
+ if (mAppContext != 0) {
+ final Surface windowSurface = windowSurfaceHolder.getSurface();
+ if (windowSurface != null) {
+ onWindowSurfaceChanged(mAppContext, windowSurface);
+ }
+ }
+ }
+
+ public void onWindowSurfaceDraw(final boolean forcePaint) {
+ if (mAppContext == 0) {
+ return;
+ }
+ paintWindow(mAppContext, forcePaint);
+ }
+
+ // Used from the native WindowedAppContext. May be called from non-UI threads.
+ protected void postInvalidateWindowSurface() {
+ if (mWindowSurfaceView == null) {
+ return;
+ }
+ mWindowSurfaceView.postInvalidate();
+ }
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String windowedAppIdentifier = getWindowedAppIdentifier();
- mAppContext = initializeWindowedAppOnCreateNative(windowedAppIdentifier, getAssets());
+ mAppContext = initializeWindowedAppOnCreate(windowedAppIdentifier, getAssets());
if (mAppContext == 0) {
finish();
throw new XeniaRuntimeException(
@@ -36,10 +107,54 @@ public abstract class WindowedAppActivity extends Activity {
@Override
protected void onDestroy() {
+ setWindowSurfaceView(null);
if (mAppContext != 0) {
onDestroyNative(mAppContext);
}
mAppContext = 0;
super.onDestroy();
}
+
+ private class WindowSurfaceOnLayoutChangeListener implements View.OnLayoutChangeListener {
+ @Override
+ public void onLayoutChange(
+ final View v, final int left, final int top, final int right, final int bottom,
+ final int oldLeft, final int oldTop, final int oldRight, final int oldBottom) {
+ if (mAppContext != 0) {
+ onWindowSurfaceLayoutChange(mAppContext, left, top, right, bottom);
+ }
+ }
+ }
+
+ private class WindowSurfaceHolderCallback implements SurfaceHolder.Callback2 {
+ @Override
+ public void surfaceCreated(final SurfaceHolder holder) {
+ if (mAppContext == 0) {
+ return;
+ }
+ onWindowSurfaceChanged(mAppContext, holder.getSurface());
+ }
+
+ @Override
+ public void surfaceChanged(
+ final SurfaceHolder holder, final int format, final int width, final int height) {
+ if (mAppContext == 0) {
+ return;
+ }
+ onWindowSurfaceChanged(mAppContext, holder.getSurface());
+ }
+
+ @Override
+ public void surfaceDestroyed(final SurfaceHolder holder) {
+ if (mAppContext == 0) {
+ return;
+ }
+ onWindowSurfaceChanged(mAppContext, null);
+ }
+
+ @Override
+ public void surfaceRedrawNeeded(final SurfaceHolder holder) {
+ onWindowSurfaceDraw(true);
+ }
+ }
}