• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { SpSystemTrace } from './SpSystemTrace';
17import { ThreadStruct, ThreadStructOnClick } from '../database/ui-worker/ProcedureWorkerThread';
18import { TraceRow } from './trace/base/TraceRow';
19import { JankStruct, JankStructOnClick } from '../database/ui-worker/ProcedureWorkerJank';
20import { HeapSnapshotStruct, HeapSnapshotStructOnClick } from '../database/ui-worker/ProcedureWorkerHeapSnapshot';
21import { FuncStruct, funcStructOnClick } from '../database/ui-worker/ProcedureWorkerFunc';
22import { CpuFreqStruct, CpuFreqStructOnClick } from '../database/ui-worker/ProcedureWorkerFreq';
23import { ClockStruct, ClockStructOnClick } from '../database/ui-worker/ProcedureWorkerClock';
24import { DmaFenceStruct, DmaFenceStructOnClick } from '../database/ui-worker/ProcedureWorkerDmaFence';
25import { SnapshotStruct, SnapshotStructOnClick } from '../database/ui-worker/ProcedureWorkerSnapshot';
26import { IrqStruct, IrqStructOnClick } from '../database/ui-worker/ProcedureWorkerIrq';
27import { HeapStruct, HeapStructOnClick } from '../database/ui-worker/ProcedureWorkerHeap';
28import { JsCpuProfilerStruct, JsCpuProfilerStructOnClick } from '../database/ui-worker/ProcedureWorkerCpuProfiler';
29import { AppStartupStruct, AppStartupStructOnClick } from '../database/ui-worker/ProcedureWorkerAppStartup';
30import { AllAppStartupStruct, allAppStartupStructOnClick } from '../database/ui-worker/ProcedureWorkerAllAppStartup';
31import { SoStruct, SoStructOnClick } from '../database/ui-worker/ProcedureWorkerSoInit';
32import { FrameAnimationStruct, FrameAnimationStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameAnimation';
33import { FrameDynamicStruct, FrameDynamicStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameDynamic';
34import { FrameSpacingStruct, FrameSpacingStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameSpacing';
35import { SampleStruct, sampleStructOnClick } from '../database/ui-worker/ProcedureWorkerBpftrace';
36import { SportRuler } from './trace/timer-shaft/SportRuler';
37import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
38import { LitSearch } from './trace/search/Search';
39import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent';
40import type { SpKeyboard } from './SpKeyboard';
41import { enableVSync } from './chart/VSync';
42import { CpuStruct, CpuStructOnClick } from '../database/ui-worker/cpu/ProcedureWorkerCPU';
43import { ProcessMemStruct } from '../database/ui-worker/ProcedureWorkerMem';
44import { CpuStateStruct, CpuStateStructOnClick } from '../database/ui-worker/cpu/ProcedureWorkerCpuState';
45import {
46  CpuFreqLimitsStruct,
47  CpuFreqLimitsStructOnClick
48} from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
49import { FlagsConfig } from './SpFlags';
50import { LitMainMenu } from '../../base-ui/menu/LitMainMenu';
51import { PerfToolsStructOnClick, PerfToolStruct } from '../database/ui-worker/ProcedureWorkerPerfTool';
52import { Utils } from './trace/base/Utils';
53import { BaseStruct } from '../bean/BaseStruct';
54import { GpuCounterStruct, gpuCounterStructOnClick } from '../database/ui-worker/ProcedureWorkerGpuCounter';
55import { HangStructOnClick } from '../database/ui-worker/ProcedureWorkerHang';
56
57function timeoutJudge(sp: SpSystemTrace): number {
58  let timeoutJudge = window.setTimeout((): void => {
59    if (SpSystemTrace.wakeupList.length && CpuStruct.selectCpuStruct) {
60      let checkHandlerKey: boolean = true;
61      let saveSelectCpuStruct: unknown = JSON.parse(sessionStorage.getItem('saveselectcpustruct')!);
62      for (const item of SpSystemTrace.wakeupList) {
63        if (item.ts === CpuStruct.selectCpuStruct.startTime && item.dur === CpuStruct.selectCpuStruct.dur) {
64          checkHandlerKey = false;
65          if (SpSystemTrace.wakeupList[0].schedulingDesc) {
66            //@ts-ignore
67            SpSystemTrace.wakeupList.unshift(saveSelectCpuStruct);
68          }
69          sp.refreshCanvas(true);
70          break;
71        } else if (
72          //@ts-ignore
73          saveSelectCpuStruct.startTime === CpuStruct.selectCpuStruct.startTime &&
74          //@ts-ignore
75          saveSelectCpuStruct.dur === CpuStruct.selectCpuStruct.dur
76        ) {
77          // 如果点击的是第一层,保持唤醒树不变
78          checkHandlerKey = false;
79          sp.refreshCanvas(true);
80          break;
81        }
82      }
83      // 点击线程在唤醒树内
84      if (!checkHandlerKey) {
85        // 查询获取tab表格数据
86        window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList);
87      } else {
88        // 不在唤醒树内,清空数组
89        sp.wakeupListNull();
90        sp.refreshCanvas(true);
91      }
92    } else {
93      sp.wakeupListNull();
94      sp.refreshCanvas(true);
95    }
96    clearTimeout(timeoutJudge);
97  }, 10);
98  return timeoutJudge;
99}
100
101function threadClickHandlerFunc(sp: SpSystemTrace): (e: ThreadStruct) => void {
102  let threadClickHandler = (d: ThreadStruct): void => {
103    sp.observerScrollHeightEnable = false;
104    sp.scrollToProcess(`${d.cpu}`, '', 'cpu-data', true);
105    let cpuRow = sp.queryAllTraceRow<TraceRow<CpuStruct>>(
106      `trace-row[row-id='${Utils.getDistributedRowId(d.cpu)}'][row-type='cpu-data']`,
107      (row) => row.rowId === `${Utils.getDistributedRowId(d.cpu)}` && row.rowType === 'cpu-data'
108    )[0];
109    if (cpuRow) {
110      sp.currentRow = cpuRow;
111      cpuRow.fixedList = [
112        {
113          startTime: d.startTime,
114          dur: d.dur,
115          tid: d.tid,
116          id: d.id,
117          processId: d.pid,
118          cpu: d.cpu,
119          argSetID: d.argSetID,
120        },
121      ];
122      let findEntry = cpuRow!.fixedList[0];
123      sp.rechargeCpuData(
124        // @ts-ignore
125        findEntry, // @ts-ignore
126        cpuRow.dataListCache.find((it) => it.startTime > findEntry.startTime)
127      );
128      if (
129        // @ts-ignore
130        findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || // @ts-ignore
131        findEntry!.startTime! > TraceRow.range!.endNS
132      ) {
133        sp.timerShaftEL?.setRangeNS(
134          // @ts-ignore
135          findEntry!.startTime! - findEntry!.dur! * 2, // @ts-ignore
136          findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2
137        );
138      }
139      sp.hoverStructNull().selectStructNull().wakeupListNull(); // @ts-ignore
140      CpuStruct.hoverCpuStruct = findEntry; // @ts-ignore
141      CpuStruct.selectCpuStruct = findEntry; // @ts-ignore
142      sp.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, 'inverted');
143      sp.traceSheetEL?.displayCpuData(
144        CpuStruct.selectCpuStruct!,
145        (wakeUpBean) => {
146          sp.removeLinkLinesByBusinessType('thread');
147          CpuStruct.wakeupBean = wakeUpBean;
148          sp.refreshCanvas(true);
149        },
150        cpuClickHandlerFunc(sp)
151      );
152    }
153  };
154  return threadClickHandler;
155}
156
157//点击prio箭头刷新canvas
158function prioClickHandlerFunc(sp: SpSystemTrace): (d: unknown) => void {
159  return function (d: unknown): void {
160    // @ts-ignore
161    ThreadStruct.prioCount = d;
162    ThreadStruct.isClickPrio = true;
163    sp.refreshCanvas(true);
164  };
165}
166
167function scrollToFuncHandlerFunc(sp: SpSystemTrace): Function {
168  let funClickHandle = (funcStruct: unknown): void => {
169    // @ts-ignore
170    if (funcStruct.chainId) {
171    }
172    sp.observerScrollHeightEnable = true;
173    // @ts-ignore
174    sp.moveRangeToCenter(funcStruct.startTs!, funcStruct.dur!);
175    sp.scrollToActFunc(funcStruct, false);
176  };
177  return funClickHandle;
178}
179
180function jankClickHandlerFunc(sp: SpSystemTrace): Function {
181  let jankClickHandler = (d: unknown): void => {
182    sp.observerScrollHeightEnable = true;
183    let jankRowParent: unknown;
184    //@ts-ignore
185    if (d.rowId === 'actual frameTime') {
186      jankRowParent = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>("trace-row[row-id='frameTime']");
187    } else {
188      jankRowParent = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>(
189        //@ts-ignore
190        `trace-row[row-type='process'][row-id='${d.pid}']`
191      );
192    }
193    //@ts-ignore
194    jankRowParent!.expansion = true;
195    let jankRow: unknown;
196    //@ts-ignore
197    jankRowParent.childrenList.forEach((item: TraceRow<JankStruct>) => {
198      //@ts-ignore
199      if (`${item.rowId}` === `${d.rowId}` && `${item.rowType}` === 'janks') {
200        jankRow = item;
201      }
202    });
203    //@ts-ignore
204    sp.currentRow = jankRow;
205    if (jankRow) {
206      JankStruct.selectJankStructList.length = 0;
207      //@ts-ignore
208      let findJankEntry = jankRow!.dataListCache!.find(
209        //@ts-ignore
210        (dat: unknown) => `${dat.name}` === `${d.name}` && `${dat.pid}` === `${d.pid}`
211      );
212      if (findJankEntry) {
213        if (
214          findJankEntry!.ts! + findJankEntry!.dur! < TraceRow.range!.startNS ||
215          findJankEntry!.ts! > TraceRow.range!.endNS
216        ) {
217          sp.timerShaftEL?.setRangeNS(
218            findJankEntry!.ts! - findJankEntry!.dur! * 2,
219            findJankEntry!.ts! + findJankEntry!.dur! + findJankEntry!.dur! * 2
220          );
221        }
222        sp.hoverStructNull().selectStructNull().wakeupListNull();
223        JankStruct.hoverJankStruct = findJankEntry;
224        JankStruct.selectJankStruct = findJankEntry;
225        sp.timerShaftEL?.drawTriangle(findJankEntry!.ts || 0, 'inverted');
226        sp.traceSheetEL?.displayJankData(
227          JankStruct.selectJankStruct!,
228          (datas) => {
229            sp.removeLinkLinesByBusinessType('janks');
230            // 绘制跟自己关联的线
231            datas.forEach((data) => {
232              //@ts-ignore
233              let endParentRow = sp.shadowRoot?.querySelector<TraceRow<BaseStruct>>( // @ts-ignore
234                `trace-row[row-type='process'][row-id='${data.pid}'][folder]`
235              );
236              sp.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data, true);
237            });
238          },
239          jankClickHandler
240        );
241      }
242      //@ts-ignore
243      sp.scrollToProcess(jankRow.rowId!, jankRow.rowParentId!, jankRow.rowType!, true);
244    }
245  };
246  return jankClickHandler;
247}
248
249function snapshotClickHandlerFunc(sp: SpSystemTrace): Function {
250  let snapshotClickHandler = (d: HeapSnapshotStruct): void => {
251    sp.observerScrollHeightEnable = true;
252    let snapshotRow = sp.shadowRoot?.querySelector<TraceRow<HeapSnapshotStruct>>(`trace-row[row-id='heapsnapshot']`);
253    let task = (): void => {
254      if (snapshotRow) {
255        let findEntry = snapshotRow!.dataListCache!.find((dat) => dat.startTs === d.startTs);
256        sp.hoverStructNull();
257        sp.selectStructNull();
258        sp.wakeupListNull();
259        HeapSnapshotStruct.hoverSnapshotStruct = findEntry;
260        HeapSnapshotStruct.selectSnapshotStruct = findEntry;
261      }
262    };
263    if (snapshotRow) {
264      if (snapshotRow!.isComplete) {
265        task();
266      } else {
267        snapshotRow!.onComplete = task;
268      }
269    }
270  };
271  return snapshotClickHandler;
272}
273
274//@ts-ignore
275function cpuClickHandlerTask(threadRow: TraceRow<unknown>, sp: SpSystemTrace, d: CpuStruct): void {
276  if (threadRow) {
277    let findEntry = threadRow!.fixedList[0];
278    if (
279      //@ts-ignore
280      findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS ||
281      //@ts-ignore
282      findEntry!.startTime! > TraceRow.range!.endNS
283    ) {
284      sp.timerShaftEL?.setRangeNS(
285        //@ts-ignore
286        findEntry!.startTime! - findEntry!.dur! * 2,
287        //@ts-ignore
288        findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2
289      );
290    }
291    ThreadStruct.firstselectThreadStruct = ThreadStruct.selectThreadStruct;
292    sp.hoverStructNull().selectStructNull().wakeupListNull();
293    //@ts-ignore
294    ThreadStruct.hoverThreadStruct = findEntry;
295    //@ts-ignore
296    ThreadStruct.selectThreadStruct = findEntry;
297    //@ts-ignore
298    sp.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, 'inverted');
299    sp.traceSheetEL?.displayThreadData(
300      ThreadStruct.selectThreadStruct!,
301      threadClickHandlerFunc(sp), // @ts-ignore
302      cpuClickHandlerFunc(sp),
303      prioClickHandlerFunc(sp),
304      (datas, str): void => {
305        sp.removeLinkLinesByBusinessType('thread');
306        if (str === 'wakeup tid') {
307          datas.forEach((data) => {
308            //@ts-ignore
309            let endParentRow = sp.shadowRoot?.querySelector<TraceRow<unknown>>( //@ts-ignore
310              `trace-row[row-id='${data.pid}'][folder]`
311            );
312            sp.drawThreadLine(endParentRow, ThreadStruct.firstselectThreadStruct, data);
313          });
314        }
315        sp.refreshCanvas(true);
316      }
317    );
318    sp.scrollToProcess(`${d.tid}`, `${d.processId}`, 'thread', true);
319  }
320}
321
322function cpuClickHandlerFunc(sp: SpSystemTrace) {
323  return function (d: CpuStruct): void {
324    //@ts-ignore
325    let traceRow = sp.shadowRoot?.querySelector<TraceRow<unknown>>(
326      `trace-row[row-id='${Utils.getDistributedRowId(d.processId)}'][row-type='process']`
327    );
328    if (traceRow) {
329      traceRow.expansion = true;
330    }
331    sp.observerScrollHeightEnable = true;
332    let threadRow = sp.queryAllTraceRow<TraceRow<ThreadStruct>>(
333      `trace-row[row-id='${Utils.getDistributedRowId(d.tid)}'][row-type='thread']`,
334      (row) => row.rowId === `${d.tid}` && row.rowType === 'thread'
335    )[0];
336    sp.currentRow = threadRow;
337    if (threadRow) {
338      threadRow.fixedList = [
339        {
340          startTime: d.startTime,
341          dur: d.dur,
342          cpu: d.cpu,
343          id: d.id,
344          tid: d.tid,
345          state: d.state,
346          pid: d.processId,
347          argSetID: d.argSetID,
348        },
349      ];
350      if (threadRow!.isComplete) {
351        cpuClickHandlerTask(threadRow, sp, d);
352      } else {
353        sp.scrollToProcess(`${d.tid}`, `${d.processId}`, 'process', false);
354        sp.scrollToProcess(`${d.tid}`, `${d.processId}`, 'thread', true);
355        threadRow!.onComplete = (): void => cpuClickHandlerTask(threadRow, sp, d);
356      }
357    }
358  };
359}
360
361
362function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRow<BaseStruct>, entry?: unknown): void {
363  CpuStructOnClick(clickRowType, sp, cpuClickHandlerFunc(sp), entry as CpuStruct)
364    .then(() => ThreadStructOnClick(clickRowType, sp, threadClickHandlerFunc(sp), cpuClickHandlerFunc(sp),
365      prioClickHandlerFunc(sp), entry as ThreadStruct))
366    .then(() => funcStructOnClick(clickRowType, sp, row as TraceRow<FuncStruct>,
367      scrollToFuncHandlerFunc(sp), entry as FuncStruct))
368    .then(() => CpuFreqStructOnClick(clickRowType, sp, entry as CpuFreqStruct))
369    .then(() => CpuStateStructOnClick(clickRowType, sp, entry as CpuStateStruct))
370    .then(() => CpuFreqLimitsStructOnClick(clickRowType, sp, entry as CpuFreqLimitsStruct))
371    .then(() => ClockStructOnClick(clickRowType, sp, entry as ClockStruct))
372    .then(() => HangStructOnClick(clickRowType, sp))
373    .then(() => DmaFenceStructOnClick(clickRowType, sp, entry as DmaFenceStruct))
374    .then(() => SnapshotStructOnClick(clickRowType, sp, row as TraceRow<SnapshotStruct>, entry as SnapshotStruct))
375    .then(() => IrqStructOnClick(clickRowType, sp, entry as IrqStruct))
376    .then(() => HeapStructOnClick(clickRowType, sp, row as TraceRow<HeapStruct>, entry as HeapStruct))
377    .then(() => JankStructOnClick(clickRowType, sp, row as TraceRow<JankStruct>,
378      jankClickHandlerFunc(sp), entry as JankStruct))
379    .then(() => HeapSnapshotStructOnClick(clickRowType, sp, row as TraceRow<HeapSnapshotStruct>,
380      snapshotClickHandlerFunc(sp), entry as HeapSnapshotStruct))
381    .then(() => JsCpuProfilerStructOnClick(clickRowType, sp, row as TraceRow<JsCpuProfilerStruct>,
382      entry as JsCpuProfilerStruct))
383    .then(() => AppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), entry as AppStartupStruct))
384    .then(() => allAppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), entry as AllAppStartupStruct))
385    .then(() => SoStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), entry as SoStruct))
386    .then(() => FrameAnimationStructOnClick(clickRowType, sp,
387      scrollToFuncHandlerFunc(sp), row as TraceRow<FrameAnimationStruct>, entry as FrameAnimationStruct))
388    .then(() => FrameDynamicStructOnClick(clickRowType, sp, row, entry as FrameDynamicStruct))
389    .then(() => FrameSpacingStructOnClick(clickRowType, sp, row!, entry as FrameSpacingStruct))
390    .then(() => sampleStructOnClick(clickRowType, sp, row as TraceRow<SampleStruct>, entry as SampleStruct))
391    .then(() => gpuCounterStructOnClick(clickRowType, sp, entry as GpuCounterStruct))
392    .then(() => PerfToolsStructOnClick(clickRowType, sp, entry as PerfToolStruct))
393    .then(() => {
394      if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) {
395        sp.removeLinkLinesByBusinessType('janks');
396      }
397      sp.observerScrollHeightEnable = false;
398      sp.selectFlag = null;
399      sp.timerShaftEL?.removeTriangle('inverted');
400      if (!SportRuler.isMouseInSportRuler) {
401        sp.traceSheetEL?.setMode('hidden');
402        sp.refreshCanvas(true, 'click');
403      }
404    })
405    .catch((e): void => { });
406}
407export default function spSystemTraceOnClickHandler(
408  sp: SpSystemTrace,
409  clickRowType: string,
410  row?: TraceRow<BaseStruct>,
411  entry?: unknown
412): void {
413  if (row) {
414    sp.currentRow = row;
415    sp.setAttribute('clickRow', clickRowType);
416    sp.setAttribute('rowName', row.name!);
417    sp.setAttribute('rowId', row.rowId!);
418  }
419  if (!sp.loadTraceCompleted) {
420    return;
421  }
422  sp.queryAllTraceRow().forEach((it): boolean => (it.rangeSelect = false));
423  sp.selectStructNull();
424  // 判断点击的线程是否在唤醒树内
425  timeoutJudge(sp);
426  allStructOnClick(clickRowType, sp, row, entry);
427  if (!JankStruct.selectJankStruct) {
428    sp.removeLinkLinesByBusinessType('janks');
429  }
430  if (!ThreadStruct.selectThreadStruct) {
431    sp.removeLinkLinesByBusinessType('thread');
432  }
433  if (!FuncStruct.selectFuncStruct) {
434    sp.removeLinkLinesByBusinessType('distributed', 'func');
435  }
436  if (row) {
437    let pointEvent = sp.createPointEvent(row);
438    SpStatisticsHttpUtil.addOrdinaryVisitAction({
439      action: 'trace_row', // @ts-ignore
440      event: pointEvent,
441    });
442  }
443}
444
445//@ts-ignore
446function handleActions(sp: SpSystemTrace, rows: Array<TraceRow<unknown>>, ev: MouseEvent): void {
447  if (sp.rangeSelect.isMouseDown && sp.rangeSelect.drag) {
448    let downRow = sp.visibleRows.find((row) => row.containPoint(ev));
449    if (downRow && downRow.traceId !== Utils.currentSelectTrace) {
450      spSystemTraceDocumentOnMouseMoveMouseUp(sp, rows, ev);
451      return;
452    }
453  }
454  sp.rangeSelect.mouseMove(rows, ev);
455  if (sp.rangeSelect.rangeTraceRow!.length > 0) {
456    sp.tabCpuFreq!.rangeTraceRow = sp.rangeSelect.rangeTraceRow;
457    sp.tabCpuState!.rangeTraceRow = sp.rangeSelect.rangeTraceRow;
458  }
459  let search = document.querySelector('body > sp-application')!.shadowRoot!.querySelector<LitSearch>('#lit-search');
460  if (sp.rangeSelect.isMouseDown && search?.isClearValue) {
461    spSystemTraceDocumentOnMouseMoveMouseDown(sp, search);
462  } else {
463    spSystemTraceDocumentOnMouseMoveMouseUp(sp, rows, ev);
464  }
465}
466
467function handleMouseInTimeShaft(sp: SpSystemTrace, ev: MouseEvent): boolean | undefined {
468  let isMouseInTimeShaft = sp.timerShaftEL?.containPoint(ev);
469  if (isMouseInTimeShaft) {
470    sp.tipEL!.style.display = 'none';
471    sp.hoverStructNull();
472  }
473  return isMouseInTimeShaft;
474}
475
476export function spSystemTraceDocumentOnMouseMove(sp: SpSystemTrace, ev: MouseEvent): void {
477  //@ts-ignore
478  if (!sp.loadTraceCompleted || (window as unknown).flagInputFocus || !sp.mouseEventEnable) {
479    return;
480  }
481  //@ts-ignore
482  if ((window as unknown).collectResize) {
483    sp.style.cursor = 'row-resize';
484    sp.cancelDrag();
485    return;
486  }
487  if (sp.isWASDKeyPress()) {
488    sp.hoverFlag = null;
489    ev.preventDefault();
490    return;
491  }
492  if (ev.ctrlKey && ev.button === 0 && SpSystemTrace.isMouseLeftDown) {
493    // 计算当前tab组件的高度
494    let tabHeight: number =
495      sp.shadowRoot?.querySelector('trace-sheet')!.shadowRoot?.querySelector('lit-tabs')!.clientHeight! + 1;
496    // 计算当前屏幕内高与鼠标位置坐标高度的差值
497    let diffHeight: number = window.innerHeight - ev.clientY;
498    // 如果差值大于面板高度,意味着鼠标位于泳道区域,可以通过ctrl+鼠标左键移动。否则不予生效
499    if (diffHeight > tabHeight) {
500      sp.translateByMouseMove(ev);
501    } else {
502      // 若鼠标位于tab面板区,则将其中标志位置成false
503      SpSystemTrace.isMouseLeftDown = false;
504    }
505  }
506  sp.inFavoriteArea = sp.favoriteChartListEL?.containPoint(ev);
507  //@ts-ignore
508  if ((window as unknown).isSheetMove || sp.isMouseInSheet(ev)) {
509    sp.hoverStructNull();
510    sp.tipEL!.style.display = 'none';
511    return;
512  }
513  let isMouseInTimeShaft = handleMouseInTimeShaft(sp, ev);
514  let rows = sp.visibleRows;
515  sp.timerShaftEL?.documentOnMouseMove(ev, sp);
516
517  if (isMouseInTimeShaft) {
518    return;
519  }
520  handleActions(sp, rows, ev);
521}
522
523function spSystemTraceDocumentOnMouseMoveMouseDown(sp: SpSystemTrace, search: LitSearch): void {
524  sp.refreshCanvas(true, 'sp move down');
525  if (TraceRow.rangeSelectObject) {
526    if (search && search.searchValue !== '') {
527      search.clear();
528      search.valueChangeHandler?.('');
529    }
530  }
531}
532
533function spSystemTraceDocumentOnMouseMoveMouseUp(
534  sp: SpSystemTrace, //@ts-ignore
535  rows: Array<TraceRow<unknown>>,
536  ev: MouseEvent
537): void {
538  if (!sp.rowsPaneEL!.containPoint(ev, { left: 248 })) {
539    sp.hoverStructNull();
540  }
541  const transformYMatch = sp.canvasPanel?.style.transform.match(/\((\d+)[^\)]+\)/);
542  const transformY = transformYMatch![1];
543  let favoriteHeight = sp.favoriteChartListEL!.getBoundingClientRect().height;
544  // @ts-ignore
545  let memTr = rows.filter((item: unknown) => item.rowType === TraceRow.ROW_TYPE_MEM);
546  rows
547    .filter((it) => it.focusContain(ev, sp.inFavoriteArea!, Number(transformY), favoriteHeight) && it.collect === sp.inFavoriteArea)
548    .filter((it) => {
549      if (it.collect) {
550        return true;
551      } else {
552        return (
553          it.getBoundingClientRect().bottom + it.getBoundingClientRect().height >
554          sp.favoriteChartListEL!.getBoundingClientRect().bottom
555        );
556      }
557    })
558    .forEach((tr): void => {
559      if (tr.rowType !== TraceRow.ROW_TYPE_CPU) {
560        CpuStruct.hoverCpuStruct = undefined;
561      }
562      if (tr.rowType !== TraceRow.ROW_TYPE_MEM) {
563        ProcessMemStruct.hoverProcessMemStruct = undefined;
564        memTr.forEach((i: unknown) => {
565          // @ts-ignore
566          i.focusHandler(ev);
567        });
568      }
569      if (sp.currentRowType !== tr.rowType) {
570        sp.currentRowType = tr.rowType || '';
571      }
572      tr.findHoverStruct?.();
573      tr.focusHandler?.(ev);
574    });
575  requestAnimationFrame(() => sp.refreshCanvas(true, 'sp move up'));
576}
577
578export function spSystemTraceDocumentOnMouseOut(sp: SpSystemTrace, ev: MouseEvent): void {
579  if (!sp.loadTraceCompleted) {
580    return;
581  }
582  CpuStruct.hoverCpuStruct = undefined;
583  TraceRow.isUserInteraction = false;
584  SpSystemTrace.isMouseLeftDown = false;
585  if (sp.isMouseInSheet(ev)) {
586    return;
587  }
588  if (ev.offsetX > sp.timerShaftEL!.canvas!.offsetLeft) {
589    sp.rangeSelect.mouseOut(ev);
590    sp.timerShaftEL?.documentOnMouseOut(ev);
591  }
592}
593
594export function spSystemTraceDocumentOnKeyPress(this: unknown, sp: SpSystemTrace, ev: KeyboardEvent): void {
595  SpSystemTrace.isKeyUp = false;
596  if (!sp.loadTraceCompleted) {
597    return;
598  }
599  let keyPress = ev.key.toLocaleLowerCase();
600  TraceRow.isUserInteraction = true;
601  if (sp.isMousePointInSheet) {
602    return;
603  }
604  sp.observerScrollHeightEnable = false;
605  if (sp.keyboardEnable) {
606    if (keyPress === 'm') {
607      sp.slicestime = sp.setSLiceMark(ev.shiftKey);
608      if (sp.slicestime) {
609        if (TraceRow.rangeSelectObject) {
610          let showTab = sp.getShowTab();
611          sp.traceSheetEL
612            ?.displayTab<TabPaneCurrent>('tabpane-current', ...showTab)
613            .setCurrentSlicesTime(sp.slicestime);
614        } else {
615          sp.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(sp.slicestime);
616        }
617      }
618    }
619    if (keyPress === 'f') {
620      let isSelectSliceOrFlag = false;
621      // 设置当前选中的slicetime
622      let selectSlice: unknown = undefined;
623      sp._slicesList.forEach((slice: { selected: boolean }): void => {
624        if (slice.selected) {
625          selectSlice = slice;
626        }
627      });
628      if (!!selectSlice) {
629        //@ts-ignore
630        sp.currentSlicesTime.startTime = selectSlice.startTime;
631        //@ts-ignore
632        sp.currentSlicesTime.endTime = selectSlice.endTime;
633        isSelectSliceOrFlag = true;
634      }
635
636      if (!!sp.selectFlag) {
637        sp.currentSlicesTime.startTime = sp.selectFlag?.time;
638        sp.currentSlicesTime.endTime = sp.selectFlag?.time;
639        isSelectSliceOrFlag = true;
640      }
641      // 设置当前的slicesTime
642      !isSelectSliceOrFlag && sp.setCurrentSlicesTime();
643    }
644    let keyPressWASD = keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd';
645    if (keyPressWASD) {
646      sp.keyPressMap.set(keyPress, true);
647      if (sp.rangeSelect.isMouseDown && sp.rangeSelect.drag) {
648        sp.rangeSelect.mouseUp();
649      }
650      sp.hoverFlag = null;
651    }
652    sp.timerShaftEL!.documentOnKeyPress(ev, sp.currentSlicesTime);
653    if (keyPress === 'f') {
654      sp.verticalScrollToRow();
655    }
656  } else {
657    sp.stopWASD();
658  }
659}
660
661export function spSystemTraceDocumentOnMouseDown(sp: SpSystemTrace, ev: MouseEvent): void {
662  if (!sp.loadTraceCompleted || !sp.mouseEventEnable) {
663    return;
664  }
665  if (sp.isWASDKeyPress()) {
666    ev.preventDefault();
667    ev.stopPropagation();
668    return;
669  }
670  if (ev.button === 0) {
671    SpSystemTrace.isMouseLeftDown = true;
672    if (ev.ctrlKey) {
673      ev.preventDefault();
674      sp.style.cursor = 'move';
675      sp.mouseCurrentPosition = ev.clientX;
676      return;
677    }
678  }
679
680  TraceRow.isUserInteraction = true;
681  if (sp.isMouseInSheet(ev)) {
682    return;
683  }
684  sp.observerScrollHeightEnable = false;
685  if (ev.offsetX > sp.timerShaftEL!.canvas!.offsetLeft) {
686    let x = ev.offsetX - sp.timerShaftEL!.canvas!.offsetLeft;
687    let y = ev.offsetY;
688    sp.timerShaftEL?.documentOnMouseDown(ev);
689    if (y > sp.timerShaftEL!.offsetHeight) {
690      sp.rangeSelect.mouseDown(ev);
691      sp.rangeSelect.drag = true;
692      let downRow = sp.visibleRows.find((row) => row.containPoint(ev));
693      Utils.currentSelectTrace = downRow?.traceId;
694    }
695    //  如果鼠标摁下事件发生在traceRow范围或时间轴(sportRuler除外)范围内,清除上次点击调用栈产生的所有的三角旗子
696    // ev.offsetY:鼠标在SpSystemTrace元素的y轴偏移量
697    if (
698      ev.offsetY > sp.timerShaftEL!.clientHeight ||
699      ev.offsetY < sp.timerShaftEL!.clientHeight - sp.timerShaftEL!.sportRuler!.frame.height
700    ) {
701      sp.clearTriangle(sp.timerShaftEL!.sportRuler!.flagList);
702    }
703  } else {
704    sp.rangeSelect.drag = false;
705  }
706}
707
708function handleTimerShaftActions(ev: MouseEvent, sp: SpSystemTrace): void {
709  if (ev.offsetX > sp.timerShaftEL!.canvas!.offsetLeft) {
710    let x = ev.offsetX - sp.timerShaftEL!.canvas!.offsetLeft;
711    let y = ev.offsetY;
712    if (
713      sp.timerShaftEL!.sportRuler!.frame.contains(x, y) &&
714      x > (TraceRow.rangeSelectObject?.startX || 0) &&
715      x < (TraceRow.rangeSelectObject?.endX || 0)
716    ) {
717      let findSlicestime = sp.timerShaftEL!.sportRuler?.findSlicesTime(x, y); // 查找帽子
718      if (!findSlicestime) {
719        // 如果没有找到帽子,则绘制一个旗子
720        let time = Math.round(
721          (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / sp.timerShaftEL!.canvas!.offsetWidth +
722          TraceRow.range?.startNS!
723        );
724        sp.timerShaftEL!.sportRuler!.drawTriangle(time, 'squre');
725      }
726    }
727  }
728}
729
730export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent): void {
731  //@ts-ignore
732  if ((window as unknown).collectResize) {
733    return;
734  }
735  if (!sp.loadTraceCompleted || !sp.mouseEventEnable) {
736    return;
737  }
738  if (sp.isWASDKeyPress()) {
739    ev.preventDefault();
740    ev.stopPropagation();
741    return;
742  }
743  SpSystemTrace.isMouseLeftDown = false;
744  if (ev.ctrlKey) {
745    ev.preventDefault();
746    sp.offsetMouse = 0;
747    sp.mouseCurrentPosition = 0;
748    sp.style.cursor = 'default';
749    return;
750  }
751  TraceRow.isUserInteraction = false;
752  sp.rangeSelect.isMouseDown = false;
753  //@ts-ignore
754  if ((window as unknown).isSheetMove) {
755    return;
756  }
757  if (sp.isMouseInSheet(ev)) {
758    return;
759  }
760  handleTimerShaftActions(ev, sp);
761  if (!SportRuler.isMouseInSportRuler) {
762    sp.rangeSelect.mouseUp(ev);
763  }
764  sp.timerShaftEL?.documentOnMouseUp(ev);
765}
766
767export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEvent): void {
768  SpSystemTrace.isKeyUp = true;
769  if (sp.times.size > 0) {
770    for (let timerId of sp.times) {
771      clearTimeout(timerId);
772    }
773  }
774  let flag: boolean = sp.parentElement
775    ?.querySelector('sp-record-trace')!
776    .shadowRoot?.querySelector('lit-main-menu-item[icon="file-config"]')!
777    .hasAttribute('back')!;
778  if (ev.key.toLocaleLowerCase() === String.fromCharCode(47) && !flag) {
779    if (SpSystemTrace.keyboardFlar) {
780      document
781        .querySelector('body > sp-application')!
782        .shadowRoot!.querySelector<SpKeyboard>('#sp-keyboard')!.style.visibility = 'visible';
783      SpSystemTrace.keyboardFlar = false;
784    } else {
785      document
786        .querySelector('body > sp-application')!
787        .shadowRoot!.querySelector<SpKeyboard>('#sp-keyboard')!.style.visibility = 'hidden';
788      SpSystemTrace.keyboardFlar = true;
789    }
790  }
791  if (!sp.loadTraceCompleted) {
792    return;
793  }
794  let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY);
795  let flagsItemJson = JSON.parse(flagsItem!);
796  if (flagsItemJson.VSync === 'Enabled') {
797    sp.keyboardEnable && enableVSync(false, ev, () => sp.refreshCanvas(true, 'sp key up'));
798  }
799  let keyPress = ev.key.toLocaleLowerCase();
800  if (keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd') {
801    sp.keyPressMap.set(keyPress, false);
802  }
803  TraceRow.isUserInteraction = false;
804  sp.observerScrollHeightEnable = false;
805  sp.keyboardEnable && sp.timerShaftEL!.documentOnKeyUp(ev);
806  if (ev.code === 'Enter' || ev.code === 'NumpadEnter') {
807    document.removeEventListener('keydown', sp.documentOnKeyDown);
808    if (ev.shiftKey) {
809      sp.dispatchEvent(
810        new CustomEvent('trace-previous-data', {
811          detail: {},
812          composed: false,
813        })
814      );
815    } else {
816      if (sp.focusTarget === '') {
817        sp.dispatchEvent(
818          new CustomEvent('trace-next-data', {
819            detail: {},
820            composed: false,
821          })
822        );
823      }
824    }
825    document.addEventListener('keydown', sp.documentOnKeyDown);
826  }
827
828  if (ev.ctrlKey) {
829    spSystemTraceDocumentOnKeyUpCtrlKey(keyPress, sp, ev);
830  }
831}
832
833function spSystemTraceDocumentOnKeyUpCtrlKey(keyPress: string, sp: SpSystemTrace, ev: KeyboardEvent): void {
834  if (keyPress === 'b') {
835    let menuBox = document
836      .querySelector('body > sp-application')!
837      .shadowRoot?.querySelector('#main-menu') as LitMainMenu;
838    let searchBox = document
839      .querySelector('body > sp-application')
840      ?.shadowRoot?.querySelector('div > div.search-vessel') as HTMLDivElement;
841    let appContent = document
842      .querySelector('body > sp-application')
843      ?.shadowRoot?.querySelector('div > #app-content') as HTMLDivElement;
844    let rowPane = appContent
845      ?.querySelector('#sp-system-trace')
846      ?.shadowRoot?.querySelector('div > div.rows-pane') as HTMLDivElement;
847    let timerShaft = appContent
848      ?.querySelector('#sp-system-trace')
849      ?.shadowRoot?.querySelector('div > timer-shaft-element') as HTMLDivElement;
850    let spChartList = appContent
851      ?.querySelector('#sp-system-trace')
852      ?.shadowRoot?.querySelector('div > sp-chart-list') as HTMLDivElement;
853    let canvasEle = spChartList.shadowRoot?.querySelector('canvas') as unknown as HTMLDivElement;
854    let sidebarButton = searchBox!.querySelector('div > div.sidebar-button') as HTMLDivElement;
855    let importConfigDiv = searchBox!.querySelector('div > #import-key-path') as HTMLDivElement;
856    if (menuBox.style.zIndex! === '2000' || searchBox!.style.display !== 'none') {
857      SpSystemTrace.isHiddenMenu = true;
858      menuBox.style.width = '0px';
859      menuBox.style.display = 'flex';
860      menuBox.style.zIndex = '0';
861      sidebarButton.style.width = '48px';
862      importConfigDiv!.style.left = '45px';
863      searchBox!.style.display = 'none';
864      rowPane.style.maxHeight = '100%';
865    } else {
866      SpSystemTrace.isHiddenMenu = false;
867      menuBox.style.width = '248px';
868      menuBox.style.zIndex = '2000';
869      menuBox.style.display = 'flex';
870      sidebarButton.style.width = '0px';
871      importConfigDiv!.style.left = '5px';
872      searchBox!.style.display = '';
873      rowPane.style.maxHeight = '100%';
874    }
875  }
876  if (keyPress === '[' && sp._slicesList.length > 1) {
877    sp.selectFlag = undefined;
878    sp.MarkJump(sp._slicesList, 'slice', 'previous', ev);
879  } else if (keyPress === ',' && sp._flagList.length > 1) {
880    sp.MarkJump(sp._flagList, 'flag', 'previous', ev);
881  } else if (keyPress === ']' && sp._slicesList.length > 1) {
882    sp.selectFlag = undefined;
883    sp.MarkJump(sp._slicesList, 'slice', 'next', ev);
884  } else if (keyPress === '.' && sp._flagList.length > 1) {
885    sp.MarkJump(sp._flagList, 'flag', 'next', ev);
886  } else {
887    return;
888  }
889}
890
891function handleClickActions(sp: SpSystemTrace, x: number, y: number, ev: MouseEvent): void {
892  if (
893    !(
894      sp.timerShaftEL!.sportRuler!.frame.contains(x, y) &&
895      x > (TraceRow.rangeSelectObject?.startX || 0) &&
896      x < (TraceRow.rangeSelectObject?.endX || 0)
897    )
898  ) {
899    const transformYMatch = sp.canvasPanel?.style.transform.match(/\((\d+)[^\)]+\)/);
900    const transformY = transformYMatch![1];
901    let inFavoriteArea = sp.favoriteChartListEL?.containPoint(ev);
902    let favoriteHeight = sp.favoriteChartListEL!.getBoundingClientRect().height;
903    let rows = sp.visibleRows.filter((it) =>
904      it.focusContain(ev, inFavoriteArea!, Number(transformY), favoriteHeight) && it.collect === inFavoriteArea);
905    if (JankStruct.delJankLineFlag) {
906      sp.removeLinkLinesByBusinessType('janks');
907    }
908    let strict = true;
909    let offset = false;
910    if (
911      rows[0] &&
912      (rows[0].rowType === TraceRow.ROW_TYPE_FRAME_DYNAMIC || rows[0].rowType === TraceRow.ROW_TYPE_FRAME_SPACING)
913    ) {
914      strict = false;
915      offset = true;
916    }
917    if (rows && rows[0] && (rows[0].getHoverStruct(strict, offset) ||
918      (rows[0].rowType === TraceRow.ROW_TYPE_GPU_COUNTER && rows[0].getHoverStruct(false)))) {
919      sp.onClickHandler(rows[0]!.rowType!, rows[0], rows[0].getHoverStruct(strict, offset));
920      sp.documentOnMouseMove(ev);
921    } else {
922      sp.clickEmptyArea();
923    }
924  }
925}
926
927export function spSystemTraceDocumentOnClick(sp: SpSystemTrace, ev: MouseEvent): void {
928  if (!sp.loadTraceCompleted) {
929    return;
930  }
931  if (sp.isWASDKeyPress()) {
932    sp.hoverFlag = null;
933    ev.preventDefault();
934    ev.stopPropagation();
935    return;
936  }
937  //@ts-ignore
938  if ((window as unknown).isSheetMove) {
939    return;
940  }
941  if (sp.isMouseInSheet(ev)) {
942    return;
943  }
944  //@ts-ignore
945  if ((window as unknown).isPackUpTable) {
946    //@ts-ignore
947    (window as unknown).isPackUpTable = false;
948    return;
949  }
950  let x = ev.offsetX - sp.timerShaftEL!.canvas!.offsetLeft;
951  let y = ev.offsetY;
952  if (sp.timerShaftEL?.getRangeRuler()?.frame.contains(x, y)) {
953    sp.clickEmptyArea();
954    return;
955  }
956  if (sp.rangeSelect.isDrag()) {
957    return;
958  }
959  handleClickActions(sp, x, y, ev);
960  ev.preventDefault();
961}
962
963export function spSystemTraceDocumentOnKeyDown(sp: SpSystemTrace, ev: KeyboardEvent): void {
964  document.removeEventListener('keyup', sp.documentOnKeyUp);
965  sp.debounce(sp.continueSearch, 250, ev)();
966  document.addEventListener('keyup', sp.documentOnKeyUp);
967}
968