From 9b4125e435b6bc8f8bd2f6e569d9b0b296ab16ef Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Tue, 11 Sep 2012 15:36:44 -0700 Subject: [PATCH] Screen magnifier should handle window rebuilds correctly. 1. The way for computing the magnified region was simplistic and incorrect. It was ignoring window layering resulting in broken behavior. For example, if the IME is up, then the everything else is magnifed and the IME not. Now the keyguard appears and covers the IME but the magnified region does not expand while it would since the keyguard completely covers the not magnified IME window. bug:7138937 Change-Id: I21414635aefab700ce75d40f3e913c1472cba202 --- core/java/android/view/WindowInfo.java | 32 +++++-- .../server/accessibility/ScreenMagnifier.java | 84 ++++++++++++++++--- .../server/wm/WindowManagerService.java | 1 + 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java index 00875ae0e310b..7d16e147d2937 100644 --- a/core/java/android/view/WindowInfo.java +++ b/core/java/android/view/WindowInfo.java @@ -45,13 +45,15 @@ public class WindowInfo implements Parcelable { public final Rect touchableRegion = new Rect(); - public int type; + public int type = UNDEFINED; - public float compatibilityScale; + public float compatibilityScale = UNDEFINED; public boolean visible; - public int displayId; + public int displayId = UNDEFINED; + + public int layer = UNDEFINED; private WindowInfo() { /* do nothing - reduce visibility */ @@ -71,6 +73,7 @@ public class WindowInfo implements Parcelable { parcel.writeFloat(compatibilityScale); parcel.writeInt(visible ? 1 : 0); parcel.writeInt(displayId); + parcel.writeInt(layer); recycle(); } @@ -82,6 +85,7 @@ public class WindowInfo implements Parcelable { compatibilityScale = parcel.readFloat(); visible = (parcel.readInt() == 1); displayId = parcel.readInt(); + layer = parcel.readInt(); } public static WindowInfo obtain(WindowInfo other) { @@ -90,9 +94,10 @@ public class WindowInfo implements Parcelable { info.frame.set(other.frame); info.touchableRegion.set(other.touchableRegion); info.type = other.type; - info.displayId = other.displayId; info.compatibilityScale = other.compatibilityScale; info.visible = other.visible; + info.displayId = other.displayId; + info.layer = other.layer; return info; } @@ -131,8 +136,25 @@ public class WindowInfo implements Parcelable { frame.setEmpty(); touchableRegion.setEmpty(); type = UNDEFINED; - displayId = UNDEFINED; + compatibilityScale = UNDEFINED; visible = false; + displayId = UNDEFINED; + layer = UNDEFINED; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Window [token:").append((token != null) ? token.hashCode() : null); + builder.append(", displayId:").append(displayId); + builder.append(", type:").append(type); + builder.append(", visible:").append(visible); + builder.append(", layer:").append(layer); + builder.append(", compatibilityScale:").append(compatibilityScale); + builder.append(", frame:").append(frame); + builder.append(", touchableRegion:").append(touchableRegion); + builder.append("]"); + return builder.toString(); } /** diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/java/com/android/server/accessibility/ScreenMagnifier.java index 830121141afca..d6482fa0c6320 100644 --- a/services/java/com/android/server/accessibility/ScreenMagnifier.java +++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java @@ -67,6 +67,8 @@ import com.android.internal.R; import com.android.internal.os.SomeArgs; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; /** * This class handles the screen magnification when accessibility is enabled. @@ -1020,7 +1022,9 @@ public final class ScreenMagnifier implements EventStreamTransformation { } if (info.type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD - || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG) { + || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG + || info.type == WindowManager.LayoutParams.TYPE_KEYGUARD + || info.type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { switch (transition) { case WindowManagerPolicy.TRANSIT_ENTER: case WindowManagerPolicy.TRANSIT_SHOW: @@ -1473,7 +1477,9 @@ public final class ScreenMagnifier implements EventStreamTransformation { private final ArrayList mTempWindowInfoList = new ArrayList(); - private final Rect mTempRect = new Rect(); + private final Rect mTempRect1 = new Rect(); + private final Rect mTempRect2 = new Rect(); + private final Rect mTempRect3 = new Rect(); private final IWindowManager mWindowManagerService; private final DisplayProvider mDisplayProvider; @@ -1542,31 +1548,83 @@ public final class ScreenMagnifier implements EventStreamTransformation { recomputeBounds(false); } + private final Comparator mWindowInfoInverseComparator = + new Comparator() { + @Override + public int compare(WindowInfo lhs, WindowInfo rhs) { + if (lhs.layer != rhs.layer) { + return rhs.layer - lhs.layer; + } + if (lhs.touchableRegion.top != rhs.touchableRegion.top) { + return rhs.touchableRegion.top - lhs.touchableRegion.top; + } + if (lhs.touchableRegion.left != rhs.touchableRegion.left) { + return rhs.touchableRegion.left - lhs.touchableRegion.left; + } + if (lhs.touchableRegion.right != rhs.touchableRegion.right) { + return rhs.touchableRegion.right - lhs.touchableRegion.right; + } + if (lhs.touchableRegion.bottom != rhs.touchableRegion.bottom) { + return rhs.touchableRegion.bottom - lhs.touchableRegion.bottom; + } + return 0; + } + }; + public void recomputeBounds(boolean animate) { - Rect frame = mTempRect; - frame.set(0, 0, mDisplayProvider.getDisplayInfo().logicalWidth, - mDisplayProvider.getDisplayInfo().logicalHeight); + Rect magnifiedFrame = mTempRect1; + magnifiedFrame.set(0, 0, 0, 0); + + Rect notMagnifiedFrame = mTempRect2; + notMagnifiedFrame.set(0, 0, 0, 0); + ArrayList infos = mTempWindowInfoList; infos.clear(); + int windowCount = 0; try { mWindowManagerService.getVisibleWindowsForDisplay( mDisplayProvider.getDisplay().getDisplayId(), infos); - final int windowCount = infos.size(); + Collections.sort(infos, mWindowInfoInverseComparator); + windowCount = infos.size(); for (int i = 0; i < windowCount; i++) { WindowInfo info = infos.get(i); - if (info.type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR - || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD - || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG) { - subtract(frame, info.touchableRegion); + if (info.type == WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY) { + continue; + } + if (isWindowMagnified(info.type)) { + Rect clippedFrame = mTempRect3; + clippedFrame.set(info.touchableRegion); + subtract(clippedFrame, notMagnifiedFrame); + magnifiedFrame.union(clippedFrame); + } else { + Rect clippedFrame = mTempRect3; + clippedFrame.set(info.touchableRegion); + subtract(clippedFrame, magnifiedFrame); + notMagnifiedFrame.union(clippedFrame); + } + if (magnifiedFrame.bottom >= notMagnifiedFrame.top) { + break; } - info.recycle(); } } catch (RemoteException re) { /* ignore */ } finally { - infos.clear(); + for (int i = windowCount - 1; i >= 0; i--) { + infos.remove(i).recycle(); + } } - resize(frame, animate); + + final int displayWidth = mDisplayProvider.getDisplayInfo().logicalWidth; + final int displayHeight = mDisplayProvider.getDisplayInfo().logicalHeight; + magnifiedFrame.intersect(0, 0, displayWidth, displayHeight); + + resize(magnifiedFrame, animate); + } + + private boolean isWindowMagnified(int type) { + return (type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR + && type != WindowManager.LayoutParams.TYPE_INPUT_METHOD + && type != WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG); } public void rotationChanged() { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index cdca8bc7b4d07..fe25f778fca1f 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -3153,6 +3153,7 @@ public class WindowManagerService extends IWindowManager.Stub info.compatibilityScale = window.mGlobalScale; info.visible = window.isVisibleLw() || info.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND; + info.layer = window.mLayer; window.getTouchableRegion(mTempRegion); mTempRegion.getBounds(info.touchableRegion); return info;