diff options
author | Jeff Brown <jeffbrown@google.com> | 2011-01-16 14:06:57 -0800 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2011-01-16 18:58:49 -0800 |
commit | fbf097732137a32930d151f7ba6816a5b870c32a (patch) | |
tree | 1f05823ea1cb06aaa3ab0954cdde614b370f30e6 /core | |
parent | 115ad16551c9cf9551f44cbea59f3edf83e4a340 (diff) | |
download | frameworks_base-fbf097732137a32930d151f7ba6816a5b870c32a.zip frameworks_base-fbf097732137a32930d151f7ba6816a5b870c32a.tar.gz frameworks_base-fbf097732137a32930d151f7ba6816a5b870c32a.tar.bz2 |
Support non-rectangular input regions.
This enables the system bar to carve out a region through which
events will be sent to the IME behind it.
Bug: 3238092
Change-Id: I69b855a8d9b5b3ee525266c0861826e53e5b5028
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/content/res/CompatibilityInfo.java | 16 | ||||
-rw-r--r-- | core/java/android/inputmethodservice/InputMethodService.java | 28 | ||||
-rw-r--r-- | core/java/android/view/IWindowSession.aidl | 2 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 36 | ||||
-rw-r--r-- | core/java/android/view/ViewTreeObserver.java | 36 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
-rw-r--r-- | core/jni/android/graphics/Region.cpp | 33 | ||||
-rw-r--r-- | core/jni/android/graphics/Region.h | 30 |
8 files changed, 147 insertions, 36 deletions
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index 406b091..6baf1c2 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -283,6 +283,7 @@ public class CompatibilityInfo { private Rect mContentInsetsBuffer = null; private Rect mVisibleInsetsBuffer = null; + private Region mTouchableAreaBuffer = null; Translator(float applicationScale, float applicationInvertedScale) { this.applicationScale = applicationScale; @@ -395,14 +396,25 @@ public class CompatibilityInfo { /** * Translate the visible insets in application window to Screen. This uses - * the internal buffer for content insets to avoid extra object allocation. + * the internal buffer for visible insets to avoid extra object allocation. */ - public Rect getTranslatedVisbileInsets(Rect visibleInsets) { + public Rect getTranslatedVisibleInsets(Rect visibleInsets) { if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect(); mVisibleInsetsBuffer.set(visibleInsets); translateRectInAppWindowToScreen(mVisibleInsetsBuffer); return mVisibleInsetsBuffer; } + + /** + * Translate the touchable area in application window to Screen. This uses + * the internal buffer for touchable area to avoid extra object allocation. + */ + public Region getTranslatedTouchableArea(Region touchableArea) { + if (mTouchableAreaBuffer == null) mTouchableAreaBuffer = new Region(); + mTouchableAreaBuffer.set(touchableArea); + mTouchableAreaBuffer.scale(applicationScale); + return mTouchableAreaBuffer; + } } /** diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 23b9ad5..4d25bac 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -25,6 +25,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Rect; +import android.graphics.Region; import android.os.Bundle; import android.os.IBinder; import android.os.ResultReceiver; @@ -283,11 +284,13 @@ public class InputMethodService extends AbstractInputMethodService { View decor = getWindow().getWindow().getDecorView(); info.contentInsets.top = info.visibleInsets.top = decor.getHeight(); + info.touchableRegion.setEmpty(); info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); } else { onComputeInsets(mTmpInsets); info.contentInsets.top = mTmpInsets.contentTopInsets; info.visibleInsets.top = mTmpInsets.visibleTopInsets; + info.touchableRegion.set(mTmpInsets.touchableRegion); info.setTouchableInsets(mTmpInsets.touchableInsets); } } @@ -510,7 +513,14 @@ public class InputMethodService extends AbstractInputMethodService { * of the input method window. */ public int visibleTopInsets; - + + /** + * This is the region of the UI that is touchable. It is used when + * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}. + * The region should be specified relative to the origin of the window frame. + */ + public final Region touchableRegion = new Region(); + /** * Option for {@link #touchableInsets}: the entire window frame * can be touched. @@ -531,11 +541,19 @@ public class InputMethodService extends AbstractInputMethodService { */ public static final int TOUCHABLE_INSETS_VISIBLE = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; - + + /** + * Option for {@link #touchableInsets}: the region specified by + * {@link #touchableRegion} can be touched. + */ + public static final int TOUCHABLE_INSETS_REGION + = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; + /** * Determine which area of the window is touchable by the user. May * be one of: {@link #TOUCHABLE_INSETS_FRAME}, - * {@link #TOUCHABLE_INSETS_CONTENT}, or {@link #TOUCHABLE_INSETS_VISIBLE}. + * {@link #TOUCHABLE_INSETS_CONTENT}, {@link #TOUCHABLE_INSETS_VISIBLE}, + * or {@link #TOUCHABLE_INSETS_REGION}. */ public int touchableInsets; } @@ -950,6 +968,7 @@ public class InputMethodService extends AbstractInputMethodService { } outInsets.visibleTopInsets = loc[1]; outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE; + outInsets.touchableRegion.setEmpty(); } /** @@ -2153,6 +2172,7 @@ public class InputMethodService extends AbstractInputMethodService { p.println("Last computed insets:"); p.println(" contentTopInsets=" + mTmpInsets.contentTopInsets + " visibleTopInsets=" + mTmpInsets.visibleTopInsets - + " touchableInsets=" + mTmpInsets.touchableInsets); + + " touchableInsets=" + mTmpInsets.touchableInsets + + " touchableRegion=" + mTmpInsets.touchableRegion); } } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index a5f405a..1218e81 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -101,7 +101,7 @@ interface IWindowSession { * {@link android.view.ViewTreeObserver.InternalInsetsInfo}. */ void setInsets(IWindow window, int touchableInsets, in Rect contentInsets, - in Rect visibleInsets); + in Rect visibleInsets, in Region touchableRegion); /** * Return the current display size in which the window is being laid out, diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index ad9e6863..b7ab3c1 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1229,24 +1229,34 @@ public final class ViewRoot extends Handler implements ViewParent, } if (computesInternalInsets) { - ViewTreeObserver.InternalInsetsInfo insets = attachInfo.mGivenInternalInsets; - final Rect givenContent = attachInfo.mGivenInternalInsets.contentInsets; - final Rect givenVisible = attachInfo.mGivenInternalInsets.visibleInsets; - givenContent.left = givenContent.top = givenContent.right - = givenContent.bottom = givenVisible.left = givenVisible.top - = givenVisible.right = givenVisible.bottom = 0; + // Clear the original insets. + final ViewTreeObserver.InternalInsetsInfo insets = attachInfo.mGivenInternalInsets; + insets.reset(); + + // Compute new insets in place. attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets); - Rect contentInsets = insets.contentInsets; - Rect visibleInsets = insets.visibleInsets; - if (mTranslator != null) { - contentInsets = mTranslator.getTranslatedContentInsets(contentInsets); - visibleInsets = mTranslator.getTranslatedVisbileInsets(visibleInsets); - } + + // Tell the window manager. if (insetsPending || !mLastGivenInsets.equals(insets)) { mLastGivenInsets.set(insets); + + // Translate insets to screen coordinates if needed. + final Rect contentInsets; + final Rect visibleInsets; + final Region touchableRegion; + if (mTranslator != null) { + contentInsets = mTranslator.getTranslatedContentInsets(insets.contentInsets); + visibleInsets = mTranslator.getTranslatedVisibleInsets(insets.visibleInsets); + touchableRegion = mTranslator.getTranslatedTouchableArea(insets.touchableRegion); + } else { + contentInsets = insets.contentInsets; + visibleInsets = insets.visibleInsets; + touchableRegion = insets.touchableRegion; + } + try { sWindowSession.setInsets(mWindow, insets.mTouchableInsets, - contentInsets, visibleInsets); + contentInsets, visibleInsets, touchableRegion); } catch (RemoteException e) { } } diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 06a0fa6..db87175 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Rect; +import android.graphics.Region; import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList; @@ -126,11 +127,18 @@ public final class ViewTreeObserver { public final Rect contentInsets = new Rect(); /** - * Offsets from the fram of the window at which windows behind it + * Offsets from the frame of the window at which windows behind it * are visible. */ public final Rect visibleInsets = new Rect(); - + + /** + * Touchable region defined relative to the origin of the frame of the window. + * Only used when {@link #setTouchableInsets(int)} is called with + * the option {@link #TOUCHABLE_INSETS_REGION}. + */ + public final Region touchableRegion = new Region(); + /** * Option for {@link #setTouchableInsets(int)}: the entire window frame * can be touched. @@ -148,11 +156,17 @@ public final class ViewTreeObserver { * the visible insets can be touched. */ public static final int TOUCHABLE_INSETS_VISIBLE = 2; - + + /** + * Option for {@link #setTouchableInsets(int)}: the area inside of + * the provided touchable region in {@link #touchableRegion} can be touched. + */ + public static final int TOUCHABLE_INSETS_REGION = 3; + /** * Set which parts of the window can be touched: either * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT}, - * or {@link #TOUCHABLE_INSETS_VISIBLE}. + * {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}. */ public void setTouchableInsets(int val) { mTouchableInsets = val; @@ -165,11 +179,9 @@ public final class ViewTreeObserver { int mTouchableInsets; void reset() { - final Rect givenContent = contentInsets; - final Rect givenVisible = visibleInsets; - givenContent.left = givenContent.top = givenContent.right - = givenContent.bottom = givenVisible.left = givenVisible.top - = givenVisible.right = givenVisible.bottom = 0; + contentInsets.setEmpty(); + visibleInsets.setEmpty(); + touchableRegion.setEmpty(); mTouchableInsets = TOUCHABLE_INSETS_FRAME; } @@ -179,13 +191,16 @@ public final class ViewTreeObserver { return false; } InternalInsetsInfo other = (InternalInsetsInfo)o; + if (mTouchableInsets != other.mTouchableInsets) { + return false; + } if (!contentInsets.equals(other.contentInsets)) { return false; } if (!visibleInsets.equals(other.visibleInsets)) { return false; } - return mTouchableInsets == other.mTouchableInsets; + return touchableRegion.equals(other.touchableRegion); } catch (ClassCastException e) { return false; } @@ -194,6 +209,7 @@ public final class ViewTreeObserver { void set(InternalInsetsInfo other) { contentInsets.set(other.contentInsets); visibleInsets.set(other.visibleInsets); + touchableRegion.set(other.touchableRegion); mTouchableInsets = other.mTouchableInsets; } } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index d28bdc9..f023e94 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -63,7 +63,6 @@ extern int register_android_graphics_MaskFilter(JNIEnv* env); extern int register_android_graphics_Movie(JNIEnv* env); extern int register_android_graphics_NinePatch(JNIEnv*); extern int register_android_graphics_PathEffect(JNIEnv* env); -extern int register_android_graphics_Region(JNIEnv* env); extern int register_android_graphics_Shader(JNIEnv* env); extern int register_android_graphics_Typeface(JNIEnv* env); extern int register_android_graphics_YuvImage(JNIEnv* env); @@ -111,6 +110,7 @@ extern int register_android_graphics_PathMeasure(JNIEnv* env); extern int register_android_graphics_Picture(JNIEnv*); extern int register_android_graphics_PorterDuff(JNIEnv* env); extern int register_android_graphics_Rasterizer(JNIEnv* env); +extern int register_android_graphics_Region(JNIEnv* env); extern int register_android_graphics_SurfaceTexture(JNIEnv* env); extern int register_android_graphics_Xfermode(JNIEnv* env); extern int register_android_graphics_PixelFormat(JNIEnv* env); diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp index 723cd37..c43b5ce 100644 --- a/core/jni/android/graphics/Region.cpp +++ b/core/jni/android/graphics/Region.cpp @@ -1,8 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "SkRegion.h" #include "SkPath.h" #include "GraphicsJNI.h" +#include <binder/Parcel.h> +#include "android_util_Binder.h" + #include <jni.h> +#include <android_runtime/AndroidRuntime.h> + +namespace android { static jfieldID gRegion_nativeInstanceFieldID; @@ -134,9 +156,6 @@ static void Region_scale(JNIEnv* env, jobject region, jfloat scale, jobject dst) //////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include <binder/Parcel.h> -#include "android_util_Binder.h" - static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel) { if (parcel == NULL) { @@ -215,8 +234,6 @@ static jboolean RegionIter_next(JNIEnv* env, jobject, RgnIterPair* pair, jobject //////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include <android_runtime/AndroidRuntime.h> - static JNINativeMethod gRegionIterMethods[] = { { "nativeConstructor", "(I)I", (void*)RegionIter_constructor }, { "nativeDestructor", "(I)V", (void*)RegionIter_destructor }, @@ -268,3 +285,9 @@ int register_android_graphics_Region(JNIEnv* env) return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/RegionIterator", gRegionIterMethods, SK_ARRAY_COUNT(gRegionIterMethods)); } + +SkRegion* android_graphics_Region_getSkRegion(JNIEnv* env, jobject regionObj) { + return GetSkRegion(env, regionObj); +} + +} // namespace android diff --git a/core/jni/android/graphics/Region.h b/core/jni/android/graphics/Region.h new file mode 100644 index 0000000..c15f06e --- /dev/null +++ b/core/jni/android/graphics/Region.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_GRAPHICS_REGION_H +#define _ANDROID_GRAPHICS_REGION_H + +#include "jni.h" +#include "SkRegion.h" + +namespace android { + +/* Gets the underlying SkRegion from a Region object. */ +extern SkRegion* android_graphics_Region_getSkRegion(JNIEnv* env, jobject regionObj); + +} // namespace android + +#endif // _ANDROID_GRAPHICS_REGION_H |