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-2 flags"> 47 <span class="mat-body-1">Flags:</span> 48 &ngsp; 49 {{ properties.flags }} 50 </p> 51 <span *ngFor="let summaryProperty of properties.summary" class="mat-body-2 summary inline"> 52 <span class="mat-body-1" [matTooltip]="summaryProperty.desc" [matTooltipShowDelay]="400">{{ 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 80 class="property mat-body-1" 81 matTooltip="Requested transform multiplied by any parent transforms. 82 Used on calculated crop to generate final bounds.">Transform:</p> 83 <transform-matrix 84 *ngIf="properties.calcTransform?.getAllChildren().length > 0" 85 [matTooltip]="getTransformType(properties.calcTransform)" 86 [matrix]="getTransformMatrix(properties.calcTransform)"></transform-matrix> 87 <p class="mat-body-2 crop"> 88 <span 89 class="mat-body-1" 90 matTooltip="Raw value read from proto.bounds. This is the buffer size or 91 requested crop, cropped by parent bounds.">Crop:</span> 92 &ngsp; 93 {{ properties.calcCrop }} 94 </p> 95 96 <p class="mat-body-2 final-bounds"> 97 <span 98 class="mat-body-1" 99 matTooltip="Raw value read from proto.screenBounds. This is the calculated crop 100 transformed by calculated transform." 101 >Final Bounds:</span 102 > 103 &ngsp; 104 {{ properties.finalBounds }} 105 </p> 106 </div> 107 <div class="right-column"> 108 <p class="column-header mat-small">Requested</p> 109 <p 110 class="property mat-body-1" 111 matTooltip="Transform requested for this layer, not accounting for parent transforms.">Transform:</p> 112 <transform-matrix 113 *ngIf="properties.reqTransform?.getAllChildren().length > 0" 114 [matTooltip]="getTransformType(properties.reqTransform)" 115 [matrix]="getTransformMatrix(properties.reqTransform)"></transform-matrix> 116 </div> 117 </div> 118 119 <mat-divider></mat-divider> 120 121 <div class="group buffer"> 122 <h3 class="group-header mat-subheading-2">Buffer</h3> 123 <div class="left-column"> 124 <p 125 class="mat-body-2 size" 126 matTooltip="Width, height, stride and format of active buffer, if available."> 127 <span class="mat-body-1">Size:</span> 128 &ngsp; 129 {{ properties.bufferSize }} 130 </p> 131 <p class="mat-body-2 frame-number"> 132 <span class="mat-body-1">Frame Number:</span> 133 &ngsp; 134 {{ properties.frameNumber }} 135 </p> 136 <p class="mat-body-2 transform"> 137 <span 138 class="mat-body-1" 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-2 dest-frame"> 150 <span 151 class="mat-body-1" 152 matTooltip="Scales buffer to the frame by overriding the requested transform 153 for this item.">Destination Frame:</span> 154 &ngsp; 155 {{ properties.destinationFrame }} 156 </p> 157 <p *ngIf="properties.ignoreDestinationFrame" class="mat-body-2 ignore-frame"> 158 Destination Frame ignored because item has eIgnoreDestinationFrame flag set. 159 </p> 160 </div> 161 </div> 162 163 <mat-divider></mat-divider> 164 165 <div class="group hierarchy-info"> 166 <h3 class="group-header mat-subheading-2">Hierarchy</h3> 167 <div class="left-column"> 168 <p class="mat-body-2 z-order"> 169 <span class="mat-body-1">Z-order:</span> 170 &ngsp; 171 {{ properties.z }} 172 </p> 173 <p class="mat-body-2 rel-parent inline"> 174 <span 175 class="mat-body-1" 176 matTooltip="Item is z-ordered relative to its relative parents but its bounds 177 and other properties are inherited from its parents." 178 >Relative Parent:</span> 179 &ngsp; 180 <ng-container *ngIf="!properties.relativeParent.nodeId"> 181 {{ properties.relativeParent }} 182 </ng-container> 183 <ng-container *ngIf="properties.relativeParent.nodeId"> 184 <button 185 mat-button 186 color="primary" 187 [matTooltip]="properties.relativeParent.name" 188 (click)="onIdClicked(properties.relativeParent.nodeId)"> 189 {{ properties.relativeParent.layerId }} 190 </button> 191 </ng-container> 192 </p> 193 <span class="mat-body-2 rel-children inline"> 194 <span class="mat-body-1">Relative Children:</span> 195 &ngsp; 196 <ng-container *ngIf="properties.relativeChildren.length === 0"> 197 none 198 </ng-container> 199 <ng-container *ngFor="let layer of properties.relativeChildren; index as i"> 200 <button 201 mat-button 202 color="primary" 203 [matTooltip]="layer.name" 204 (click)="onIdClicked(layer.nodeId)"> 205 {{ layer.layerId }} 206 </button> 207 {{(i === properties.relativeChildren.length - 1) ? '' : ', '}} 208 </ng-container> 209 </span> 210 </div> 211 </div> 212 213 <mat-divider></mat-divider> 214 215 <div class="group effects"> 216 <h3 class="group-header mat-subheading-2">Effects</h3> 217 <div class="left-column"> 218 <p class="column-header mat-small">Calculated</p> 219 <p class="mat-body-2 color"> 220 <span 221 class="mat-body-1" 222 matTooltip="Final color - alpha may be inherited from a parent layer.">Color:</span> 223 &ngsp; 224 {{ properties.calcColor }} 225 </p> 226 <p class="mat-body-2 corner-radius"> 227 <span 228 class="mat-body-1" 229 matTooltip="Final corner radius - may be affected by parent corner radii.">Corner Radius:</span> 230 &ngsp; 231 {{ properties.calcCornerRadius }} 232 </p> 233 <p class="mat-body-2 shadow"> 234 <span class="mat-body-1">Shadow Radius:</span> 235 &ngsp; 236 {{ properties.calcShadowRadius }} 237 </p> 238 <p class="mat-body-2"> 239 <span 240 class="mat-body-1" 241 matTooltip="Crop used to define the bounds of the corner radii. If the bounds 242 are greater than the item bounds then the rounded corner will not 243 be visible." 244 >Corner Radius Crop:</span 245 > 246 &ngsp; 247 {{ properties.calcCornerRadiusCrop }} 248 </p> 249 <p class="mat-body-2 blur"> 250 <span class="mat-body-1">Blur Radius:</span> 251 &ngsp; 252 {{ properties.backgroundBlurRadius }} 253 </p> 254 </div> 255 <div class="right-column"> 256 <p class="column-header mat-small">Requested</p> 257 <p class="mat-body-2"> 258 <span 259 class="mat-body-1" 260 matTooltip="Requested color and alpha for this layer.">Color:</span> 261 &ngsp; 262 {{ properties.reqColor }} 263 </p> 264 <p class="mat-body-2 corner-radius"> 265 <span 266 class="mat-body-1" 267 matTooltip="Requested corner radius not accounting for any parent values.">Corner Radius:</span> 268 &ngsp; 269 {{ properties.reqCornerRadius }} 270 </p> 271 </div> 272 </div> 273 274 <mat-divider></mat-divider> 275 276 <div class="group inputs"> 277 <h3 class="group-header mat-subheading-2">Input</h3> 278 <ng-container *ngIf="properties.hasInputChannel"> 279 <div class="left-column"> 280 <p class="property mat-body-1">To Display Transform:</p> 281 <transform-matrix 282 *ngIf="properties.inputTransform?.getAllChildren().length > 0" 283 [matTooltip]="getTransformType(properties.inputTransform)" 284 [matrix]="getTransformMatrix(properties.inputTransform)"></transform-matrix> 285 <p class="mat-body-2"> 286 <span class="mat-body-1">Touchable Region:</span> 287 &ngsp; 288 {{ properties.inputRegion }} 289 </p> 290 </div> 291 <div class="right-column"> 292 <p class="column-header mat-small">Config</p> 293 <p class="mat-body-2 focusable"> 294 <span class="mat-body-1">Focusable:</span> 295 &ngsp; 296 {{ properties.focusable }} 297 </p> 298 <p class="mat-body-2 crop-touch-region"> 299 <span class="mat-body-1">Crop touch region with item:</span> 300 &ngsp; 301 {{ properties.cropTouchRegionWithItem }} 302 </p> 303 <p class="mat-body-2 replace-touch-region"> 304 <span class="mat-body-1">Replace touch region with crop:</span> 305 &ngsp; 306 {{ properties.replaceTouchRegionWithCrop }} 307 </p> 308 <p class="mat-body-2 input-config"> 309 <span class="mat-body-1">Input Config:</span> 310 &ngsp; 311 {{ properties.inputConfig }} 312 </p> 313 </div> 314 </ng-container> 315 <div *ngIf="!properties.hasInputChannel" class="left-column"> 316 <p class="mat-body-2"> 317 <span class="mat-body-1">Input Channel:</span> 318 &ngsp; not set 319 </p> 320 </div> 321 </div> 322 </div> 323 `, 324 styles: [ 325 ` 326 :host collapsible-section-title { 327 padding-bottom: 8px; 328 } 329 .placeholder-text { 330 padding: 8px 12px; 331 } 332 333 .property-groups-content { 334 overflow-y: auto; 335 padding: 0px 12px; 336 } 337 338 .group { 339 display: flex; 340 flex-direction: row; 341 padding: 8px; 342 } 343 344 .group-header { 345 width: 80px; 346 color: gray; 347 } 348 349 .left-column { 350 flex: 1; 351 padding: 0 5px; 352 } 353 354 .right-column { 355 flex: 1; 356 border: 1px solid var(--border-color); 357 border-left-width: 5px; 358 padding: 0 5px; 359 } 360 361 .column-header { 362 color: gray; 363 } 364 365 .summary { 366 display: block; 367 } 368 `, 369 inlineButtonStyle, 370 viewerCardInnerStyle, 371 ], 372}) 373export class SurfaceFlingerPropertyGroupsComponent { 374 @Input() properties: SfCuratedProperties | undefined; 375 376 @Output() collapseButtonClicked = new EventEmitter(); 377 378 constructor(@Inject(ElementRef) private elementRef: ElementRef) {} 379 380 getTransformType(transformNode: UiPropertyTreeNode): string { 381 const typeFlags = transformNode.formattedValue(); 382 return typeFlags !== 'null' ? typeFlags : 'IDENTITY'; 383 } 384 385 getTransformMatrix(transformNode: UiPropertyTreeNode): UiPropertyTreeNode { 386 return assertDefined(transformNode.getChildByName('matrix')); 387 } 388 389 onIdClicked(layerNodeId: string) { 390 const event = new CustomEvent(ViewerEvents.HighlightedIdChange, { 391 bubbles: true, 392 detail: {id: layerNodeId}, 393 }); 394 this.elementRef.nativeElement.dispatchEvent(event); 395 } 396} 397