diff options
-rw-r--r-- | core/java/android/view/InputWindowHandle.java | 43 | ||||
-rw-r--r-- | core/jni/android_hardware_input_InputWindowHandle.cpp | 42 |
2 files changed, 84 insertions, 1 deletions
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java index ec79eea45ee6..16a6412684d1 100644 --- a/core/java/android/view/InputWindowHandle.java +++ b/core/java/android/view/InputWindowHandle.java @@ -18,9 +18,12 @@ package android.view; import static android.view.Display.INVALID_DISPLAY; +import android.annotation.Nullable; import android.graphics.Region; import android.os.IBinder; +import java.lang.ref.WeakReference; + /** * Functions as a handle for a window that can receive input. * Enables the native input dispatcher to refer indirectly to the window manager's window state. @@ -38,7 +41,7 @@ public final class InputWindowHandle { // The client window. public final IWindow clientWindow; - // The token assosciated with the window. + // The token associated with the window. public IBinder token; // The window name. @@ -98,6 +101,23 @@ public final class InputWindowHandle { // transports the touch of this window to the display indicated by portalToDisplayId. public int portalToDisplayId = INVALID_DISPLAY; + /** + * Crops the touchable region to the bounds of the surface provided. + * + * This can be used in cases where the window is not + * {@link android.view.WindowManager#FLAG_NOT_TOUCH_MODAL} but should be constrained to the + * bounds of a parent window. That is the window should receive touch events outside its + * window but be limited to its stack bounds, such as in the case of split screen. + */ + public WeakReference<IBinder> touchableRegionCropHandle = new WeakReference<>(null); + + /** + * Replace {@link touchableRegion} with the bounds of {@link touchableRegionCropHandle}. If + * the handle is {@code null}, the bounds of the surface associated with this window is used + * as the touchable region. + */ + public boolean replaceTouchableRegionWithCrop; + private native void nativeDispose(); public InputWindowHandle(InputApplicationHandle inputApplicationHandle, @@ -127,4 +147,25 @@ public final class InputWindowHandle { super.finalize(); } } + + /** + * Set the window touchable region to the bounds of {@link touchableRegionBounds} ignoring any + * touchable region provided. + * + * @param bounds surface to set the touchable region to. Set to {@code null} to set the bounds + * to the current surface. + */ + public void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) { + setTouchableRegionCrop(bounds); + replaceTouchableRegionWithCrop = true; + } + + /** + * Crop the window touchable region to the bounds of the surface provided. + */ + public void setTouchableRegionCrop(@Nullable SurfaceControl bounds) { + if (bounds != null) { + touchableRegionCropHandle = new WeakReference<>(bounds.getHandle()); + } + } } diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index eb710526895e..a1d1d4f0733d 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -31,6 +31,11 @@ namespace android { +struct WeakRefHandleField { + jfieldID handle; + jmethodID get; +}; + static struct { jfieldID ptr; jfieldID inputApplicationHandle; @@ -57,6 +62,8 @@ static struct { jfieldID inputFeatures; jfieldID displayId; jfieldID portalToDisplayId; + jfieldID replaceTouchableRegionWithCrop; + WeakRefHandleField touchableRegionCropHandle; } gInputWindowHandleClassInfo; static Mutex gHandleMutex; @@ -90,6 +97,7 @@ bool NativeInputWindowHandle::updateInfo() { jobject tokenObj = env->GetObjectField(obj, gInputWindowHandleClassInfo.token); if (tokenObj) { mInfo.token = ibinderForJavaObject(env, tokenObj); + env->DeleteLocalRef(tokenObj); } else { mInfo.token.clear(); } @@ -161,6 +169,24 @@ bool NativeInputWindowHandle::updateInfo() { env->DeleteLocalRef(inputApplicationHandleObj); } + mInfo.replaceTouchableRegionWithCrop = env->GetBooleanField(obj, + gInputWindowHandleClassInfo.replaceTouchableRegionWithCrop); + + jobject handleObj = env->GetObjectField(obj, + gInputWindowHandleClassInfo.touchableRegionCropHandle.handle); + if (handleObj) { + // Promote java weak reference. + jobject strongHandleObj = env->CallObjectMethod(handleObj, + gInputWindowHandleClassInfo.touchableRegionCropHandle.get); + if (strongHandleObj) { + mInfo.touchableRegionCropHandle = ibinderForJavaObject(env, strongHandleObj); + env->DeleteLocalRef(strongHandleObj); + } else { + mInfo.touchableRegionCropHandle.clear(); + } + env->DeleteLocalRef(handleObj); + } + env->DeleteLocalRef(obj); return true; } @@ -220,6 +246,10 @@ static const JNINativeMethod gInputWindowHandleMethods[] = { var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(! (var), "Unable to find field " fieldName); +#define GET_METHOD_ID(var, clazz, methodName, methodSignature) \ + var = env->GetMethodID(clazz, methodName, methodSignature); \ + LOG_FATAL_IF(! (var), "Unable to find method " methodName); + int register_android_view_InputWindowHandle(JNIEnv* env) { int res = jniRegisterNativeMethods(env, "android/view/InputWindowHandle", gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods)); @@ -303,6 +333,18 @@ int register_android_view_InputWindowHandle(JNIEnv* env) { GET_FIELD_ID(gInputWindowHandleClassInfo.portalToDisplayId, clazz, "portalToDisplayId", "I"); + + GET_FIELD_ID(gInputWindowHandleClassInfo.replaceTouchableRegionWithCrop, clazz, + "replaceTouchableRegionWithCrop", "Z"); + + jclass weakRefClazz; + FIND_CLASS(weakRefClazz, "java/lang/ref/Reference"); + + GET_METHOD_ID(gInputWindowHandleClassInfo.touchableRegionCropHandle.get, weakRefClazz, + "get", "()Ljava/lang/Object;") + + GET_FIELD_ID(gInputWindowHandleClassInfo.touchableRegionCropHandle.handle, clazz, + "touchableRegionCropHandle", "Ljava/lang/ref/WeakReference;"); return 0; } |