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

Commit cce89e27 authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Introduce WindowMetrics and WM#getCurrent/MaximumWindowMetrics"

parents 1a585bec f65e022c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -54632,7 +54632,9 @@ package android.view {
  }
  public interface WindowManager extends android.view.ViewManager {
    method @NonNull public default android.view.WindowMetrics getCurrentWindowMetrics();
    method @Deprecated public android.view.Display getDefaultDisplay();
    method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
    method public void removeViewImmediate(android.view.View);
  }
@@ -54801,6 +54803,12 @@ package android.view {
    field @android.view.ViewDebug.ExportedProperty public int y;
  }
  public final class WindowMetrics {
    ctor public WindowMetrics(@NonNull android.util.Size, @NonNull android.view.WindowInsets);
    method @NonNull public android.util.Size getSize();
    method @NonNull public android.view.WindowInsets getWindowInsets();
  }
}
package android.view.accessibility {
+9 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.graphics.Region;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.view.DisplayCutout;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IDockedStackListener;
@@ -739,4 +740,12 @@ interface IWindowManager
     * Called when a remote process modifies insets on a display window container.
     */
    void modifyDisplayWindowInsets(int displayId, in InsetsState state);

    /**
     * Called to get the expected window insets.
     * TODO(window-context): Remove when new insets flag is available.
     */
    void getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
            out Rect outContentInsets, out Rect outStableInsets,
            out DisplayCutout.ParcelableWrapper displayCutout);
}
+43 −0
Original line number Diff line number Diff line
@@ -436,6 +436,49 @@ public interface WindowManager extends ViewManager {
     */
    public void removeViewImmediate(View view);

    /**
     * Returns the {@link WindowMetrics} according to the current system state.
     * <p>
     * The metrics describe the size of the area the window would occupy with
     * {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
     * such a window would have.
     * <p>
     * The value of this is based on the <b>current</b> windowing state of the system.
     *
     * For example, for activities in multi-window mode, the metrics returned are based on the
     * current bounds that the user has selected for the {@link android.app.Activity Activity}'s
     * task.
     *
     * @see #getMaximumWindowMetrics()
     * @see WindowMetrics
     */
    default @NonNull WindowMetrics getCurrentWindowMetrics() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the largets {@link WindowMetrics} an app may expect in the current system state.
     * <p>
     * The metrics describe the size of the largest potential area the window might occupy with
     * {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
     * such a window would have.
     * <p>
     * The value of this is based on the largest <b>potential</b> windowing state of the system.
     *
     * For example, for activities in multi-window mode, the metrics returned are based on the
     * what the bounds would be if the user expanded the {@link android.app.Activity Activity}'s
     * task to cover the entire screen.
     *
     * Note that this might still be smaller than the size of the physical display if certain areas
     * of the display are not available to windows created in this {@link Context}.
     *
     * @see #getMaximumWindowMetrics()
     * @see WindowMetrics
     */
    default @NonNull WindowMetrics getMaximumWindowMetrics() {
        throw new UnsupportedOperationException();
    }

    /**
     * Used to asynchronously request Keyboard Shortcuts from the focused window.
     *
+79 −0
Original line number Diff line number Diff line
@@ -17,12 +17,17 @@
package android.view;

import android.annotation.NonNull;
import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Size;

import com.android.internal.os.IResultReceiver;

@@ -62,6 +67,10 @@ public final class WindowManagerImpl implements WindowManager {

    private IBinder mDefaultToken;

    private boolean mIsViewAdded;
    private View mLastView;
    private WindowManager.LayoutParams mLastParams;

    public WindowManagerImpl(Context context) {
        this(context, null);
    }
@@ -93,6 +102,9 @@ public final class WindowManagerImpl implements WindowManager {
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
        mIsViewAdded = true;
        mLastView = view;
        mLastParams = (WindowManager.LayoutParams) params;
    }

    @Override
@@ -201,4 +213,71 @@ public final class WindowManagerImpl implements WindowManager {
        }
        return false;
    }

    @Override
    public WindowMetrics getCurrentWindowMetrics() {
        final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
        final Rect bound = getCurrentBounds(context);

        return new WindowMetrics(toSize(bound), computeWindowInsets());
    }

    private static Rect getCurrentBounds(Context context) {
        synchronized (ResourcesManager.getInstance()) {
            return context.getResources().getConfiguration().windowConfiguration.getBounds();
        }
    }

    @Override
    public WindowMetrics getMaximumWindowMetrics() {
        return new WindowMetrics(toSize(getMaximumBounds()), computeWindowInsets());
    }

    private Size toSize(Rect frame) {
        return new Size(frame.width(), frame.height());
    }

    private Rect getMaximumBounds() {
        // TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
        //  bound after displayArea feature is finished.
        final Display display = mContext.getDisplay();
        final Point displaySize = new Point();
        display.getRealSize(displaySize);
        return new Rect(0, 0, displaySize.x, displaySize.y);
    }

    private WindowInsets computeWindowInsets() {
        // TODO(window-context): This can only be properly implemented
        //  once we flip the new insets mode flag.
        if (mParentWindow != null) {
            if (mParentWindow.getDecorView().isAttachedToWindow()) {
                return mParentWindow.getDecorView().getViewRootImpl()
                        .getWindowInsets(true /* forceConstruct */);
            }
            return getWindowInsetsFromServer(mParentWindow.getAttributes());
        }
        if (mIsViewAdded) {
            return mLastView.getViewRootImpl().getWindowInsets(true /* forceConstruct */);
        } else {
            return getWindowInsetsFromServer(new WindowManager.LayoutParams());
        }

    }

    private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) {
        try {
            final Rect systemWindowInsets = new Rect();
            final Rect stableInsets = new Rect();
            final DisplayCutout.ParcelableWrapper displayCutout =
                    new DisplayCutout.ParcelableWrapper();
            WindowManagerGlobal.getWindowManagerService().getWindowInsets(attrs,
                    mContext.getDisplayId(), systemWindowInsets, stableInsets, displayCutout);
            return new WindowInsets.Builder()
                    .setSystemWindowInsets(Insets.of(systemWindowInsets))
                    .setStableInsets(Insets.of(stableInsets))
                    .setDisplayCutout(displayCutout.get()).build();
        } catch (RemoteException e) {
        }
        return null;
    }
}
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import android.annotation.NonNull;
import android.util.Size;

/**
 * Metrics about a Window, consisting of the size and {@link WindowInsets}.
 * <p>
 * This is usually obtained from {@link WindowManager#getCurrentWindowMetrics()} and
 * {@link WindowManager#getMaximumWindowMetrics()}.
 *
 * @see WindowInsets#getInsets(int)
 * @see WindowManager#getCurrentWindowMetrics()
 * @see WindowManager#getMaximumWindowMetrics()
 */
public final class WindowMetrics {
    private final @NonNull Size mSize;
    private final @NonNull WindowInsets mWindowInsets;

    public WindowMetrics(@NonNull Size size, @NonNull WindowInsets windowInsets) {
        mSize = size;
        mWindowInsets = windowInsets;
    }

    /**
     * Returns the size of the window.
     *
     * @return window size in pixel.
     */
    public @NonNull Size getSize() {
        return mSize;
    }

    /**
     * Returns the {@link WindowInsets} of the window.
     *
     * @return the {@link WindowInsets} of the window.
     */
    public @NonNull WindowInsets getWindowInsets() {
        return mWindowInsets;
    }
}
Loading