summaryrefslogtreecommitdiffstats
path: root/core/java/android/content/res
diff options
context:
space:
mode:
authorMitsuru Oshima <oshima@google.com>2009-06-21 00:03:11 -0700
committerMitsuru Oshima <oshima@google.com>2009-06-23 23:11:55 -0700
commit64f59342d41849bd365cb43fad7505d5e3daa417 (patch)
treeb0cef479b2674ee78a8bff6e833224850a36f2ab /core/java/android/content/res
parent5a42b08389f3fe9195930ce5d2998e68bb09b748 (diff)
downloadframeworks_base-64f59342d41849bd365cb43fad7505d5e3daa417.zip
frameworks_base-64f59342d41849bd365cb43fad7505d5e3daa417.tar.gz
frameworks_base-64f59342d41849bd365cb43fad7505d5e3daa417.tar.bz2
* new screen resolution support impl.
* use full window for activities, and shift & clip the content * refactored the compatibility code, and introdcued Translator class to handle cooridnate translations. * removed a workaround to handle an activity with configChagne=rotation in old implementation. * I'll fix background issue on rotation in next CL. * removed unnecessary scaling code in SurfaceView, which I forgot to remove when I changed SurfaceView not to scale the content.
Diffstat (limited to 'core/java/android/content/res')
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java393
-rw-r--r--core/java/android/content/res/Resources.java6
2 files changed, 374 insertions, 25 deletions
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 680fef8..179b9bd 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -17,8 +17,15 @@
package android.content.res;
import android.content.pm.ApplicationInfo;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Region;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
/**
* CompatibilityInfo class keeps the information about compatibility mode that the application is
@@ -27,6 +34,9 @@ import android.view.Gravity;
* {@hide}
*/
public class CompatibilityInfo {
+ private static final boolean DBG = false;
+ private static final String TAG = "CompatibilityInfo";
+
/** default compatibility info object for compatible applications */
public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo();
@@ -41,36 +51,75 @@ public class CompatibilityInfo {
public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
/**
- * Application's scale.
+ * The x-shift mode that controls the position of the content or the window under
+ * compatibility mode.
+ * {@see getTranslator}
+ * {@see Translator#mShiftMode}
*/
- public final float mApplicationScale;
+ 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;
+
/**
- * Application's inverted scale.
+ * A compatibility flags
*/
- public final float mApplicationInvertedScale;
+ private int compatibilityFlags;
/**
- * A boolean flag to indicates that the application can expand over the original size.
+ * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
+ * {@see compatibilityFlag}
+ */
+ private static final int SCALING_REQUIRED = 1;
+
+ /**
+ * A flag mask to indicates that the application can expand over the original size.
* The flag is set to true if
* 1) Application declares its expandable in manifest file using <expandable /> or
* 2) The screen size is same as (320 x 480) * density.
+ * {@see compatibilityFlag}
+ */
+ private static final int EXPANDABLE = 2;
+
+ /**
+ * A flag mask to tell if the application is configured to be expandable. This differs
+ * from EXPANDABLE in that the application that is not expandable will be
+ * marked as expandable if it runs in (320x 480) * density screen size.
+ */
+ private static final int CONFIGURED_EXPANDABLE = 4;
+
+ private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE;
+
+ /**
+ * Application's scale.
*/
- public boolean mExpandable;
+ public final float applicationScale;
/**
- * A expandable flag in the configuration.
+ * Application's inverted scale.
*/
- public final boolean mConfiguredExpandable;
+ public final float applicationInvertedScale;
+
+
+ /**
+ * Window size in Compatibility Mode, in real pixels. This is updated by
+ * {@link DisplayMetrics#updateMetrics}.
+ */
+ private int mWidth;
+ private int mHeight;
/**
- * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
+ * 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.
*/
- public final boolean mScalingRequired;
+ private int mXOffset;
public CompatibilityInfo(ApplicationInfo appInfo) {
- mExpandable = mConfiguredExpandable =
- (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0;
+ if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+ compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+ }
float packageDensityScale = -1.0f;
if (appInfo.supportsDensities != null) {
@@ -93,23 +142,323 @@ public class CompatibilityInfo {
}
}
if (packageDensityScale > 0.0f) {
- mApplicationScale = packageDensityScale;
+ applicationScale = packageDensityScale;
} else {
- mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+ applicationScale =
+ DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+ }
+ applicationInvertedScale = 1.0f / applicationScale;
+ if (applicationScale != 1.0f) {
+ compatibilityFlags |= SCALING_REQUIRED;
}
- mApplicationInvertedScale = 1.0f / mApplicationScale;
- mScalingRequired = mApplicationScale != 1.0f;
}
private CompatibilityInfo() {
- mApplicationScale = mApplicationInvertedScale = 1.0f;
- mExpandable = mConfiguredExpandable = true;
- mScalingRequired = false;
+ applicationScale = applicationInvertedScale = 1.0f;
+ compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
}
+ /**
+ * 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.
+ */
+ public void setExpandable(boolean expandable) {
+ if (expandable) {
+ compatibilityFlags |= CompatibilityInfo.EXPANDABLE;
+ } else {
+ compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
+ }
+ }
+
+ /**
+ * @return true if the application is configured to be expandable.
+ */
+ public boolean isConfiguredExpandable() {
+ return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
+ }
+
+ /**
+ * @return true if the scaling is required
+ */
+ public boolean isScalingRequired() {
+ return (compatibilityFlags & SCALING_REQUIRED) != 0;
+ }
+
@Override
public String toString() {
- return "CompatibilityInfo{scale=" + mApplicationScale +
- ", expandable=" + mExpandable + "}";
+ return "CompatibilityInfo{scale=" + applicationScale +
+ ", compatibility flag=" + compatibilityFlags + "}";
+ }
+
+ /**
+ * Returns the translator which can translate the coordinates of the window.
+ * 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
+ */
+ public Translator getTranslator(WindowManager.LayoutParams params) {
+ if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
+ == CompatibilityInfo.EXPANDABLE) {
+ if (DBG) Log.d(TAG, "no translation required");
+ return null;
+ }
+
+ if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 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;
+ }
+ }
+
+ /**
+ * A helper object to translate the screen and window coordinates back and forth.
+ * @hide
+ */
+ public class Translator {
+ final private int mShiftMode;
+ final public boolean scalingRequired;
+ final public float applicationScale;
+ final public float applicationInvertedScale;
+
+ private Rect mContentInsetsBuffer = null;
+ private Rect mVisibleInsets = null;
+
+ Translator(int shiftMode, boolean scalingRequired, float applicationScale,
+ float applicationInvertedScale) {
+ mShiftMode = shiftMode;
+ this.scalingRequired = scalingRequired;
+ this.applicationScale = applicationScale;
+ this.applicationInvertedScale = applicationInvertedScale;
+ }
+
+ Translator(int shiftMode) {
+ this(shiftMode,
+ isScalingRequired(),
+ CompatibilityInfo.this.applicationScale,
+ CompatibilityInfo.this.applicationInvertedScale);
+ }
+
+ Translator() {
+ this(X_SHIFT_NONE);
+ }
+
+ /**
+ * Translate the screen rect to the application frame.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Translate the region in window to screen.
+ */
+ public void translateRegionInWindowToScreen(Region transparentRegion) {
+ switch (mShiftMode) {
+ case X_SHIFT_AND_CLIP_CONTENT:
+ case X_SHIFT_CONTENT:
+ 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.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Translate the motion event captured on screen to the application's window.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Translate the window's layout parameter, from application's view to
+ * Screen's view.
+ */
+ 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);
+ break;
+ case X_SHIFT_WINDOW:
+ params.scale(applicationScale);
+ params.x += mXOffset;
+ break;
+ }
+ }
+
+ /**
+ * Translate a Rect in application's window to screen.
+ */
+ public void translateRectInAppWindowToScreen(Rect rect) {
+ // TODO Auto-generated method stub
+ if (scalingRequired) {
+ 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.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Translate the location of the sub window.
+ * @param params
+ */
+ public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
+ if (scalingRequired) {
+ 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
+ * the internal buffer for content insets to avoid extra object allocation.
+ */
+ public Rect getTranslatedContentInsets(Rect contentInsets) {
+ if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
+ mContentInsetsBuffer.set(contentInsets);
+ translateRectInAppWindowToScreen(mContentInsetsBuffer);
+ return mContentInsetsBuffer;
+ }
+
+ /**
+ * Translate the visible insets in application window to Screen. This uses
+ * the internal buffer for content insets to avoid extra object allocation.
+ */
+ public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
+ if (mVisibleInsets == null) mVisibleInsets = new Rect();
+ mVisibleInsets.set(visibleInsets);
+ translateRectInAppWindowToScreen(mVisibleInsets);
+ return mVisibleInsets;
+ }
}
-}
+} \ No newline at end of file
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 71dbd38..cb9d46e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -158,10 +158,10 @@ public class Resources {
}
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
- if (!mCompatibilityInfo.mScalingRequired) {
- mPreloadedDrawables = sPreloadedDrawables;
- } else {
+ if (mCompatibilityInfo.isScalingRequired()) {
mPreloadedDrawables = emptySparseArray();
+ } else {
+ mPreloadedDrawables = sPreloadedDrawables;
}
}