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

Commit 62a91d67 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Renamed NonClientDecorView to DecorCaptionView

DecorCaptionView better describes what it does now which is to
display the caption area and control buttons within it.

Change-Id: I6b641d6b117bb8f03656bff93702fc093160851d
parent 2b547c3f
Loading
Loading
Loading
Loading
+65 −86
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ import com.android.internal.view.menu.MenuDialogHelper;
import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.DecorCaptionView;
import com.android.internal.widget.FloatingToolbar;
import com.android.internal.widget.NonClientDecorView;

import android.animation.Animator;
import android.animation.ObjectAnimator;
@@ -113,8 +113,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind

    private final Rect mFrameOffsets = new Rect();

    // True if a non client area decor exists.
    private boolean mHasNonClientDecor = false;
    private boolean mHasCaption = false;

    private boolean mChanging;

@@ -173,18 +172,18 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    private Rect mTempRect;
    private Rect mOutsets = new Rect();

    // This is the non client decor view for the window, containing the caption and window control
    // This is the caption view for the window, containing the caption and window control
    // buttons. The visibility of this decor depends on the workspace and the window type.
    // If the window type does not require such a view, this member might be null.
    NonClientDecorView mNonClientDecorView;
    DecorCaptionView mDecorCaptionView;

    // The non client decor needs to adapt to the used workspace. Since querying and changing the
    // workspace is expensive, this is the workspace value the window is currently set up for.
    int mWorkspaceId;
    // Stack window is currently in. Since querying and changing the stack is expensive,
    // this is the stack value the window is currently set up for.
    int mStackId;

    private boolean mWindowResizeCallbacksAdded = false;

    public BackdropFrameRenderer mBackdropFrameRenderer = null;
    BackdropFrameRenderer mBackdropFrameRenderer = null;
    private Drawable mResizingBackgroundDrawable;
    private Drawable mCaptionBackgroundDrawable;

@@ -203,7 +202,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        setWindow(window);
    }

    public void setBackgroundFallback(int resId) {
    void setBackgroundFallback(int resId) {
        mBackgroundFallback.setDrawable(resId != 0 ? getContext().getDrawable(resId) : null);
        setWillNotDraw(getBackground() == null && !mBackgroundFallback.hasFallback());
    }
@@ -363,10 +362,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        int action = event.getAction();
        if (mHasNonClientDecor && isShowingCaption()) {
            // Don't dispatch ACTION_DOWN to the non client decor if the window is
            // resizable and the event was (starting) outside the window.
            // Window resizing events should be handled by WindowManager.
        if (mHasCaption && isShowingCaption()) {
            // Don't dispatch ACTION_DOWN to the captionr if the window is resizable and the event
            // was (starting) outside the window. Window resizing events should be handled by
            // WindowManager.
            // TODO: Investigate how to handle the outside touch in window manager
            //       without generating these events.
            //       Currently we receive these because we need to enlarge the window's
@@ -798,11 +797,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        }
    }

    public void startChanging() {
    void startChanging() {
        mChanging = true;
    }

    public void finishChanging() {
    void finishChanging() {
        mChanging = false;
        drawableChanged();
    }
@@ -1155,7 +1154,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        invalidate();

        int opacity = PixelFormat.OPAQUE;
        if (windowHasShadow()) {
        if (ActivityManager.StackId.hasWindowShadow(mStackId)) {
            // If the window has a shadow, it must be translucent.
            opacity = PixelFormat.TRANSLUCENT;
        } else{
@@ -1514,38 +1513,19 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    }

    /**
     * Informs the decor if a non client decor is attached and visible.
     * Informs the decor if the caption is attached and visible.
     * @param attachedAndVisible true when the decor is visible.
     * Note that this will even be called if there is no non client decor.
     * Note that this will even be called if there is no caption.
     **/
    void enableNonClientDecor(boolean attachedAndVisible) {
        if (mHasNonClientDecor != attachedAndVisible) {
            mHasNonClientDecor = attachedAndVisible;
    void enableCaption(boolean attachedAndVisible) {
        if (mHasCaption != attachedAndVisible) {
            mHasCaption = attachedAndVisible;
            if (getForeground() != null) {
                drawableChanged();
            }
        }
    }

    /**
     * Returns true if the window has a non client decor.
     * @return If there is a non client decor - even if it is not visible.
     **/
    private boolean windowHasNonClientDecor() {
        return mHasNonClientDecor;
    }

    /**
     * Returns true if the Window is free floating and has a shadow (although at some times
     * it might not be displaying it, e.g. during a resize). Note that non overlapping windows
     * do not have a shadow since it could not be seen anyways (a small screen / tablet
     * "tiles" the windows side by side but does not overlap them).
     * @return Returns true when the window has a shadow created by the non client decor.
     **/
    private boolean windowHasShadow() {
        return windowHasNonClientDecor() && ActivityManager.StackId.hasWindowShadow(mWorkspaceId);
    }

    void setWindow(PhoneWindow phoneWindow) {
        mWindow = phoneWindow;
        Context context = getContext();
@@ -1556,40 +1536,40 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    }

    void onConfigurationChanged() {
        int workspaceId = getWorkspaceId();
        if (mNonClientDecorView != null) {
            if (mWorkspaceId != workspaceId) {
                mWorkspaceId = workspaceId;
        int workspaceId = getStackId();
        if (mDecorCaptionView != null) {
            if (mStackId != workspaceId) {
                mStackId = workspaceId;
                // We might have to change the kind of surface before we do anything else.
                mNonClientDecorView.onConfigurationChanged(
                        ActivityManager.StackId.hasWindowDecor(mWorkspaceId));
                enableNonClientDecor(ActivityManager.StackId.hasWindowDecor(workspaceId));
                mDecorCaptionView.onConfigurationChanged(
                        ActivityManager.StackId.hasWindowDecor(mStackId));
                enableCaption(ActivityManager.StackId.hasWindowDecor(workspaceId));
            }
        }
        initializeElevation();
    }

    View onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
        mWorkspaceId = getWorkspaceId();
        mStackId = getStackId();

        mResizingBackgroundDrawable = getResizingBackgroundDrawable(
                mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource);
        mCaptionBackgroundDrawable =
                getContext().getDrawable(R.drawable.non_client_decor_title_focused);
                getContext().getDrawable(R.drawable.decor_caption_title_focused);

        if (mBackdropFrameRenderer != null) {
            mBackdropFrameRenderer.onResourcesLoaded(
                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
        }

        mNonClientDecorView = createNonClientDecorView(inflater);
        mDecorCaptionView = createDecorCaptionView(inflater);
        final View root = inflater.inflate(layoutResource, null);
        if (mNonClientDecorView != null) {
            if (mNonClientDecorView.getParent() == null) {
                addView(mNonClientDecorView,
        if (mDecorCaptionView != null) {
            if (mDecorCaptionView.getParent() == null) {
                addView(mDecorCaptionView,
                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
            }
            mNonClientDecorView.addView(root,
            mDecorCaptionView.addView(root,
                    new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        } else {
            addView(root, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
@@ -1599,47 +1579,46 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        return root;
    }

    // Free floating overlapping windows require a non client decor with a caption and shadow..
    private NonClientDecorView createNonClientDecorView(LayoutInflater inflater) {
        NonClientDecorView nonClientDecorView = null;
        for (int i = getChildCount() - 1; i >= 0 && nonClientDecorView == null; i--) {
    // Free floating overlapping windows require a caption.
    private DecorCaptionView createDecorCaptionView(LayoutInflater inflater) {
        DecorCaptionView DecorCaptionView = null;
        for (int i = getChildCount() - 1; i >= 0 && DecorCaptionView == null; i--) {
            View view = getChildAt(i);
            if (view instanceof NonClientDecorView) {
            if (view instanceof DecorCaptionView) {
                // The decor was most likely saved from a relaunch - so reuse it.
                nonClientDecorView = (NonClientDecorView) view;
                DecorCaptionView = (DecorCaptionView) view;
                removeViewAt(i);
            }
        }
        final WindowManager.LayoutParams attrs = mWindow.getAttributes();
        final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
                attrs.type == TYPE_APPLICATION;
        // Only a non floating application window on one of the allowed workspaces can get a non
        // client decor.
        // Only a non floating application window on one of the allowed workspaces can get a caption
        if (!mWindow.isFloating() && isApplication
                && ActivityManager.StackId.hasWindowDecor(mWorkspaceId)) {
                && ActivityManager.StackId.hasWindowDecor(mStackId)) {
            // Dependent on the brightness of the used title we either use the
            // dark or the light button frame.
            if (nonClientDecorView == null) {
            if (DecorCaptionView == null) {
                Context context = getContext();
                TypedValue value = new TypedValue();
                context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
                inflater = inflater.from(context);
                if (Color.luminance(value.data) < 0.5) {
                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
                            R.layout.non_client_decor_dark, null);
                    DecorCaptionView = (DecorCaptionView) inflater.inflate(
                            R.layout.decor_caption_dark, null);
                } else {
                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
                            R.layout.non_client_decor_light, null);
                    DecorCaptionView = (DecorCaptionView) inflater.inflate(
                            R.layout.decor_caption_light, null);
                }
            }
            nonClientDecorView.setPhoneWindow(mWindow, true /*showDecor*/);
            DecorCaptionView.setPhoneWindow(mWindow, true /*showDecor*/);
        } else {
            nonClientDecorView = null;
            DecorCaptionView = null;
        }

        // Tell the decor if it has a visible non client decor.
        enableNonClientDecor(nonClientDecorView != null);
        return nonClientDecorView;
        // Tell the decor if it has a visible caption.
        enableCaption(DecorCaptionView != null);
        return DecorCaptionView;
    }

    /**
@@ -1670,12 +1649,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    }

    /**
     * Returns the Id of the workspace which contains this window.
     * Note that if no workspace can be determined - which usually means that it was not
     * created for an activity - the fullscreen workspace ID will be returned.
     * @return Returns the workspace stack id which contains this window.
     * Returns the Id of the stack which contains this window.
     * Note that if no stack can be determined - which usually means that it was not
     * created for an activity - the fullscreen stack ID will be returned.
     * @return Returns the stack id which contains this window.
     **/
    private int getWorkspaceId() {
    private int getStackId() {
        int workspaceId = INVALID_STACK_ID;
        final Window.WindowControllerCallback callback = mWindow.getWindowControllerCallback();
        if (callback != null) {
@@ -1692,12 +1671,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    }

    void clearContentView() {
        if (mNonClientDecorView != null) {
            if (mNonClientDecorView.getChildCount() > 1) {
                mNonClientDecorView.removeViewAt(1);
        if (mDecorCaptionView != null) {
            if (mDecorCaptionView.getChildCount() > 1) {
                mDecorCaptionView.removeViewAt(1);
            }
        } else {
            // This window doesn't have non client decor, so we need to just remove the
            // This window doesn't have caption, so we need to just remove the
            // children of the decor view.
            removeAllViews();
        }
@@ -1782,7 +1761,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        final boolean wasAdjustedForStack = mElevationAdjustedForStack;
        // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
        // since the shadow is bound to the content size and not the target size.
        if (ActivityManager.StackId.hasWindowShadow(mWorkspaceId)
        if (ActivityManager.StackId.hasWindowShadow(mStackId)
                && mBackdropFrameRenderer == null) {
            elevation = hasWindowFocus() ?
                    DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
@@ -1806,11 +1785,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
    }

    boolean isShowingCaption() {
        return mNonClientDecorView != null && mNonClientDecorView.isShowingDecor();
        return mDecorCaptionView != null && mDecorCaptionView.isCaptionShowing();
    }

    int getCaptionHeight() {
        return isShowingCaption() ? mNonClientDecorView.getDecorCaptionHeight() : 0;
        return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
    }

    /**
+22 −25
Original line number Diff line number Diff line
@@ -34,8 +34,7 @@ import com.android.internal.policy.PhoneWindow;

/**
 * This class represents the special screen elements to control a window on freeform
 * environment. All these screen elements are added in the "non client area" which is the area of
 * the window which is handled by the OS and not the application.
 * environment.
 * As such this class handles the following things:
 * <ul>
 * <li>The caption, containing the system buttons like maximize, close and such as well as
@@ -46,18 +45,16 @@ import com.android.internal.policy.PhoneWindow;
 * Note: At this time the application can change various attributes of the DecorView which
 * will break things (in settle/unexpected ways):
 * <ul>
 * <li>setElevation</li>
 * <li>setOutlineProvider</li>
 * <li>setSurfaceFormat</li>
 * <li>..</li>
 * </ul>
 * This will be mitigated once b/22527834 will be addressed.
 */
public class NonClientDecorView extends LinearLayout
public class DecorCaptionView extends LinearLayout
        implements View.OnClickListener, View.OnTouchListener {
    private final static String TAG = "NonClientDecorView";
    private final static String TAG = "DecorCaptionView";
    private PhoneWindow mOwner = null;
    private boolean mShowDecor = false;
    private boolean mShow = false;

    // True if the window is being dragged.
    private boolean mDragging = false;
@@ -65,21 +62,21 @@ public class NonClientDecorView extends LinearLayout
    // True when the left mouse button got released while dragging.
    private boolean mLeftMouseButtonReleased;

    public NonClientDecorView(Context context) {
    public DecorCaptionView(Context context) {
        super(context);
    }

    public NonClientDecorView(Context context, AttributeSet attrs) {
    public DecorCaptionView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NonClientDecorView(Context context, AttributeSet attrs, int defStyle) {
    public DecorCaptionView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setPhoneWindow(PhoneWindow owner, boolean showDecor) {
    public void setPhoneWindow(PhoneWindow owner, boolean show) {
        mOwner = owner;
        mShowDecor = showDecor;
        mShow = show;
        updateCaptionVisibility();
        // By changing the outline provider to BOUNDS, the window can remove its
        // background without removing the shadow.
@@ -96,8 +93,8 @@ public class NonClientDecorView extends LinearLayout
        // input device we are listening to.
        switch (e.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                if (!mShowDecor) {
                    // When there is no decor we should not react to anything.
                if (!mShow) {
                    // When there is no caption we should not react to anything.
                    return false;
                }
                // A drag action is started if we aren't dragging already and the starting event is
@@ -136,11 +133,11 @@ public class NonClientDecorView extends LinearLayout
    }

    /**
     * The phone window configuration has changed and the decor needs to be updated.
     * @param showDecor True if the decor should be shown.
     * The phone window configuration has changed and the caption needs to be updated.
     * @param show True if the caption should be shown.
     */
    public void onConfigurationChanged(boolean showDecor) {
        mShowDecor = showDecor;
    public void onConfigurationChanged(boolean show) {
        mShow = show;
        updateCaptionVisibility();
    }

@@ -157,7 +154,7 @@ public class NonClientDecorView extends LinearLayout
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        // Make sure that we never get more then one client area in our view.
        if (index >= 2 || getChildCount() >= 2) {
            throw new IllegalStateException("NonClientDecorView can only handle 1 client view");
            throw new IllegalStateException("DecorCaptionView can only handle 1 client view");
        }
        super.addView(child, index, params);
    }
@@ -176,8 +173,8 @@ public class NonClientDecorView extends LinearLayout
     * Updates the visibility of the caption.
     **/
    private void updateCaptionVisibility() {
        // Don't show the decor if the window has e.g. entered full screen.
        boolean invisible = isFillingScreen() || !mShowDecor;
        // Don't show the caption if the window has e.g. entered full screen.
        boolean invisible = isFillingScreen() || !mShow;
        View caption = getChildAt(0);
        caption.setVisibility(invisible ? GONE : VISIBLE);
        caption.setOnTouchListener(this);
@@ -197,11 +194,11 @@ public class NonClientDecorView extends LinearLayout
        }
    }

    public boolean isShowingDecor() {
        return mShowDecor;
    public boolean isCaptionShowing() {
        return mShow;
    }

    public int getDecorCaptionHeight() {
    public int getCaptionHeight() {
        final View caption = getChildAt(0);
        return (caption != null) ? caption.getHeight() : 0;
    }
+2 −2
Original line number Diff line number Diff line
@@ -16,6 +16,6 @@

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="true"
          android:drawable="@drawable/non_client_decor_title_focused" />
    <item android:drawable="@drawable/non_client_decor_title_unfocused" />
          android:drawable="@drawable/decor_caption_title_focused" />
    <item android:drawable="@drawable/decor_caption_title_unfocused" />
</selector>
Loading