Input: Override touchable region bounds with surface bounds 1/2
Take advantage of the surface flinger layer hierarchy to set touchable region. - Let a client set a surface touchable region to its own bounds. - Let a client set a surface touchable region to another surface bounds. - Let a client bound its touchable region to a surface. Test: go/wm-smoke Test: existing tests Change-Id: Id5ef8b35f4779861c1537811a045a44ee2394fdf
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user