1/* 2 * Copyright (C) 2022 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 {Component, ElementRef, Inject, Input} from '@angular/core'; 17import {ImeAdditionalProperties} from 'viewers/common/ime_additional_properties'; 18import {UiTreeUtils} from 'viewers/common/ui_tree_utils'; 19import {ViewerEvents} from 'viewers/common/viewer_events'; 20 21@Component({ 22 selector: 'ime-additional-properties', 23 template: ` 24 <h2 class="view-header mat-title">WM & SF Properties</h2> 25 <div class="additional-properties-content"> 26 <div *ngIf="isAllPropertiesNull()" class="group"> 27 <p class="mat-body-1"> 28 There is no corresponding WM / SF additionalProperties for this IME entry – no WM / SF 29 entry is recorded before this IME entry in time. View later frames for WM & SF properties. 30 </p> 31 </div> 32 33 <ng-container *ngIf="isImeManagerService"> 34 <div class="group"> 35 <button 36 *ngIf="wmProtoOrNull()" 37 color="primary" 38 mat-button 39 class="group-header" 40 [class]="{selected: isHighlighted(wmProtoOrNull())}" 41 (click)="onClickShowInPropertiesPanel(wmProtoOrNull(), additionalProperties.wm?.name)"> 42 WMState 43 </button> 44 <h3 *ngIf="!wmProtoOrNull()" class="group-header mat-subheading-2">WMState</h3> 45 <div class="left-column"> 46 <p *ngIf="additionalProperties.wm" class="mat-body-1"> 47 {{ additionalProperties.wm.name }} 48 </p> 49 <p *ngIf="!additionalProperties.wm" class="mat-body-1"> 50 There is no corresponding WMState entry. 51 </p> 52 </div> 53 </div> 54 <div *ngIf="wmInsetsSourceProviderOrNull()" class="group"> 55 <button 56 color="primary" 57 mat-button 58 class="group-header" 59 [class]="{selected: isHighlighted(wmInsetsSourceProviderOrNull())}" 60 (click)=" 61 onClickShowInPropertiesPanel( 62 wmInsetsSourceProviderOrNull(), 63 'Ime Insets Source Provider' 64 ) 65 "> 66 IME Insets Source Provider 67 </button> 68 <div class="left-column"> 69 <p class="mat-body-2">Source Frame:</p> 70 <coordinates-table 71 [coordinates]="wmInsetsSourceProviderSourceFrameOrNull()"></coordinates-table> 72 <p class="mat-body-1"> 73 <span class="mat-body-2">Source Visible:</span> 74 &ngsp; 75 {{ wmInsetsSourceProviderSourceVisibleOrNull() }} 76 </p> 77 <p class="mat-body-2">Source Visible Frame:</p> 78 <coordinates-table 79 [coordinates]="wmInsetsSourceProviderSourceVisibleFrameOrNull()"></coordinates-table> 80 <p class="mat-body-1"> 81 <span class="mat-body-2">Position:</span> 82 &ngsp; 83 {{ wmInsetsSourceProviderPositionOrNull() }} 84 </p> 85 <p class="mat-body-1"> 86 <span class="mat-body-2">IsLeashReadyForDispatching:</span> 87 &ngsp; 88 {{ wmInsetsSourceProviderIsLeashReadyOrNull() }} 89 </p> 90 <p class="mat-body-1"> 91 <span class="mat-body-2">Controllable:</span> 92 &ngsp; 93 {{ wmInsetsSourceProviderControllableOrNull() }} 94 </p> 95 </div> 96 </div> 97 <div *ngIf="wmImeControlTargetOrNull()" class="group"> 98 <button 99 color="primary" 100 mat-button 101 class="group-header" 102 [class]="{selected: isHighlighted(wmImeControlTargetOrNull())}" 103 (click)=" 104 onClickShowInPropertiesPanel(wmImeControlTargetOrNull(), 'Ime Control Target') 105 "> 106 IME Control Target 107 </button> 108 <div class="left-column"> 109 <p *ngIf="wmImeControlTargetTitleOrNull()" class="mat-body-1"> 110 <span class="mat-body-2">Title:</span> 111 &ngsp; 112 {{ wmImeControlTargetTitleOrNull() }} 113 </p> 114 </div> 115 </div> 116 <div *ngIf="wmImeInputTargetOrNull()" class="group"> 117 <button 118 color="primary" 119 mat-button 120 class="group-header" 121 [class]="{selected: isHighlighted(wmImeInputTargetOrNull())}" 122 (click)="onClickShowInPropertiesPanel(wmImeInputTargetOrNull(), 'Ime Input Target')"> 123 IME Input Target 124 </button> 125 <div class="left-column"> 126 <p *ngIf="wmImeInputTargetTitleOrNull()" class="mat-body-1"> 127 <span class="mat-body-2">Title:</span> 128 &ngsp; 129 {{ wmImeInputTargetTitleOrNull() }} 130 </p> 131 </div> 132 </div> 133 <div *ngIf="wmImeLayeringTargetOrNull()" class="group"> 134 <button 135 color="primary" 136 mat-button 137 class="group-header" 138 [class]="{selected: isHighlighted(wmImeLayeringTargetOrNull())}" 139 (click)=" 140 onClickShowInPropertiesPanel(wmImeLayeringTargetOrNull(), 'Ime Layering Target') 141 "> 142 IME Layering Target 143 </button> 144 <div class="left-column"> 145 <p *ngIf="wmImeLayeringTargetTitleOrNull()" class="mat-body-1"> 146 <span class="mat-body-2">Title:</span> 147 &ngsp; 148 {{ wmImeLayeringTargetTitleOrNull() }} 149 </p> 150 </div> 151 </div> 152 </ng-container> 153 154 <ng-container *ngIf="!isImeManagerService"> 155 <!-- Ime Client or Ime Service --> 156 <div class="group"> 157 <button 158 *ngIf="wmProtoOrNull()" 159 color="primary" 160 mat-button 161 class="group-header" 162 [class]="{selected: isHighlighted(wmProtoOrNull())}" 163 (click)="onClickShowInPropertiesPanel(wmProtoOrNull(), additionalProperties.wm?.name)"> 164 WMState 165 </button> 166 <h3 *ngIf="!wmProtoOrNull()" class="group-header mat-subheading-2">WMState</h3> 167 <div class="left-column"> 168 <p *ngIf="additionalProperties.wm" class="mat-body-1"> 169 {{ additionalProperties.wm.name }} 170 </p> 171 <p *ngIf="!additionalProperties.wm" class="mat-body-1"> 172 There is no corresponding WMState entry. 173 </p> 174 </div> 175 </div> 176 <div class="group"> 177 <h3 class="group-header mat-subheading-2">SFLayer</h3> 178 <div class="left-column"> 179 <p *ngIf="additionalProperties.sf" class="mat-body-1"> 180 {{ additionalProperties.sf.name }} 181 </p> 182 <p *ngIf="!additionalProperties.sf" class="mat-body-1"> 183 There is no corresponding SFLayer entry. 184 </p> 185 </div> 186 </div> 187 <div *ngIf="additionalProperties.wm" class="group"> 188 <h3 class="group-header mat-subheading-2">Focus</h3> 189 <div class="left-column"> 190 <p class="mat-body-1"> 191 <span class="mat-body-2">Focused App:</span> 192 &ngsp; 193 {{ additionalProperties.wm.focusedApp }} 194 </p> 195 <p class="mat-body-1"> 196 <span class="mat-body-2">Focused Activity:</span> 197 &ngsp; 198 {{ additionalProperties.wm.focusedActivity }} 199 </p> 200 <p class="mat-body-1"> 201 <span class="mat-body-2">Focused Window:</span> 202 &ngsp; 203 {{ additionalProperties.wm.focusedWindow }} 204 </p> 205 <p *ngIf="additionalProperties.sf" class="mat-body-1"> 206 <span class="mat-body-2">Focused Window Color:</span> 207 &ngsp; 208 {{ additionalProperties.sf.focusedWindow?.color }} 209 </p> 210 <p class="mat-body-2">Input Control Target Frame:</p> 211 <coordinates-table [coordinates]="wmControlTargetFrameOrNull()"></coordinates-table> 212 </div> 213 </div> 214 <div class="group"> 215 <h3 class="group-header mat-subheading-2">Visibility</h3> 216 <div class="left-column"> 217 <p *ngIf="additionalProperties.wm" class="mat-body-1"> 218 <span class="mat-body-2">InputMethod Window:</span> 219 &ngsp; 220 {{ additionalProperties.wm.isInputMethodWindowVisible }} 221 </p> 222 <p *ngIf="additionalProperties.sf" class="mat-body-1"> 223 <span class="mat-body-2">InputMethod Surface:</span> 224 &ngsp; 225 {{ additionalProperties.sf.inputMethodSurface?.isInputMethodSurfaceVisible ?? false }} 226 </p> 227 </div> 228 </div> 229 <div *ngIf="additionalProperties.sf" class="group"> 230 <button 231 color="primary" 232 mat-button 233 class="group-header" 234 [class]="{selected: isHighlighted(additionalProperties.sf.imeContainer)}" 235 (click)="onClickShowInPropertiesPanel(additionalProperties.sf.imeContainer)"> 236 Ime Container 237 </button> 238 <div class="left-column"> 239 <p class="mat-body-1"> 240 <span class="mat-body-2">ZOrderRelativeOfId:</span> 241 &ngsp; 242 {{ additionalProperties.sf.imeContainer.zOrderRelativeOfId }} 243 </p> 244 <p class="mat-body-1"> 245 <span class="mat-body-2">Z:</span> 246 &ngsp; 247 {{ additionalProperties.sf.imeContainer.z }} 248 </p> 249 </div> 250 </div> 251 <div *ngIf="additionalProperties.sf" class="group"> 252 <button 253 color="primary" 254 mat-button 255 class="group-header" 256 [class]="{selected: isHighlighted(additionalProperties.sf.inputMethodSurface)}" 257 (click)="onClickShowInPropertiesPanel(additionalProperties.sf.inputMethodSurface)"> 258 Input Method Surface 259 </button> 260 <div class="left-column"> 261 <p class="mat-body-2">ScreenBounds:</p> 262 <coordinates-table 263 [coordinates]="sfImeContainerScreenBoundsOrNull()"></coordinates-table> 264 </div> 265 <div class="right-column"> 266 <p class="mat-body-2">Rect:</p> 267 <coordinates-table [coordinates]="sfImeContainerRectOrNull()"></coordinates-table> 268 </div> 269 </div> 270 </ng-container> 271 </div> 272 `, 273 styles: [ 274 ` 275 .view-header { 276 border-bottom: 1px solid var(--border-color); 277 } 278 279 .additional-properties-content { 280 height: 0; 281 flex-grow: 1; 282 overflow-y: auto; 283 } 284 285 .group { 286 padding: 8px; 287 display: flex; 288 flex-direction: row; 289 border-bottom: 1px solid var(--border-color); 290 } 291 292 .mat-body-1 { 293 overflow-wrap: anywhere; 294 } 295 296 .group-header { 297 height: 100%; 298 width: 80px; 299 padding: 0; 300 text-align: center; 301 line-height: normal; 302 white-space: normal; 303 } 304 305 p.group-header { 306 color: gray; 307 } 308 309 .left-column { 310 flex: 1; 311 padding: 0 5px; 312 } 313 314 .right-column { 315 flex: 1; 316 padding: 0 5px; 317 } 318 `, 319 ], 320}) 321export class ImeAdditionalPropertiesComponent { 322 @Input() additionalProperties!: ImeAdditionalProperties; 323 @Input() isImeManagerService?: boolean; 324 @Input() highlightedItems: string[] = []; 325 326 constructor(@Inject(ElementRef) private elementRef: ElementRef) {} 327 328 isHighlighted(item: any) { 329 return UiTreeUtils.isHighlighted(item, this.highlightedItems); 330 } 331 332 formatProto(item: any) { 333 if (item?.prettyPrint) { 334 return item.prettyPrint(); 335 } 336 } 337 338 wmProtoOrNull() { 339 return this.additionalProperties.wm?.proto; 340 } 341 342 wmInsetsSourceProviderOrNull() { 343 return this.additionalProperties.wm?.protoImeInsetsSourceProvider 344 ? Object.assign( 345 {name: 'Ime Insets Source Provider'}, 346 this.additionalProperties.wm.protoImeInsetsSourceProvider 347 ) 348 : null; 349 } 350 351 wmControlTargetFrameOrNull() { 352 return ( 353 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider 354 ?.controlTarget?.windowFrames?.frame || 'null' 355 ); 356 } 357 358 wmInsetsSourceProviderPositionOrNull() { 359 return ( 360 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.control 361 ?.position || 'null' 362 ); 363 } 364 365 wmInsetsSourceProviderIsLeashReadyOrNull() { 366 return ( 367 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider 368 ?.isLeashReadyForDispatching || 'null' 369 ); 370 } 371 372 wmInsetsSourceProviderControllableOrNull() { 373 return ( 374 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider 375 ?.controllable || 'null' 376 ); 377 } 378 379 wmInsetsSourceProviderSourceFrameOrNull() { 380 return ( 381 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source 382 ?.frame || 'null' 383 ); 384 } 385 386 wmInsetsSourceProviderSourceVisibleOrNull() { 387 return ( 388 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source 389 ?.visible || 'null' 390 ); 391 } 392 393 wmInsetsSourceProviderSourceVisibleFrameOrNull() { 394 return ( 395 this.additionalProperties.wm?.protoImeInsetsSourceProvider?.insetsSourceProvider?.source 396 ?.visibleFrame || 'null' 397 ); 398 } 399 400 wmImeControlTargetOrNull() { 401 return this.additionalProperties?.wm?.protoImeControlTarget 402 ? Object.assign( 403 {name: 'IME Control Target'}, 404 this.additionalProperties.wm.protoImeControlTarget 405 ) 406 : null; 407 } 408 409 wmImeControlTargetTitleOrNull() { 410 return ( 411 this.additionalProperties?.wm?.protoImeControlTarget?.windowContainer?.identifier?.title || 412 'null' 413 ); 414 } 415 416 wmImeInputTargetOrNull() { 417 return this.additionalProperties?.wm?.protoImeInputTarget 418 ? Object.assign({name: 'IME Input Target'}, this.additionalProperties.wm.protoImeInputTarget) 419 : null; 420 } 421 422 wmImeInputTargetTitleOrNull() { 423 return ( 424 this.additionalProperties?.wm?.protoImeInputTarget?.windowContainer?.identifier?.title || 425 'null' 426 ); 427 } 428 wmImeLayeringTargetOrNull() { 429 return this.additionalProperties?.wm?.protoImeLayeringTarget 430 ? Object.assign( 431 {name: 'IME Layering Target'}, 432 this.additionalProperties.wm.protoImeLayeringTarget 433 ) 434 : null; 435 } 436 437 wmImeLayeringTargetTitleOrNull() { 438 return ( 439 this.additionalProperties?.wm?.protoImeLayeringTarget?.windowContainer?.identifier?.title || 440 'null' 441 ); 442 } 443 444 sfImeContainerScreenBoundsOrNull() { 445 return this.additionalProperties.sf?.inputMethodSurface?.screenBounds || 'null'; 446 } 447 448 sfImeContainerRectOrNull() { 449 return this.additionalProperties.sf?.inputMethodSurface?.rect || 'null'; 450 } 451 452 isAllPropertiesNull() { 453 if (this.isImeManagerService) { 454 return !this.additionalProperties.wm; 455 } else { 456 return !(this.additionalProperties.wm || this.additionalProperties.sf); 457 } 458 } 459 460 onClickShowInPropertiesPanel(item: any, name?: string) { 461 if (item.id) { 462 this.updateHighlightedItems(item.id); 463 } else { 464 this.updateAdditionalPropertySelected(item, name); 465 } 466 } 467 468 private updateHighlightedItems(newId: string) { 469 const event: CustomEvent = new CustomEvent(ViewerEvents.HighlightedChange, { 470 bubbles: true, 471 detail: {id: newId}, 472 }); 473 this.elementRef.nativeElement.dispatchEvent(event); 474 } 475 476 private updateAdditionalPropertySelected(item: any, name?: string) { 477 const itemWrapper = { 478 name, 479 proto: item, 480 }; 481 const event: CustomEvent = new CustomEvent(ViewerEvents.AdditionalPropertySelected, { 482 bubbles: true, 483 detail: {selectedItem: itemWrapper}, 484 }); 485 this.elementRef.nativeElement.dispatchEvent(event); 486 } 487} 488