1/* 2 * Copyright (C) 2024 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 */ 16import { 17 Component, 18 ElementRef, 19 EventEmitter, 20 Inject, 21 Input, 22 Output, 23} from '@angular/core'; 24import {assertDefined} from 'common/assert_utils'; 25import {SfCuratedProperties} from 'viewers/common/curated_properties'; 26import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node'; 27import {ViewerEvents} from 'viewers/common/viewer_events'; 28import {inlineButtonStyle} from './styles/clickable_property.styles'; 29import {viewerCardInnerStyle} from './styles/viewer_card.styles'; 30 31@Component({ 32 selector: 'surface-flinger-property-groups', 33 template: ` 34 <div class="title-section"> 35 <collapsible-section-title 36 title="PROPERTIES" 37 (collapseButtonClicked)="collapseButtonClicked.emit()"></collapsible-section-title> 38 </div> 39 40 <span class="mat-body-1 placeholder-text" *ngIf="!properties"> Layer not selected. </span> 41 42 <div class="property-groups-content" *ngIf="properties"> 43 <div class="group"> 44 <h3 class="group-header mat-subheading-2">Visibility</h3> 45 <div class="left-column"> 46 <p class="mat-body-1 flags"> 47 <span class="mat-body-2">Flags:</span> 48 &ngsp; 49 {{ properties.flags }} 50 </p> 51 <span *ngFor="let summaryProperty of properties.summary" class="mat-body-1 summary inline"> 52 <span class="mat-body-2">{{ summaryProperty.key }}:</span> 53 <ng-container *ngIf="summaryProperty.simpleValue"> 54 {{ summaryProperty.simpleValue }} 55 </ng-container> 56 <ng-container *ngIf="summaryProperty.layerValues"> 57 &ngsp; 58 <ng-container *ngFor="let layer of summaryProperty.layerValues; index as i"> 59 <button 60 mat-button 61 color="primary" 62 [matTooltip]="layer.name" 63 (click)="onIdClicked(layer.nodeId)"> 64 {{ layer.layerId }} 65 </button> 66 {{(i === summaryProperty.layerValues.length - 1) ? '' : ', '}} 67 </ng-container> 68 </ng-container> 69 </span> 70 </div> 71 </div> 72 73 <mat-divider></mat-divider> 74 75 <div class="group geometry"> 76 <h3 class="group-header mat-subheading-2">Geometry</h3> 77 <div class="left-column"> 78 <p class="column-header mat-small">Calculated</p> 79 <p class="property mat-body-2">Transform:</p> 80 <transform-matrix 81 *ngIf="properties.calcTransform?.getAllChildren().length > 0" 82 [matTooltip]="getTransformType(properties.calcTransform)" 83 [matrix]="getTransformMatrix(properties.calcTransform)"></transform-matrix> 84 <p class="mat-body-1 crop"> 85 <span 86 class="mat-body-2" 87 matTooltip="Raw value read from proto.bounds. This is the buffer size or 88 requested crop cropped by parent bounds." 89 >Crop:</span 90 > 91 &ngsp; 92 {{ properties.calcCrop }} 93 </p> 94 95 <p class="mat-body-1 final-bounds"> 96 <span 97 class="mat-body-2" 98 matTooltip="Raw value read from proto.screenBounds. This is the calculated crop 99 transformed." 100 >Final Bounds:</span 101 > 102 &ngsp; 103 {{ properties.finalBounds }} 104 </p> 105 </div> 106 <div class="right-column"> 107 <p class="column-header mat-small">Requested</p> 108 <p class="property mat-body-2">Transform:</p> 109 <transform-matrix 110 *ngIf="properties.reqTransform?.getAllChildren().length > 0" 111 [matTooltip]="getTransformType(properties.reqTransform)" 112 [matrix]="getTransformMatrix(properties.reqTransform)"></transform-matrix> 113 <p class="mat-body-1 crop"> 114 <span class="mat-body-2">Crop:</span> 115 &ngsp; 116 {{ properties.reqCrop }} 117 </p> 118 </div> 119 </div> 120 121 <mat-divider></mat-divider> 122 123 <div class="group buffer"> 124 <h3 class="group-header mat-subheading-2">Buffer</h3> 125 <div class="left-column"> 126 <p class="mat-body-1 size"> 127 <span class="mat-body-2">Size:</span> 128 &ngsp; 129 {{ properties.bufferSize }} 130 </p> 131 <p class="mat-body-1 frame-number"> 132 <span class="mat-body-2">Frame Number:</span> 133 &ngsp; 134 {{ properties.frameNumber }} 135 </p> 136 <p class="mat-body-1 transform"> 137 <span 138 class="mat-body-2" 139 matTooltip="Rotates or flips the buffer in place. Used with display transform 140 hint to cancel out any buffer transformation when sending to 141 HWC." 142 >Transform:</span 143 > 144 &ngsp; 145 {{ properties.bufferTransformType }} 146 </p> 147 </div> 148 <div class="right-column"> 149 <p class="mat-body-1 dest-frame"> 150 <span 151 class="mat-body-2" 152 matTooltip="Scales buffer to the frame by overriding the requested transform 153 for this item." 154 >Destination Frame:</span 155 > 156 &ngsp; 157 {{ properties.destinationFrame }} 158 </p> 159 <p *ngIf="properties.ignoreDestinationFrame" class="mat-body-1 ignore-frame"> 160 Destination Frame ignored because item has eIgnoreDestinationFrame flag set. 161 </p> 162 </div> 163 </div> 164 165 <mat-divider></mat-divider> 166 167 <div class="group hierarchy-info"> 168 <h3 class="group-header mat-subheading-2">Hierarchy</h3> 169 <div class="left-column"> 170 <p class="mat-body-1 z-order"> 171 <span class="mat-body-2">z-order:</span> 172 &ngsp; 173 {{ properties.z }} 174 </p> 175 <p class="mat-body-1 rel-parent"> 176 <span 177 class="mat-body-2" 178 matTooltip="item is z-ordered relative to its relative parents but its bounds 179 and other properties are inherited from its parents." 180 >relative parent:</span 181 > 182 &ngsp; 183 {{ properties.relativeParent }} 184 </p> 185 </div> 186 </div> 187 188 <mat-divider></mat-divider> 189 190 <div class="group effects"> 191 <h3 class="group-header mat-subheading-2">Effects</h3> 192 <div class="left-column"> 193 <p class="column-header mat-small">Calculated</p> 194 <p class="mat-body-1 color"> 195 <span class="mat-body-2">Color:</span> 196 &ngsp; 197 {{ properties.calcColor }} 198 </p> 199 <p class="mat-body-1 corner-radius"> 200 <span class="mat-body-2">Corner Radius:</span> 201 &ngsp; 202 {{ properties.calcCornerRadius }} 203 </p> 204 <p class="mat-body-1 shadow"> 205 <span class="mat-body-2">Shadow:</span> 206 &ngsp; 207 {{ properties.calcShadowRadius }} 208 </p> 209 <p class="mat-body-1"> 210 <span 211 class="mat-body-2" 212 matTooltip="Crop used to define the bounds of the corner radii. If the bounds 213 are greater than the item bounds then the rounded corner will not 214 be visible." 215 >Corner Radius Crop:</span 216 > 217 &ngsp; 218 {{ properties.calcCornerRadiusCrop }} 219 </p> 220 <p class="mat-body-1 blur"> 221 <span class="mat-body-2">Blur:</span> 222 &ngsp; 223 {{ properties.backgroundBlurRadius }} 224 </p> 225 </div> 226 <div class="right-column"> 227 <p class="column-header mat-small">Requested</p> 228 <p class="mat-body-1"> 229 <span class="mat-body-2">Color:</span> 230 &ngsp; 231 {{ properties.reqColor }} 232 </p> 233 <p class="mat-body-1 corner-radius"> 234 <span class="mat-body-2">Corner Radius:</span> 235 &ngsp; 236 {{ properties.reqCornerRadius }} 237 </p> 238 </div> 239 </div> 240 241 <mat-divider></mat-divider> 242 243 <div class="group inputs"> 244 <h3 class="group-header mat-subheading-2">Input</h3> 245 <ng-container *ngIf="properties.hasInputChannel"> 246 <div class="left-column"> 247 <p class="property mat-body-2">To Display Transform:</p> 248 <transform-matrix 249 *ngIf="properties.inputTransform?.getAllChildren().length > 0" 250 [matTooltip]="getTransformType(properties.inputTransform)" 251 [matrix]="getTransformMatrix(properties.inputTransform)"></transform-matrix> 252 <p class="mat-body-1"> 253 <span class="mat-body-2">Touchable Region:</span> 254 &ngsp; 255 {{ properties.inputRegion }} 256 </p> 257 </div> 258 <div class="right-column"> 259 <p class="column-header mat-small">Config</p> 260 <p class="mat-body-1 focusable"> 261 <span class="mat-body-2">Focusable:</span> 262 &ngsp; 263 {{ properties.focusable }} 264 </p> 265 <p class="mat-body-1 crop-touch-region"> 266 <span class="mat-body-2">Crop touch region with item:</span> 267 &ngsp; 268 {{ properties.cropTouchRegionWithItem }} 269 </p> 270 <p class="mat-body-1 replace-touch-region"> 271 <span class="mat-body-2">Replace touch region with crop:</span> 272 &ngsp; 273 {{ properties.replaceTouchRegionWithCrop }} 274 </p> 275 <p class="mat-body-1 input-config"> 276 <span class="mat-body-2">Input Config:</span> 277 &ngsp; 278 {{ properties.inputConfig }} 279 </p> 280 </div> 281 </ng-container> 282 <div *ngIf="!properties.hasInputChannel" class="left-column"> 283 <p class="mat-body-1"> 284 <span class="mat-body-2">Input channel:</span> 285 &ngsp; not set 286 </p> 287 </div> 288 </div> 289 </div> 290 `, 291 styles: [ 292 ` 293 :host collapsible-section-title { 294 padding-bottom: 8px; 295 } 296 .placeholder-text { 297 padding: 8px 12px; 298 } 299 300 .property-groups-content { 301 overflow-y: auto; 302 padding: 0px 12px; 303 } 304 305 .group { 306 display: flex; 307 flex-direction: row; 308 padding: 8px; 309 } 310 311 .group-header { 312 width: 80px; 313 color: gray; 314 } 315 316 .left-column { 317 flex: 1; 318 padding: 0 5px; 319 } 320 321 .right-column { 322 flex: 1; 323 border: 1px solid var(--border-color); 324 border-left-width: 5px; 325 padding: 0 5px; 326 } 327 328 .column-header { 329 color: gray; 330 } 331 332 .summary { 333 display: block; 334 } 335 `, 336 inlineButtonStyle, 337 viewerCardInnerStyle, 338 ], 339}) 340export class SurfaceFlingerPropertyGroupsComponent { 341 @Input() properties: SfCuratedProperties | undefined; 342 343 @Output() collapseButtonClicked = new EventEmitter(); 344 345 constructor(@Inject(ElementRef) private elementRef: ElementRef) {} 346 347 getTransformType(transformNode: UiPropertyTreeNode): string { 348 const typeFlags = transformNode.formattedValue(); 349 return typeFlags !== 'null' ? typeFlags : 'IDENTITY'; 350 } 351 352 getTransformMatrix(transformNode: UiPropertyTreeNode): UiPropertyTreeNode { 353 return assertDefined(transformNode.getChildByName('matrix')); 354 } 355 356 onIdClicked(layerNodeId: string) { 357 const event = new CustomEvent(ViewerEvents.HighlightedIdChange, { 358 bubbles: true, 359 detail: {id: layerNodeId}, 360 }); 361 this.elementRef.nativeElement.dispatchEvent(event); 362 } 363} 364