Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ecf5d28 authored by Mitsuru Oshima's avatar Mitsuru Oshima
Browse files

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.
parent 7761920b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -173,7 +173,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     * {@hide}
     */
    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
+12 −2
Original line number Diff line number Diff line
@@ -945,15 +945,25 @@ public class PackageParser {
                        >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
        }
        
        int densities[] = null;
        int size = pkg.supportsDensityList.size();
        if (size > 0) {
            int densities[] = pkg.supportsDensities = new int[size];
            densities = pkg.supportsDensities = new int[size];
            List<Integer> densityList = pkg.supportsDensityList;
            for (int i = 0; i < size; 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;
    }

+45 −199
Original line number Diff line number Diff line
@@ -50,18 +50,6 @@ public class CompatibilityInfo {
     */    
    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
     */
@@ -106,20 +94,6 @@ public class CompatibilityInfo {
     */
    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) {
        appFlags = appInfo.flags;
        
@@ -153,6 +127,7 @@ public class CompatibilityInfo {
            applicationScale =
                    DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
        }

        applicationInvertedScale = 1.0f / applicationScale;
        if (applicationScale != 1.0f) {
            mCompatibilityFlags |= SCALING_REQUIRED;
@@ -181,22 +156,9 @@ public class CompatibilityInfo {
    public CompatibilityInfo copy() {
        CompatibilityInfo info = new CompatibilityInfo(appFlags, mCompatibilityFlags,
                applicationScale, applicationInvertedScale);
        info.setVisibleRect(mXOffset, mWidth, mHeight);
        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.
     */
@@ -222,6 +184,10 @@ public class CompatibilityInfo {
        return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
    }
    
    public boolean supportsScreen() {
        return (mCompatibilityFlags & CompatibilityInfo.EXPANDABLE) != 0;
    }
    
    @Override
    public String toString() {
        return "CompatibilityInfo{scale=" + applicationScale +
@@ -231,21 +197,6 @@ public class CompatibilityInfo {
    /**
     * 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) {
@@ -254,35 +205,11 @@ public class CompatibilityInfo {
            if (DBG) Log.d(TAG, "no translation required");
            return null;
        }
        
        if ((mCompatibilityFlags & 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 {
        if (!isScalingRequired() ||
            (params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
            return null;
        }
        return new Translator();
    }

    /**
@@ -290,181 +217,79 @@ public class CompatibilityInfo {
     * @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;
        private Rect mVisibleInsetsBuffer = null;
        
        Translator(int shiftMode, boolean scalingRequired, float applicationScale,
                float applicationInvertedScale) {
            mShiftMode = shiftMode;
            this.scalingRequired = scalingRequired;
        Translator(float applicationScale, float applicationInvertedScale) {
            this.applicationScale = applicationScale;
            this.applicationInvertedScale = applicationInvertedScale;
        }

        Translator(int shiftMode) {
            this(shiftMode,
                    isScalingRequired(),
                    CompatibilityInfo.this.applicationScale,
                    CompatibilityInfo.this.applicationInvertedScale);
        }
        
        Translator() {
            this(X_SHIFT_NONE);
            this(CompatibilityInfo.this.applicationScale,
                    CompatibilityInfo.this.applicationInvertedScale);
        }

        /**
         * 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
@@ -482,10 +307,31 @@ public class CompatibilityInfo {
         * 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;
            if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect();
            mVisibleInsetsBuffer.set(visibleInsets);
            translateRectInAppWindowToScreen(mVisibleInsetsBuffer);
            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);
        }
    }
}
+0 −3
Original line number Diff line number Diff line
@@ -109,7 +109,6 @@ public class DisplayMetrics {
     */
    public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
            int screenLayout) {
        int xOffset = 0;
        if (!compatibilityInfo.isConfiguredExpandable()) {
            // Note: this assume that configuration is updated before calling
            // updateMetrics method.
@@ -142,7 +141,6 @@ public class DisplayMetrics {
                
                if (defaultWidth < widthPixels) {
                    // content/window's x offset in original pixels
                    xOffset = ((widthPixels - defaultWidth) / 2);
                    widthPixels = defaultWidth;
                }
                if (defaultHeight < heightPixels) {
@@ -154,7 +152,6 @@ public class DisplayMetrics {
                compatibilityInfo.setExpandable(true);
            }
        }
        compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
        if (compatibilityInfo.isScalingRequired()) {
            float invertedRatio = compatibilityInfo.applicationInvertedScale;
            density *= invertedRatio;
+1 −1
Original line number Diff line number Diff line
@@ -306,7 +306,7 @@ public class SurfaceView extends View {

        // Use original size if the app specified the size of the view,
        // and let the flinger to scale up.
        if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) {
        if (mRequestedWidth <= 0 && mTranslator != null) {
            myWidth *= appScale;
            myHeight *= appScale;
        }
Loading