diff options
author | Wale Ogunwale <ogunwale@google.com> | 2014-10-22 22:17:18 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-10-22 22:17:19 +0000 |
commit | d0aae5a2226c620c547690039fc06dfdf20ea35d (patch) | |
tree | 6002adfd67dac2d5a201d53a98a8a68228aee07e /core | |
parent | fed9888e60f0c7c9eecffbeee22ea058aedbc692 (diff) | |
parent | 393b1c1e88cbdd0f65c8f217c495dbbe8de9125d (diff) | |
download | frameworks_base-d0aae5a2226c620c547690039fc06dfdf20ea35d.zip frameworks_base-d0aae5a2226c620c547690039fc06dfdf20ea35d.tar.gz frameworks_base-d0aae5a2226c620c547690039fc06dfdf20ea35d.tar.bz2 |
Merge "Fix issue #17789629: PopupWindow overlaps with navigation bar." into lmp-mr1-dev
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/Window.java | 13 | ||||
-rw-r--r-- | core/java/android/view/WindowManager.java | 96 | ||||
-rw-r--r-- | core/java/android/widget/PopupWindow.java | 63 |
3 files changed, 130 insertions, 42 deletions
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 63ab7d2..ef073b5 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -24,7 +24,6 @@ import android.content.res.TypedArray; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.media.session.MediaController; -import android.media.session.MediaSession; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; @@ -801,9 +800,6 @@ public abstract class Window { public void setFlags(int flags, int mask) { final WindowManager.LayoutParams attrs = getAttributes(); attrs.flags = (attrs.flags&~mask) | (flags&mask); - if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) { - attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY; - } mForcedWindowFlags |= mask; dispatchWindowAttributesChanged(attrs); } @@ -817,6 +813,15 @@ public abstract class Window { /** * {@hide} */ + protected void setNeedsMenuKey(int value) { + final WindowManager.LayoutParams attrs = getAttributes(); + attrs.needsMenuKey = value; + dispatchWindowAttributesChanged(attrs); + } + + /** + * {@hide} + */ protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) { if (mCallback != null) { mCallback.onWindowAttributesChanged(attrs); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 75c9ebd..3f84c9b 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -878,9 +878,6 @@ public interface WindowManager extends ViewManager { */ public static final int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000; - // ----- HIDDEN FLAGS. - // These start at the high bit and go down. - /** * Flag for a window in local focus mode. * Window in local focus mode can control focus independent of window manager using @@ -903,17 +900,12 @@ public interface WindowManager extends ViewManager { public static final int FLAG_SLIPPERY = 0x20000000; /** - * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU} - * and therefore needs a Menu key. For devices where Menu is a physical button this flag is - * ignored, but on devices where the Menu key is drawn in software it may be hidden unless - * this flag is set. - * - * (Note that Action Bars, when available, are the preferred way to offer additional - * functions otherwise accessed via an options menu.) - * - * {@hide} + * Window flag: When requesting layout with an attached window, the attached window may + * overlap with the screen decorations of the parent window such as the navigation bar. By + * including this flag, the window manager will layout the attached window within the decor + * frame of the parent window such that it doesn't overlap with screen decorations. */ - public static final int FLAG_NEEDS_MENU_KEY = 0x40000000; + public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000; /** * Flag indicating that this Window is responsible for drawing the background for the @@ -1056,16 +1048,6 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004; - /** - * This is set for a window that has explicitly specified its - * FLAG_NEEDS_MENU_KEY, so we know the value on this window is the - * appropriate one to use. If this is not set, we should look at - * windows behind it to determine the appropriate value. - * - * @hide - */ - public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008; - /** In a multiuser system if this flag is set and the owner is a system process then this * window will appear on all user screens. This overrides the default behavior of window * types that normally only appear on the owning user's screen. Refer to each window type @@ -1113,6 +1095,45 @@ public interface WindowManager extends ViewManager { public int privateFlags; /** + * Value for {@link #needsMenuKey} for a window that has not explicitly specified if it + * needs {@link #NEEDS_MENU_SET_TRUE} or doesn't need {@link #NEEDS_MENU_SET_FALSE} a menu + * key. For this case, we should look at windows behind it to determine the appropriate + * value. + * + * @hide + */ + public static final int NEEDS_MENU_UNSET = 0; + + /** + * Value for {@link #needsMenuKey} for a window that has explicitly specified it needs a + * menu key. + * + * @hide + */ + public static final int NEEDS_MENU_SET_TRUE = 1; + + /** + * Value for {@link #needsMenuKey} for a window that has explicitly specified it doesn't + * needs a menu key. + * + * @hide + */ + public static final int NEEDS_MENU_SET_FALSE = 2; + + /** + * State variable for a window belonging to an activity that responds to + * {@link KeyEvent#KEYCODE_MENU} and therefore needs a Menu key. For devices where Menu is a + * physical button this variable is ignored, but on devices where the Menu key is drawn in + * software it may be hidden unless this variable is set to {@link #NEEDS_MENU_SET_TRUE}. + * + * (Note that Action Bars, when available, are the preferred way to offer additional + * functions otherwise accessed via an options menu.) + * + * {@hide} + */ + public int needsMenuKey = NEEDS_MENU_UNSET; + + /** * Given a particular set of window manager flags, determine whether * such a window may be a target for an input method when it has * focus. In particular, this checks the @@ -1120,9 +1141,9 @@ public interface WindowManager extends ViewManager { * flags and returns true if the combination of the two corresponds * to a window that needs to be behind the input method so that the * user can type into it. - * + * * @param flags The current window manager flags. - * + * * @return Returns true if such a window should be behind/interact * with an input method, false if not. */ @@ -1587,14 +1608,15 @@ public interface WindowManager extends ViewManager { out.writeInt(surfaceInsets.top); out.writeInt(surfaceInsets.right); out.writeInt(surfaceInsets.bottom); + out.writeInt(needsMenuKey); } - + public static final Parcelable.Creator<LayoutParams> CREATOR = new Parcelable.Creator<LayoutParams>() { public LayoutParams createFromParcel(Parcel in) { return new LayoutParams(in); } - + public LayoutParams[] newArray(int size) { return new LayoutParams[size]; } @@ -1634,8 +1656,9 @@ public interface WindowManager extends ViewManager { surfaceInsets.top = in.readInt(); surfaceInsets.right = in.readInt(); surfaceInsets.bottom = in.readInt(); + needsMenuKey = in.readInt(); } - + @SuppressWarnings({"PointlessBitwiseExpression"}) public static final int LAYOUT_CHANGED = 1<<0; public static final int TYPE_CHANGED = 1<<1; @@ -1669,14 +1692,16 @@ public interface WindowManager extends ViewManager { /** {@hide} */ public static final int PREFERRED_REFRESH_RATE_CHANGED = 1 << 21; /** {@hide} */ + public static final int NEEDS_MENU_KEY_CHANGED = 1 << 22; + /** {@hide} */ public static final int EVERYTHING_CHANGED = 0xffffffff; // internal buffer to backup/restore parameters under compatibility mode. private int[] mCompatibilityParamsBackup = null; - + public final int copyFrom(LayoutParams o) { int changes = 0; - + if (width != o.width) { width = o.width; changes |= LAYOUT_CHANGED; @@ -1813,9 +1838,14 @@ public interface WindowManager extends ViewManager { changes |= SURFACE_INSETS_CHANGED; } + if (needsMenuKey != o.needsMenuKey) { + needsMenuKey = o.needsMenuKey; + changes |= NEEDS_MENU_KEY_CHANGED; + } + return changes; } - + @Override public String debug(String output) { output += "Contents of " + this + ":"; @@ -1919,6 +1949,10 @@ public interface WindowManager extends ViewManager { if (!surfaceInsets.equals(Insets.NONE)) { sb.append(" surfaceInsets=").append(surfaceInsets); } + if (needsMenuKey != NEEDS_MENU_UNSET) { + sb.append(" needsMenuKey="); + sb.append(needsMenuKey); + } sb.append('}'); return sb.toString(); } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 41d3e320..54a7940 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -97,9 +97,11 @@ public class PopupWindow { private boolean mAllowScrollingAnchorParent = true; private boolean mLayoutInsetDecor = false; private boolean mNotTouchModal; + private boolean mAttachedInDecor = true; + private boolean mAttachedInDecorSet = false; private OnTouchListener mTouchInterceptor; - + private int mWidthMode; private int mWidth; private int mLastWidth; @@ -316,6 +318,7 @@ public class PopupWindow { mContext = contentView.getContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } + setContentView(contentView); setWidth(width); setHeight(height); @@ -373,16 +376,16 @@ public class PopupWindow { public int getAnimationStyle() { return mAnimationStyle; } - + /** - * Set the flag on popup to ignore cheek press eventt; by default this flag + * Set the flag on popup to ignore cheek press event; by default this flag * is set to false * which means the pop wont ignore cheek press dispatch events. - * + * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> - * + * * @see #update() */ public void setIgnoreCheekPress() { @@ -443,6 +446,19 @@ public class PopupWindow { if (mWindowManager == null && mContentView != null) { mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } + + // Setting the default for attachedInDecor based on SDK version here + // instead of in the constructor since we might not have the context + // object in the constructor. We only want to set default here if the + // app hasn't already set the attachedInDecor. + if (mContext != null && !mAttachedInDecorSet) { + // Attach popup window in decor frame of parent window by default for + // {@link Build.VERSION_CODES.LOLLIPOP_MR1} or greater. Keep current + // behavior of not attaching to decor frame for older SDKs. + setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion + >= Build.VERSION_CODES.LOLLIPOP_MR1); + } + } /** @@ -452,7 +468,7 @@ public class PopupWindow { public void setTouchInterceptor(OnTouchListener l) { mTouchInterceptor = l; } - + /** * <p>Indicate whether the popup window can grab the focus.</p> * @@ -702,6 +718,36 @@ public class PopupWindow { } /** + * <p>Indicates whether the popup window will be attached in the decor frame of its parent + * window. + * + * @return true if the window will be attached to the decor frame of its parent window. + * + * @see #setAttachedInDecor(boolean) + * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR + */ + public boolean isAttachedInDecor() { + return mAttachedInDecor; + } + + /** + * <p>This will attach the popup window to the decor frame of the parent window to avoid + * overlaping with screen decorations like the navigation bar. Overrides the default behavior of + * the flag {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR}. + * + * <p>By default the flag is set on SDK version {@link Build.VERSION_CODES#LOLLIPOP_MR1} or + * greater and cleared on lesser SDK versions. + * + * @param enabled true if the popup should be attached to the decor frame of its parent window. + * + * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR + */ + public void setAttachedInDecor(boolean enabled) { + mAttachedInDecor = enabled; + mAttachedInDecorSet = true; + } + + /** * Allows the popup window to force the flag * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior. * This will cause the popup to inset its content to account for system windows overlaying @@ -1140,9 +1186,12 @@ public class PopupWindow { if (mNotTouchModal) { curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; } + if (mAttachedInDecor) { + curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR; + } return curFlags; } - + private int computeAnimationResource() { if (mAnimationStyle == -1) { if (mIsDropdown) { |