Re-implementation of large screen support using window manager.

* added background filler surface to fill the outer rim. Using the same layer as dim surface because
   they never co-exists (in the same window)
 * clean up the obsolete code in CompatibiltyMode/ViewRoot for support large screen support.
This commit is contained in:
Mitsuru Oshima
2009-07-06 17:20:38 -07:00
parent 7761920b2a
commit 1ecf5d2881
8 changed files with 164 additions and 233 deletions

View File

@@ -173,7 +173,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* {@hide} * {@hide}
*/ */
public static final int ANY_DENSITY = -1; public static final int ANY_DENSITY = -1;
private static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY }; static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
/** /**
* Flags associated with the application. Any combination of * Flags associated with the application. Any combination of

View File

@@ -945,15 +945,25 @@ public class PackageParser {
>= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
} }
int densities[] = null;
int size = pkg.supportsDensityList.size(); int size = pkg.supportsDensityList.size();
if (size > 0) { if (size > 0) {
int densities[] = pkg.supportsDensities = new int[size]; densities = pkg.supportsDensities = new int[size];
List<Integer> densityList = pkg.supportsDensityList; List<Integer> densityList = pkg.supportsDensityList;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
densities[i] = densityList.get(i); densities[i] = densityList.get(i);
} }
} }
/**
* TODO: enable this before code freeze. b/1967935
* *
if ((densities == null || densities.length == 0)
&& (pkg.applicationInfo.targetSdkVersion
>= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY;
}
*/
return pkg; return pkg;
} }

View File

@@ -50,18 +50,6 @@ public class CompatibilityInfo {
*/ */
public static final int DEFAULT_PORTRAIT_HEIGHT = 480; public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
/**
* The x-shift mode that controls the position of the content or the window under
* compatibility mode.
* {@see getTranslator}
* {@see Translator#mShiftMode}
*/
private static final int X_SHIFT_NONE = 0;
private static final int X_SHIFT_CONTENT = 1;
private static final int X_SHIFT_AND_CLIP_CONTENT = 2;
private static final int X_SHIFT_WINDOW = 3;
/** /**
* A compatibility flags * A compatibility flags
*/ */
@@ -106,20 +94,6 @@ public class CompatibilityInfo {
*/ */
public final int appFlags; public final int appFlags;
/**
* Window size in Compatibility Mode, in real pixels. This is updated by
* {@link DisplayMetrics#updateMetrics}.
*/
private int mWidth;
private int mHeight;
/**
* The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added
* to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset
* is used to translate the Canvas.
*/
private int mXOffset;
public CompatibilityInfo(ApplicationInfo appInfo) { public CompatibilityInfo(ApplicationInfo appInfo) {
appFlags = appInfo.flags; appFlags = appInfo.flags;
@@ -153,6 +127,7 @@ public class CompatibilityInfo {
applicationScale = applicationScale =
DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY; DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
} }
applicationInvertedScale = 1.0f / applicationScale; applicationInvertedScale = 1.0f / applicationScale;
if (applicationScale != 1.0f) { if (applicationScale != 1.0f) {
mCompatibilityFlags |= SCALING_REQUIRED; mCompatibilityFlags |= SCALING_REQUIRED;
@@ -181,22 +156,9 @@ public class CompatibilityInfo {
public CompatibilityInfo copy() { public CompatibilityInfo copy() {
CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags, CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags,
applicationScale, applicationInvertedScale); applicationScale, applicationInvertedScale);
info.setVisibleRect(mXOffset, mWidth, mHeight);
return info; return info;
} }
/**
* Sets the application's visible rect in compatibility mode.
* @param xOffset the application's x offset that is added to center the content.
* @param widthPixels the application's width in real pixels on the screen.
* @param heightPixels the application's height in real pixels on the screen.
*/
public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) {
this.mXOffset = xOffset;
mWidth = widthPixels;
mHeight = heightPixels;
}
/** /**
* Sets expandable bit in the compatibility flag. * Sets expandable bit in the compatibility flag.
*/ */
@@ -222,6 +184,10 @@ public class CompatibilityInfo {
return (mCompatibilityFlags & SCALING_REQUIRED) != 0; return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
} }
public boolean supportsScreen() {
return (mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) != 0;
}
@Override @Override
public String toString() { public String toString() {
return "CompatibilityInfo{scale=" + applicationScale + return "CompatibilityInfo{scale=" + applicationScale +
@@ -231,21 +197,6 @@ public class CompatibilityInfo {
/** /**
* Returns the translator which can translate the coordinates of the window. * Returns the translator which can translate the coordinates of the window.
* There are five different types of Translator. * There are five different types of Translator.
*
* 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT}
* Shift and clip the content of the window at drawing time. Used for activities'
* main window (with no gravity).
* 2) {@link CompatibilityInfo#X_SHIFT_CONTENT}
* Shift the content of the window at drawing time. Used for windows that is created by
* an application and expected to be aligned with the application window.
* 3) {@link CompatibilityInfo#X_SHIFT_WINDOW}
* Create the window with adjusted x- coordinates. This is typically used
* in popup window, where it has to be placed relative to main window.
* 4) {@link CompatibilityInfo#X_SHIFT_NONE}
* No adjustment required, such as dialog.
* 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which
* does not require scaling, but its window's location has to be adjusted.
*
* @param params the window's parameter * @param params the window's parameter
*/ */
public Translator getTranslator(WindowManager.LayoutParams params) { public Translator getTranslator(WindowManager.LayoutParams params) {
@@ -254,35 +205,11 @@ public class CompatibilityInfo {
if (DBG) Log.d(TAG, "no translation required"); if (DBG) Log.d(TAG, "no translation required");
return null; return null;
} }
if (!isScalingRequired() ||
if ((mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) { (params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
if (DBG) Log.d(TAG, "translation for surface view selected");
return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
} else {
int shiftMode;
if (params.gravity == Gravity.NO_GRAVITY) {
// For Regular Application window
shiftMode = X_SHIFT_AND_CLIP_CONTENT;
if (DBG) Log.d(TAG, "shift and clip translator");
} else if (params.width == WindowManager.LayoutParams.FILL_PARENT) {
// For Regular Application window
shiftMode = X_SHIFT_CONTENT;
if (DBG) Log.d(TAG, "shift content translator");
} else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) {
shiftMode = X_SHIFT_WINDOW;
if (DBG) Log.d(TAG, "shift window translator");
} else {
shiftMode = X_SHIFT_NONE;
if (DBG) Log.d(TAG, "no content/window translator");
}
return new Translator(shiftMode);
}
} else if (isScalingRequired()) {
return new Translator();
} else {
return null; return null;
} }
return new Translator();
} }
/** /**
@@ -290,181 +217,79 @@ public class CompatibilityInfo {
* @hide * @hide
*/ */
public class Translator { public class Translator {
final private int mShiftMode;
final public boolean scalingRequired;
final public float applicationScale; final public float applicationScale;
final public float applicationInvertedScale; final public float applicationInvertedScale;
private Rect mContentInsetsBuffer = null; private Rect mContentInsetsBuffer = null;
private Rect mVisibleInsets = null; private Rect mVisibleInsetsBuffer = null;
Translator(int shiftMode, boolean scalingRequired, float applicationScale, Translator(float applicationScale, float applicationInvertedScale) {
float applicationInvertedScale) {
mShiftMode = shiftMode;
this.scalingRequired = scalingRequired;
this.applicationScale = applicationScale; this.applicationScale = applicationScale;
this.applicationInvertedScale = applicationInvertedScale; this.applicationInvertedScale = applicationInvertedScale;
} }
Translator(int shiftMode) {
this(shiftMode,
isScalingRequired(),
CompatibilityInfo.this.applicationScale,
CompatibilityInfo.this.applicationInvertedScale);
}
Translator() { Translator() {
this(X_SHIFT_NONE); this(CompatibilityInfo.this.applicationScale,
CompatibilityInfo.this.applicationInvertedScale);
} }
/** /**
* Translate the screen rect to the application frame. * Translate the screen rect to the application frame.
*/ */
public void translateRectInScreenToAppWinFrame(Rect rect) { public void translateRectInScreenToAppWinFrame(Rect rect) {
if (rect.isEmpty()) return; // skip if the window size is empty.
switch (mShiftMode) {
case X_SHIFT_AND_CLIP_CONTENT:
rect.intersect(0, 0, mWidth, mHeight);
break;
case X_SHIFT_CONTENT:
rect.intersect(0, 0, mWidth + mXOffset, mHeight);
break;
case X_SHIFT_WINDOW:
case X_SHIFT_NONE:
break;
}
if (scalingRequired) {
rect.scale(applicationInvertedScale); rect.scale(applicationInvertedScale);
} }
}
/** /**
* Translate the region in window to screen. * Translate the region in window to screen.
*/ */
public void translateRegionInWindowToScreen(Region transparentRegion) { public void translateRegionInWindowToScreen(Region transparentRegion) {
switch (mShiftMode) {
case X_SHIFT_AND_CLIP_CONTENT:
case X_SHIFT_CONTENT:
transparentRegion.scale(applicationScale); transparentRegion.scale(applicationScale);
transparentRegion.translate(mXOffset, 0);
break;
case X_SHIFT_WINDOW:
case X_SHIFT_NONE:
transparentRegion.scale(applicationScale);
}
} }
/** /**
* Apply translation to the canvas that is necessary to draw the content. * Apply translation to the canvas that is necessary to draw the content.
*/ */
public void translateCanvas(Canvas canvas) { public void translateCanvas(Canvas canvas) {
if (mShiftMode == X_SHIFT_CONTENT ||
mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
// TODO: clear outside when rotation is changed.
// Translate x-offset only when the content is shifted.
canvas.translate(mXOffset, 0);
}
if (scalingRequired) {
canvas.scale(applicationScale, applicationScale); canvas.scale(applicationScale, applicationScale);
} }
}
/** /**
* Translate the motion event captured on screen to the application's window. * Translate the motion event captured on screen to the application's window.
*/ */
public void translateEventInScreenToAppWindow(MotionEvent event) { public void translateEventInScreenToAppWindow(MotionEvent event) {
if (mShiftMode == X_SHIFT_CONTENT ||
mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
event.translate(-mXOffset, 0);
}
if (scalingRequired) {
event.scale(applicationInvertedScale); event.scale(applicationInvertedScale);
} }
}
/** /**
* Translate the window's layout parameter, from application's view to * Translate the window's layout parameter, from application's view to
* Screen's view. * Screen's view.
*/ */
public void translateWindowLayout(WindowManager.LayoutParams params) { public void translateWindowLayout(WindowManager.LayoutParams params) {
switch (mShiftMode) {
case X_SHIFT_NONE:
case X_SHIFT_AND_CLIP_CONTENT:
case X_SHIFT_CONTENT:
params.scale(applicationScale); params.scale(applicationScale);
break;
case X_SHIFT_WINDOW:
params.scale(applicationScale);
params.x += mXOffset;
break;
}
} }
/** /**
* Translate a Rect in application's window to screen. * Translate a Rect in application's window to screen.
*/ */
public void translateRectInAppWindowToScreen(Rect rect) { public void translateRectInAppWindowToScreen(Rect rect) {
// TODO Auto-generated method stub
if (scalingRequired) {
rect.scale(applicationScale); rect.scale(applicationScale);
} }
switch(mShiftMode) {
case X_SHIFT_NONE:
case X_SHIFT_WINDOW:
break;
case X_SHIFT_CONTENT:
case X_SHIFT_AND_CLIP_CONTENT:
rect.offset(mXOffset, 0);
break;
}
}
/** /**
* Translate a Rect in screen coordinates into the app window's coordinates. * Translate a Rect in screen coordinates into the app window's coordinates.
*/ */
public void translateRectInScreenToAppWindow(Rect rect) { public void translateRectInScreenToAppWindow(Rect rect) {
switch (mShiftMode) {
case X_SHIFT_NONE:
case X_SHIFT_WINDOW:
break;
case X_SHIFT_CONTENT: {
rect.intersects(mXOffset, 0, rect.right, rect.bottom);
int dx = Math.min(mXOffset, rect.left);
rect.offset(-dx, 0);
break;
}
case X_SHIFT_AND_CLIP_CONTENT: {
rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight);
int dx = Math.min(mXOffset, rect.left);
rect.offset(-dx, 0);
break;
}
}
if (scalingRequired) {
rect.scale(applicationInvertedScale); rect.scale(applicationInvertedScale);
} }
}
/** /**
* Translate the location of the sub window. * Translate the location of the sub window.
* @param params * @param params
*/ */
public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) { public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
if (scalingRequired) {
params.scale(applicationScale); params.scale(applicationScale);
} }
switch (mShiftMode) {
// the window location on these mode does not require adjustmenet.
case X_SHIFT_NONE:
case X_SHIFT_WINDOW:
break;
case X_SHIFT_CONTENT:
case X_SHIFT_AND_CLIP_CONTENT:
params.x += mXOffset;
break;
}
}
/** /**
* Translate the content insets in application window to Screen. This uses * Translate the content insets in application window to Screen. This uses
@@ -482,10 +307,31 @@ public class CompatibilityInfo {
* the internal buffer for content insets to avoid extra object allocation. * the internal buffer for content insets to avoid extra object allocation.
*/ */
public Rect getTranslatedVisbileInsets(Rect visibleInsets) { public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
if (mVisibleInsets == null) mVisibleInsets = new Rect(); if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect();
mVisibleInsets.set(visibleInsets); mVisibleInsetsBuffer.set(visibleInsets);
translateRectInAppWindowToScreen(mVisibleInsets); translateRectInAppWindowToScreen(mVisibleInsetsBuffer);
return mVisibleInsets; return mVisibleInsetsBuffer;
}
}
/**
* Returns the frame Rect for applications runs under compatibility mode.
*
* @param dm the display metrics used to compute the frame size.
* @param orientation the orientation of the screen.
* @param outRect the output parameter which will contain the result.
*/
public static void updateCompatibleScreenFrame(DisplayMetrics dm, int orientation,
Rect outRect) {
int width = dm.widthPixels;
int portraitHeight = (int) (DEFAULT_PORTRAIT_HEIGHT * dm.density);
int portraitWidth = (int) (DEFAULT_PORTRAIT_WIDTH * dm.density);
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
int xOffset = (width - portraitHeight) / 2 ;
outRect.set(xOffset, 0, xOffset + portraitHeight, portraitWidth);
} else {
int xOffset = (width - portraitWidth) / 2 ;
outRect.set(xOffset, 0, xOffset + portraitWidth, portraitHeight);
} }
} }
} }

View File

@@ -109,7 +109,6 @@ public class DisplayMetrics {
*/ */
public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation, public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
int screenLayout) { int screenLayout) {
int xOffset = 0;
if (!compatibilityInfo.isConfiguredExpandable()) { if (!compatibilityInfo.isConfiguredExpandable()) {
// Note: this assume that configuration is updated before calling // Note: this assume that configuration is updated before calling
// updateMetrics method. // updateMetrics method.
@@ -142,7 +141,6 @@ public class DisplayMetrics {
if (defaultWidth < widthPixels) { if (defaultWidth < widthPixels) {
// content/window's x offset in original pixels // content/window's x offset in original pixels
xOffset = ((widthPixels - defaultWidth) / 2);
widthPixels = defaultWidth; widthPixels = defaultWidth;
} }
if (defaultHeight < heightPixels) { if (defaultHeight < heightPixels) {
@@ -154,7 +152,6 @@ public class DisplayMetrics {
compatibilityInfo.setExpandable(true); compatibilityInfo.setExpandable(true);
} }
} }
compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
if (compatibilityInfo.isScalingRequired()) { if (compatibilityInfo.isScalingRequired()) {
float invertedRatio = compatibilityInfo.applicationInvertedScale; float invertedRatio = compatibilityInfo.applicationInvertedScale;
density *= invertedRatio; density *= invertedRatio;

View File

@@ -306,7 +306,7 @@ public class SurfaceView extends View {
// Use original size if the app specified the size of the view, // Use original size if the app specified the size of the view,
// and let the flinger to scale up. // and let the flinger to scale up.
if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) { if (mRequestedWidth <= 0 && mTranslator != null) {
myWidth *= appScale; myWidth *= appScale;
myHeight *= appScale; myHeight *= appScale;
} }

View File

@@ -385,6 +385,7 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mView == null) { if (mView == null) {
mView = view; mView = view;
mWindowAttributes.copyFrom(attrs); mWindowAttributes.copyFrom(attrs);
attrs = mWindowAttributes;
CompatibilityInfo compatibilityInfo = CompatibilityInfo compatibilityInfo =
mView.getContext().getResources().getCompatibilityInfo(); mView.getContext().getResources().getCompatibilityInfo();
@@ -397,11 +398,14 @@ public final class ViewRoot extends Handler implements ViewParent,
} }
if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs); if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
if (!compatibilityInfo.supportsScreen()) {
attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
}
mSoftInputMode = attrs.softInputMode; mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true; mWindowAttributesChanged = true;
mAttachInfo.mRootView = view; mAttachInfo.mRootView = view;
mAttachInfo.mScalingRequired = mAttachInfo.mScalingRequired = mTranslator == null ? false : true;
mTranslator == null ? false : mTranslator.scalingRequired;
mAttachInfo.mApplicationScale = mAttachInfo.mApplicationScale =
mTranslator == null ? 1.0f : mTranslator.applicationScale; mTranslator == null ? 1.0f : mTranslator.applicationScale;
if (panelParentView != null) { if (panelParentView != null) {

View File

@@ -484,11 +484,19 @@ public interface WindowManager extends ViewManager {
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000; public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
/** Window flag: special flag to let a window ignore the compatibility scaling. /** Window flag: special flag to let a window ignore the compatibility scaling.
* This is used by SurfaceView to create a window that does not scale the content. * This is used by SurfaceView to pass this info into ViewRoot, and not used
* by WindowManager.
* *
* {@hide} */ * {@hide} */
public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000; public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000;
/** Window flag: special flag to limit the size of the window to be
* original size ([320x480] x density). Used to create window for applications
* running under compatibility mode.
*
* {@hide} */
public static final int FLAG_COMPATIBLE_WINDOW = 0x00200000;
/** Window flag: a special option intended for system dialogs. When /** Window flag: a special option intended for system dialogs. When
* this flag is set, the window will demand focus unconditionally when * this flag is set, the window will demand focus unconditionally when
* it is created. * it is created.

View File

@@ -53,6 +53,7 @@ import android.app.IActivityManager;
import android.content.Context; import android.content.Context;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
@@ -418,6 +419,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
final Configuration mTempConfiguration = new Configuration(); final Configuration mTempConfiguration = new Configuration();
int screenLayout = Configuration.SCREENLAYOUT_UNDEFINED; int screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
// The frame use to limit the size of the app running in compatibility mode.
Rect mCompatibleScreenFrame = new Rect();
// The surface used to fill the outer rim of the app running in compatibility mode.
Surface mBackgroundFillerSurface = null;
boolean mBackgroundFillerShown = false;
public static WindowManagerService main(Context context, public static WindowManagerService main(Context context,
PowerManagerService pm, boolean haveInputMethods) { PowerManagerService pm, boolean haveInputMethods) {
WMThread thr = new WMThread(context, pm, haveInputMethods); WMThread thr = new WMThread(context, pm, haveInputMethods);
@@ -3738,12 +3745,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
} }
config.orientation = orientation; config.orientation = orientation;
DisplayMetrics dm = new DisplayMetrics();
mDisplay.getMetrics(dm);
CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
if (screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) { if (screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
// Note we only do this once because at this point we don't // Note we only do this once because at this point we don't
// expect the screen to change in this way at runtime, and want // expect the screen to change in this way at runtime, and want
// to avoid all of this computation for every config change. // to avoid all of this computation for every config change.
DisplayMetrics dm = new DisplayMetrics();
mDisplay.getMetrics(dm);
int longSize = dw; int longSize = dw;
int shortSize = dh; int shortSize = dh;
if (longSize < shortSize) { if (longSize < shortSize) {
@@ -5845,8 +5854,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) { public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
mHaveFrame = true; mHaveFrame = true;
final int pw = pf.right-pf.left; final Rect container = mContainingFrame;
final int ph = pf.bottom-pf.top; container.set(pf);
final Rect display = mDisplayFrame;
display.set(df);
if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW) != 0) {
container.intersect(mCompatibleScreenFrame);
display.intersect(mCompatibleScreenFrame);
}
final int pw = container.right - container.left;
final int ph = container.bottom - container.top;
int w,h; int w,h;
if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) { if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
@@ -5857,12 +5877,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight; h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight;
} }
final Rect container = mContainingFrame;
container.set(pf);
final Rect display = mDisplayFrame;
display.set(df);
final Rect content = mContentFrame; final Rect content = mContentFrame;
content.set(cf); content.set(cf);
@@ -6573,16 +6587,29 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
return false; return false;
} }
boolean isFullscreenOpaque(int screenWidth, int screenHeight) { /**
if (mAttrs.format != PixelFormat.OPAQUE || mSurface == null * Return true if the window is opaque and fully drawn.
|| mAnimation != null || mDrawPending || mCommitDrawPending) { */
return false; boolean isOpaqueDrawn() {
return mAttrs.format == PixelFormat.OPAQUE && mSurface != null
&& mAnimation == null && !mDrawPending && !mCommitDrawPending;
} }
if (mFrame.left <= 0 && mFrame.top <= 0 &&
mFrame.right >= screenWidth && mFrame.bottom >= screenHeight) { boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
return true; return
// only if the application is requesting compatible window
(mAttrs.flags & mAttrs.FLAG_COMPATIBLE_WINDOW) != 0 &&
// and only if the application wanted to fill the screen
mAttrs.width == mAttrs.FILL_PARENT &&
mAttrs.height == mAttrs.FILL_PARENT &&
// and only if the screen is bigger
((mFrame.right - mFrame.right) < screenWidth ||
(mFrame.bottom - mFrame.top) < screenHeight);
} }
return false;
boolean isFullscreen(int screenWidth, int screenHeight) {
return mFrame.left <= 0 && mFrame.top <= 0 &&
mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
} }
void removeLocked() { void removeLocked() {
@@ -8102,6 +8129,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
boolean dimming = false; boolean dimming = false;
boolean covered = false; boolean covered = false;
boolean syswin = false; boolean syswin = false;
boolean backgroundFillerShown = false;
for (i=N-1; i>=0; i--) { for (i=N-1; i>=0; i--) {
WindowState w = (WindowState)mWindows.get(i); WindowState w = (WindowState)mWindows.get(i);
@@ -8371,11 +8399,39 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
syswin = true; syswin = true;
} }
} }
if (w.isFullscreenOpaque(dw, dh)) {
boolean opaqueDrawn = w.isOpaqueDrawn();
if (opaqueDrawn && w.isFullscreen(dw, dh)) {
// This window completely covers everything behind it, // This window completely covers everything behind it,
// so we want to leave all of them as unblurred (for // so we want to leave all of them as unblurred (for
// performance reasons). // performance reasons).
obscured = true; obscured = true;
} else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler");
// This window is in compatibility mode, and needs background filler.
obscured = true;
if (mBackgroundFillerSurface == null) {
try {
mBackgroundFillerSurface = new Surface(mFxSession, 0,
0, dw, dh,
PixelFormat.OPAQUE,
Surface.FX_SURFACE_NORMAL);
} catch (Exception e) {
Log.e(TAG, "Exception creating filler surface", e);
}
}
try {
mBackgroundFillerSurface.setPosition(0, 0);
mBackgroundFillerSurface.setSize(dw, dh);
// Using the same layer as Dim because they will never be shown at the
// same time.
mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
mBackgroundFillerSurface.show();
} catch (RuntimeException e) {
Log.e(TAG, "Exception showing filler surface");
}
backgroundFillerShown = true;
mBackgroundFillerShown = true;
} else if (canBeSeen && !obscured && } else if (canBeSeen && !obscured &&
(attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
if (localLOGV) Log.v(TAG, "Win " + w if (localLOGV) Log.v(TAG, "Win " + w
@@ -8473,6 +8529,16 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
} }
} }
if (backgroundFillerShown == false && mBackgroundFillerShown) {
mBackgroundFillerShown = false;
if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler");
try {
mBackgroundFillerSurface.hide();
} catch (RuntimeException e) {
Log.e(TAG, "Exception hiding filler surface", e);
}
}
if (!dimming && mDimShown) { if (!dimming && mDimShown) {
// Time to hide the dim surface... start fading. // Time to hide the dim surface... start fading.
if (mDimTargetAlpha != 0) { if (mDimTargetAlpha != 0) {