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 * Whether the parent frame would have been different if there was no display cutout. 93 */ 94 private boolean mParentFrameWasClippedByDisplayCutout; 95 96 boolean mLastForceReportingResized = false; 97 boolean mForceReportingResized = false; 98 99 private boolean mContentChanged; 100 setFrames(Rect parentFrame, Rect displayFrame)101 public void setFrames(Rect parentFrame, Rect displayFrame) { 102 mParentFrame.set(parentFrame); 103 mDisplayFrame.set(displayFrame); 104 } 105 setParentFrameWasClippedByDisplayCutout( boolean parentFrameWasClippedByDisplayCutout)106 public void setParentFrameWasClippedByDisplayCutout( 107 boolean parentFrameWasClippedByDisplayCutout) { 108 mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout; 109 } 110 parentFrameWasClippedByDisplayCutout()111 boolean parentFrameWasClippedByDisplayCutout() { 112 return mParentFrameWasClippedByDisplayCutout; 113 } 114 115 /** 116 * @return true if the width or height has changed since last updating resizing window. 117 */ didFrameSizeChange()118 boolean didFrameSizeChange() { 119 return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height()); 120 } 121 offsetFrames(int layoutXDiff, int layoutYDiff)122 void offsetFrames(int layoutXDiff, int layoutYDiff) { 123 mFrame.offset(layoutXDiff, layoutYDiff); 124 } 125 126 /** 127 * Updates info about whether the size of the window has changed since last reported. 128 * 129 * @return true if info about size has changed since last reported. 130 */ setReportResizeHints()131 boolean setReportResizeHints() { 132 mLastForceReportingResized |= mForceReportingResized; 133 mFrameSizeChanged |= didFrameSizeChange(); 134 return mLastForceReportingResized || mFrameSizeChanged; 135 } 136 137 /** 138 * @return true if the width or height has changed since last reported to the client. 139 */ isFrameSizeChangeReported()140 boolean isFrameSizeChangeReported() { 141 return mFrameSizeChanged || didFrameSizeChange(); 142 } 143 144 /** 145 * Resets the size changed flags so they're all set to false again. This should be called 146 * after the frames are reported to client. 147 */ clearReportResizeHints()148 void clearReportResizeHints() { 149 mLastForceReportingResized = false; 150 mFrameSizeChanged = false; 151 } 152 153 /** 154 * Clears factors that would cause report-resize. 155 */ onResizeHandled()156 void onResizeHandled() { 157 mForceReportingResized = false; 158 } 159 160 /** 161 * Forces the next layout pass to update the client. 162 */ forceReportingResized()163 void forceReportingResized() { 164 mForceReportingResized = true; 165 } 166 167 /** 168 * Sets whether the content has changed. This means that either the size or parent frame has 169 * changed. 170 */ setContentChanged(boolean contentChanged)171 public void setContentChanged(boolean contentChanged) { 172 mContentChanged = contentChanged; 173 } 174 175 /** 176 * @see #setContentChanged(boolean) 177 */ hasContentChanged()178 boolean hasContentChanged() { 179 return mContentChanged; 180 } 181 dumpDebug(@onNull ProtoOutputStream proto, long fieldId)182 public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) { 183 final long token = proto.start(fieldId); 184 mParentFrame.dumpDebug(proto, PARENT_FRAME); 185 mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME); 186 mContainingFrame.dumpDebug(proto, CONTAINING_FRAME); 187 mFrame.dumpDebug(proto, FRAME); 188 mCompatFrame.dumpDebug(proto, COMPAT_FRAME); 189 proto.end(token); 190 } 191 dump(PrintWriter pw, String prefix)192 public void dump(PrintWriter pw, String prefix) { 193 pw.println(prefix + "Frames: containing=" 194 + mContainingFrame.toShortString(sTmpSB) 195 + " parent=" + mParentFrame.toShortString(sTmpSB) 196 + " display=" + mDisplayFrame.toShortString(sTmpSB)); 197 pw.println(prefix + "mFrame=" + mFrame.toShortString(sTmpSB) 198 + " last=" + mLastFrame.toShortString(sTmpSB)); 199 } 200 getInsetsChangedInfo()201 String getInsetsChangedInfo() { 202 return "forceReportingResized=" + mLastForceReportingResized; 203 } 204 } 205