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