diff options
| author | Triang3l <triang3l@yandex.ru> | 2022-02-01 22:18:04 +0300 |
|---|---|---|
| committer | Triang3l <triang3l@yandex.ru> | 2022-02-01 22:18:04 +0300 |
| commit | 413d7ded490e1244311993d8e8546a753473c044 (patch) | |
| tree | fc70a9ddd974114238dfdd741e7a7ed7c2e3632e /android/android_studio_project/app/src/main/java | |
| parent | c6fc8f706a122a597787c5c35eaa5c69cfa26b67 (diff) | |
[UI] Android surface [skip appveyor]
Diffstat (limited to 'android/android_studio_project/app/src/main/java')
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); + } + } } |
