• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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