Merge "Allow focusable in touch mode views to ignore touchscreen focus blocks" into lmp-dev
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 90eb516..0079cc9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5048,8 +5048,17 @@
* View, false otherwise.
*
* @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
+ * @see ViewGroup#getTouchscreenBlocksFocus()
*/
public boolean hasFocusable() {
+ if (!isFocusableInTouchMode()) {
+ for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
+ final ViewGroup g = (ViewGroup) p;
+ if (g.shouldBlockFocusForTouchscreen()) {
+ return false;
+ }
+ }
+ }
return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
}
@@ -7439,11 +7448,12 @@
* @return Whether any ancestor of this view blocks descendant focus.
*/
private boolean hasAncestorThatBlocksDescendantFocus() {
+ final boolean focusableInTouchMode = isFocusableInTouchMode();
ViewParent ancestor = mParent;
while (ancestor instanceof ViewGroup) {
final ViewGroup vgAncestor = (ViewGroup) ancestor;
if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
- || vgAncestor.shouldBlockFocusForTouchscreen()) {
+ || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
return true;
} else {
ancestor = vgAncestor.getParent();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 04c8b0b..1028a0c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -669,7 +669,7 @@
// shortcut: don't report a new focusable view if we block our descendants from
// getting focus
&& (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
- && !shouldBlockFocusForTouchscreen()
+ && (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())
// shortcut: don't report a new focusable view if we already are focused
// (and we don't prefer our descendants)
//
@@ -865,6 +865,17 @@
return mFocused;
}
+ View getDeepestFocusedChild() {
+ View v = this;
+ while (v != null) {
+ if (v.isFocused()) {
+ return v;
+ }
+ v = v instanceof ViewGroup ? ((ViewGroup) v).getFocusedChild() : null;
+ }
+ return null;
+ }
+
/**
* Returns true if this view has or contains focus
*
@@ -911,8 +922,7 @@
}
final int descendantFocusability = getDescendantFocusability();
- if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS &&
- !shouldBlockFocusForTouchscreen()) {
+ if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
final int count = mChildrenCount;
final View[] children = mChildren;
@@ -936,8 +946,11 @@
final int descendantFocusability = getDescendantFocusability();
- if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS &&
- !shouldBlockFocusForTouchscreen()) {
+ if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
+ if (shouldBlockFocusForTouchscreen()) {
+ focusableMode |= FOCUSABLES_TOUCH_MODE;
+ }
+
final int count = mChildrenCount;
final View[] children = mChildren;
@@ -955,7 +968,8 @@
// among the focusable children would be more interesting.
if ((descendantFocusability != FOCUS_AFTER_DESCENDANTS
// No focusable descendants
- || (focusableCount == views.size())) && !shouldBlockFocusForTouchscreen()) {
+ || (focusableCount == views.size())) &&
+ (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())) {
super.addFocusables(views, direction, focusableMode);
}
}
@@ -971,9 +985,12 @@
if (touchscreenBlocksFocus) {
mGroupFlags |= FLAG_TOUCHSCREEN_BLOCKS_FOCUS;
if (hasFocus()) {
- final View newFocus = focusSearch(FOCUS_FORWARD);
- if (newFocus != null) {
- newFocus.requestFocus();
+ final View focusedChild = getDeepestFocusedChild();
+ if (!focusedChild.isFocusableInTouchMode()) {
+ final View newFocus = focusSearch(FOCUS_FORWARD);
+ if (newFocus != null) {
+ newFocus.requestFocus();
+ }
}
}
} else {
@@ -2485,10 +2502,6 @@
}
int descendantFocusability = getDescendantFocusability();
- if (shouldBlockFocusForTouchscreen()) {
- return false;
- }
-
switch (descendantFocusability) {
case FOCUS_BLOCK_DESCENDANTS:
return super.requestFocus(direction, previouslyFocusedRect);