1 /* 2 * Copyright (C) 2018 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.server.wm; 18 19 import static com.android.server.wm.WindowFramesProto.COMPAT_FRAME; 20 import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME; 21 import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME; 22 import static com.android.server.wm.WindowFramesProto.FRAME; 23 import static com.android.server.wm.WindowFramesProto.PARENT_FRAME; 24 25 import android.annotation.NonNull; 26 import android.graphics.Rect; 27 import android.util.proto.ProtoOutputStream; 28 29 import java.io.PrintWriter; 30 31 /** 32 * Container class for all the window frames that affect how windows are laid out. 33 * 34 * TODO(b/111611553): Investigate which frames are still needed and which are duplicates 35 */ 36 public class WindowFrames { 37 private static final StringBuilder sTmpSB = new StringBuilder(); 38 39 /** 40 * In most cases, this is the area of the entire screen. 41 * 42 * TODO(b/111611553): The name is unclear and most likely should be swapped with 43 * {@link #mDisplayFrame} 44 * TODO(b/111611553): In some cases, it also includes top insets, like for IME. Determine 45 * whether this is still necessary to do. 46 */ 47 public final Rect mParentFrame = new Rect(); 48 49 /** 50 * The entire screen area of the {@link Task} this window is in. Usually equal to the 51 * screen area of the device. 52 * 53 * TODO(b/111611553): The name is unclear and most likely should be swapped with 54 * {@link #mParentFrame} 55 */ 56 public final Rect mDisplayFrame = new Rect(); 57 58 /** 59 * Similar to {@link #mDisplayFrame} 60 * 61 * TODO: Why is this different than mDisplayFrame 62 */ 63 final Rect mContainingFrame = new Rect(); 64 65 /** 66 * "Real" frame that the application sees, in display coordinate space. 67 */ 68 final Rect mFrame = new Rect(); 69 70 /** 71 * The last real frame that was reported to the client. 72 */ 73 final Rect mLastFrame = new Rect(); 74 75 /** 76 * mFrame but relative to the parent container. 77 */ 78 final Rect mRelFrame = new Rect(); 79 80 /** 81 * mLastFrame but relative to the parent container 82 */ 83 final Rect mLastRelFrame = new Rect(); 84 85 private boolean mFrameSizeChanged = false; 86 87 // Frame that is scaled to the application's coordinate space when in 88 // screen size compatibility mode. 89 final Rect mCompatFrame = new Rect(); 90 91 /** 92 * {@code true} if the window frame is a simulated frame and attached to a decor window. 93 */ 94 boolean mIsSimulatingDecorWindow = false; 95 96 /** 97 * Whether the parent frame would have been different if there was no display cutout. 98 */ 99 private boolean mParentFrameWasClippedByDisplayCutout; 100 101 boolean mLastForceReportingResized = false; 102 boolean mForceReportingResized = false; 103 104 private boolean mContentChanged; 105 setFrames(Rect parentFrame, Rect displayFrame)106 public void setFrames(Rect parentFrame, Rect displayFrame) { 107 mParentFrame.set(parentFrame); 108 mDisplayFrame.set(displayFrame); 109 } 110 setParentFrameWasClippedByDisplayCutout( boolean parentFrameWasClippedByDisplayCutout)111 public void setParentFrameWasClippedByDisplayCutout( 112 boolean parentFrameWasClippedByDisplayCutout) { 113 mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout; 114 } 115 parentFrameWasClippedByDisplayCutout()116 boolean parentFrameWasClippedByDisplayCutout() { 117 return mParentFrameWasClippedByDisplayCutout; 118 } 119 120 /** 121 * @return true if the width or height has changed since last updating resizing window. 122 */ didFrameSizeChange()123 boolean didFrameSizeChange() { 124 return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height()); 125 } 126 offsetFrames(int layoutXDiff, int layoutYDiff)127 void offsetFrames(int layoutXDiff, int layoutYDiff) { 128 mFrame.offset(layoutXDiff, layoutYDiff); 129 } 130 131 /** 132 * Updates info about whether the size of the window has changed since last reported. 133 * 134 * @return true if info about size has changed since last reported. 135 */ setReportResizeHints()136 boolean setReportResizeHints() { 137 mLastForceReportingResized |= mForceReportingResized; 138 mFrameSizeChanged |= didFrameSizeChange(); 139 return mLastForceReportingResized || mFrameSizeChanged; 140 } 141 142 /** 143 * @return true if the width or height has changed since last reported to the client. 144 */ isFrameSizeChangeReported()145 boolean isFrameSizeChangeReported() { 146 return mFrameSizeChanged || didFrameSizeChange(); 147 } 148 149 /** 150 * Resets the size changed flags so they're all set to false again. This should be called 151 * after the frames are reported to client. 152 */ clearReportResizeHints()153 void clearReportResizeHints() { 154 mLastForceReportingResized = false; 155 mFrameSizeChanged = false; 156 } 157 158 /** 159 * Clears factors that would cause report-resize. 160 */ onResizeHandled()161 void onResizeHandled() { 162 mForceReportingResized = false; 163 } 164 165 /** 166 * Forces the next layout pass to update the client. 167 */ forceReportingResized()168 void forceReportingResized() { 169 mForceReportingResized = true; 170 } 171 172 /** 173 * Sets whether the content has changed. This means that either the size or parent frame has 174 * changed. 175 */ setContentChanged(boolean contentChanged)176 public void setContentChanged(boolean contentChanged) { 177 mContentChanged = contentChanged; 178 } 179 180 /** 181 * @see #setContentChanged(boolean) 182 */ hasContentChanged()183 boolean hasContentChanged() { 184 return mContentChanged; 185 } 186 dumpDebug(@onNull ProtoOutputStream proto, long fieldId)187 public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) { 188 final long token = proto.start(fieldId); 189 mParentFrame.dumpDebug(proto, PARENT_FRAME); 190 mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME); 191 mContainingFrame.dumpDebug(proto, CONTAINING_FRAME); 192 mFrame.dumpDebug(proto, FRAME); 193 mCompatFrame.dumpDebug(proto, COMPAT_FRAME); 194 proto.end(token); 195 } 196 dump(PrintWriter pw, String prefix)197 public void dump(PrintWriter pw, String prefix) { 198 pw.println(prefix + "Frames: containing=" 199 + mContainingFrame.toShortString(sTmpSB) 200 + " parent=" + mParentFrame.toShortString(sTmpSB) 201 + " display=" + mDisplayFrame.toShortString(sTmpSB)); 202 pw.println(prefix + "mFrame=" + mFrame.toShortString(sTmpSB) 203 + " last=" + mLastFrame.toShortString(sTmpSB)); 204 } 205 getInsetsChangedInfo()206 String getInsetsChangedInfo() { 207 return "forceReportingResized=" + mLastForceReportingResized; 208 } 209 } 210