blob: d7d335b856be2627fd63c7bdb6ff22f7af9a474d [file] [log] [blame]
/*
* Copyright (C) 2022 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 com.android.wm.shell.pip.phone;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.graphics.Rect;
import com.android.wm.shell.pip.PipBoundsState;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Static utilities to get appropriate {@link PipDoubleTapHelper.PipSizeSpec} on a double tap.
*/
public class PipDoubleTapHelper {
/**
* Should not be instantiated as a stateless class.
*/
private PipDoubleTapHelper() {}
/**
* A constant that represents a pip screen size.
*
* <p>CUSTOM - user resized screen size (by pinching in/out)</p>
* <p>DEFAULT - normal screen size used as default when entering pip mode</p>
* <p>MAX - maximum allowed screen size</p>
*/
@IntDef(value = {
SIZE_SPEC_DEFAULT,
SIZE_SPEC_MAX,
SIZE_SPEC_CUSTOM
})
@Retention(RetentionPolicy.SOURCE)
@interface PipSizeSpec {}
static final int SIZE_SPEC_DEFAULT = 0;
static final int SIZE_SPEC_MAX = 1;
static final int SIZE_SPEC_CUSTOM = 2;
/**
* Returns MAX or DEFAULT {@link PipSizeSpec} to toggle to/from.
*
* <p>Each double tap toggles back and forth between {@code PipSizeSpec.CUSTOM} and
* either {@code PipSizeSpec.MAX} or {@code PipSizeSpec.DEFAULT}. The choice between
* the latter two sizes is determined based on the current state of the pip screen.</p>
*
* @param mPipBoundsState current state of the pip screen
*/
@PipSizeSpec
private static int getMaxOrDefaultPipSizeSpec(@NonNull PipBoundsState mPipBoundsState) {
// determine the average pip screen width
int averageWidth = (mPipBoundsState.getMaxSize().x
+ mPipBoundsState.getMinSize().x) / 2;
// If pip screen width is above average, DEFAULT is the size spec we need to
// toggle to. Otherwise, we choose MAX.
return (mPipBoundsState.getBounds().width() > averageWidth)
? SIZE_SPEC_DEFAULT
: SIZE_SPEC_MAX;
}
/**
* Determines the {@link PipSizeSpec} to toggle to on double tap.
*
* @param mPipBoundsState current state of the pip screen
* @param userResizeBounds latest user resized bounds (by pinching in/out)
* @return pip screen size to switch to
*/
@PipSizeSpec
static int nextSizeSpec(@NonNull PipBoundsState mPipBoundsState,
@NonNull Rect userResizeBounds) {
// is pip screen at its maximum
boolean isScreenMax = mPipBoundsState.getBounds().width()
== mPipBoundsState.getMaxSize().x;
// is pip screen at its normal default size
boolean isScreenDefault = (mPipBoundsState.getBounds().width()
== mPipBoundsState.getNormalBounds().width())
&& (mPipBoundsState.getBounds().height()
== mPipBoundsState.getNormalBounds().height());
// edge case 1
// if user hasn't resized screen yet, i.e. CUSTOM size does not exist yet
// or if user has resized exactly to DEFAULT, then we just want to maximize
if (isScreenDefault
&& userResizeBounds.width() == mPipBoundsState.getNormalBounds().width()) {
return SIZE_SPEC_MAX;
}
// edge case 2
// if user has maximized, then we want to toggle to DEFAULT
if (isScreenMax
&& userResizeBounds.width() == mPipBoundsState.getMaxSize().x) {
return SIZE_SPEC_DEFAULT;
}
// otherwise in general we want to toggle back to user's CUSTOM size
if (isScreenDefault || isScreenMax) {
return SIZE_SPEC_CUSTOM;
}
// if we are currently in user resized CUSTOM size state
// then we toggle either to MAX or DEFAULT depending on the current pip screen state
return getMaxOrDefaultPipSizeSpec(mPipBoundsState);
}
}