1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.util; 18 19 import static java.lang.annotation.RetentionPolicy.SOURCE; 20 21 import android.graphics.Rect; 22 23 import androidx.annotation.IntDef; 24 25 import java.lang.annotation.Retention; 26 27 public final class SplitConfigurationOptions { 28 29 /////////////////////////////////// 30 // Taken from 31 // frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java 32 /** 33 * Stage position isn't specified normally meaning to use what ever it is currently set to. 34 */ 35 public static final int STAGE_POSITION_UNDEFINED = -1; 36 /** 37 * Specifies that a stage is positioned at the top half of the screen if 38 * in portrait mode or at the left half of the screen if in landscape mode. 39 */ 40 public static final int STAGE_POSITION_TOP_OR_LEFT = 0; 41 42 /** 43 * Specifies that a stage is positioned at the bottom half of the screen if 44 * in portrait mode or at the right half of the screen if in landscape mode. 45 */ 46 public static final int STAGE_POSITION_BOTTOM_OR_RIGHT = 1; 47 48 @Retention(SOURCE) 49 @IntDef({STAGE_POSITION_UNDEFINED, STAGE_POSITION_TOP_OR_LEFT, STAGE_POSITION_BOTTOM_OR_RIGHT}) 50 public @interface StagePosition {} 51 52 /** 53 * Stage type isn't specified normally meaning to use what ever the default is. 54 * E.g. exit split-screen and launch the app in fullscreen. 55 */ 56 public static final int STAGE_TYPE_UNDEFINED = -1; 57 /** 58 * The main stage type. 59 */ 60 public static final int STAGE_TYPE_MAIN = 0; 61 62 /** 63 * The side stage type. 64 */ 65 public static final int STAGE_TYPE_SIDE = 1; 66 67 @IntDef({STAGE_TYPE_UNDEFINED, STAGE_TYPE_MAIN, STAGE_TYPE_SIDE}) 68 public @interface StageType {} 69 /////////////////////////////////// 70 71 /** 72 * Default split ratio for launching app pair from overview. 73 */ 74 public static final float DEFAULT_SPLIT_RATIO = 0.5f; 75 76 public static class SplitPositionOption { 77 public final int iconResId; 78 public final int textResId; 79 @StagePosition 80 public final int stagePosition; 81 82 @StageType 83 public final int mStageType; 84 SplitPositionOption(int iconResId, int textResId, int stagePosition, int stageType)85 public SplitPositionOption(int iconResId, int textResId, int stagePosition, int stageType) { 86 this.iconResId = iconResId; 87 this.textResId = textResId; 88 this.stagePosition = stagePosition; 89 mStageType = stageType; 90 } 91 } 92 93 /** 94 * NOTE: Engineers complained about too little ambiguity in the last survey, so there is a class 95 * with the same name/functionality in wm.shell.util (which launcher3 cannot be built against) 96 * 97 * If you make changes here, consider making the same changes there 98 */ 99 public static class StagedSplitBounds { 100 public final Rect leftTopBounds; 101 public final Rect rightBottomBounds; 102 /** This rect represents the actual gap between the two apps */ 103 public final Rect visualDividerBounds; 104 // This class is orientation-agnostic, so we compute both for later use 105 public final float topTaskPercent; 106 public final float leftTaskPercent; 107 public final float dividerWidthPercent; 108 public final float dividerHeightPercent; 109 /** 110 * If {@code true}, that means at the time of creation of this object, the 111 * split-screened apps were vertically stacked. This is useful in scenarios like 112 * rotation where the bounds won't change, but this variable can indicate what orientation 113 * the bounds were originally in 114 */ 115 public final boolean appsStackedVertically; 116 public final int leftTopTaskId; 117 public final int rightBottomTaskId; 118 StagedSplitBounds(Rect leftTopBounds, Rect rightBottomBounds, int leftTopTaskId, int rightBottomTaskId)119 public StagedSplitBounds(Rect leftTopBounds, Rect rightBottomBounds, int leftTopTaskId, 120 int rightBottomTaskId) { 121 this.leftTopBounds = leftTopBounds; 122 this.rightBottomBounds = rightBottomBounds; 123 this.leftTopTaskId = leftTopTaskId; 124 this.rightBottomTaskId = rightBottomTaskId; 125 126 if (rightBottomBounds.top > leftTopBounds.top) { 127 // vertical apps, horizontal divider 128 this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom, 129 leftTopBounds.right, rightBottomBounds.top); 130 appsStackedVertically = true; 131 } else { 132 // horizontal apps, vertical divider 133 this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top, 134 rightBottomBounds.left, leftTopBounds.bottom); 135 appsStackedVertically = false; 136 } 137 138 leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right; 139 topTaskPercent = this.leftTopBounds.height() / (float) rightBottomBounds.bottom; 140 dividerWidthPercent = visualDividerBounds.width() / (float) rightBottomBounds.right; 141 dividerHeightPercent = visualDividerBounds.height() / (float) rightBottomBounds.bottom; 142 } 143 } 144 145 public static class StagedSplitTaskPosition { 146 public int taskId = -1; 147 @StagePosition 148 public int stagePosition = STAGE_POSITION_UNDEFINED; 149 @StageType 150 public int stageType = STAGE_TYPE_UNDEFINED; 151 } 152 } 153