summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/ViewGroup.java78
2 files changed, 79 insertions, 1 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 537c474..ab3413e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7338,7 +7338,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
// If the window does not have input focus we take away accessibility
// focus as soon as the user stop hovering over the view.
- if (!mAttachInfo.mHasWindowFocus) {
+ if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
getViewRootImpl().setAccessibilityFocusedHost(null);
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 91e945b..1641d4c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1569,6 +1569,43 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return handled;
}
+ private void exitHoverTargets() {
+ if (mHoveredSelf || mFirstHoverTarget != null) {
+ final long now = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_HOVER_EXIT, 0.0f, 0.0f, 0);
+ event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ dispatchHoverEvent(event);
+ event.recycle();
+ }
+ }
+
+ private void cancelHoverTarget(View view) {
+ HoverTarget predecessor = null;
+ HoverTarget target = mFirstHoverTarget;
+ while (target != null) {
+ final HoverTarget next = target.next;
+ if (target.child == view) {
+ if (predecessor == null) {
+ mFirstHoverTarget = next;
+ } else {
+ predecessor.next = next;
+ }
+ target.recycle();
+
+ final long now = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_HOVER_EXIT, 0.0f, 0.0f, 0);
+ event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ view.dispatchHoverEvent(event);
+ event.recycle();
+ return;
+ }
+ predecessor = target;
+ target = next;
+ }
+ }
+
/** @hide */
@Override
protected boolean hasHoveredChild() {
@@ -1997,6 +2034,32 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ private void cancelTouchTarget(View view) {
+ TouchTarget predecessor = null;
+ TouchTarget target = mFirstTouchTarget;
+ while (target != null) {
+ final TouchTarget next = target.next;
+ if (target.child == view) {
+ if (predecessor == null) {
+ mFirstTouchTarget = next;
+ } else {
+ predecessor.next = next;
+ }
+ target.recycle();
+
+ final long now = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ view.dispatchTouchEvent(event);
+ event.recycle();
+ return;
+ }
+ predecessor = target;
+ target = next;
+ }
+ }
+
/**
* Returns true if a child view can receive pointer events.
* @hide
@@ -2416,6 +2479,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// first send it an ACTION_CANCEL motion event.
cancelAndClearTouchTargets(null);
+ // Similarly, set ACTION_EXIT to all hover targets and clear them.
+ exitHoverTargets();
+
// In case view is detached while transition is running
mLayoutSuppressed = false;
@@ -3453,6 +3519,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
clearChildFocus = true;
}
+ cancelTouchTarget(view);
+ cancelHoverTarget(view);
+
if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
@@ -3533,6 +3602,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
clearChildFocus = view;
}
+ cancelTouchTarget(view);
+ cancelHoverTarget(view);
+
if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
@@ -3603,6 +3675,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
clearChildFocus = view;
}
+ cancelTouchTarget(view);
+ cancelHoverTarget(view);
+
if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
@@ -3648,6 +3723,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
child.clearFocus();
}
+ cancelTouchTarget(child);
+ cancelHoverTarget(child);
+
if ((animate && child.getAnimation() != null) ||
(mTransitioningViews != null && mTransitioningViews.contains(child))) {
addDisappearingView(child);