Merge "Update atoms descriptor." into main
diff --git a/ui/src/base/hotkeys.ts b/ui/src/base/hotkeys.ts
index 17e3a00..85c194f 100644
--- a/ui/src/base/hotkeys.ts
+++ b/ui/src/base/hotkeys.ts
@@ -88,7 +88,9 @@
| 'ArrowLeft'
| 'ArrowRight'
| '['
- | ']';
+ | ']'
+ | ','
+ | '.';
export type Key = Alphabet | Number | Special;
export type Modifier =
| ''
diff --git a/ui/src/core_plugins/track_utils/index.ts b/ui/src/core_plugins/track_utils/index.ts
index 369d2fe..e13d479 100644
--- a/ui/src/core_plugins/track_utils/index.ts
+++ b/ui/src/core_plugins/track_utils/index.ts
@@ -18,6 +18,7 @@
import {AppImpl} from '../../core/app_impl';
import {getTimeSpanOfSelectionOrVisibleWindow} from '../../public/utils';
import {exists} from '../../base/utils';
+import {LONG, NUM, NUM_NULL} from '../../trace_processor/query_result';
export default class implements PerfettoPlugin {
static readonly id = 'perfetto.TrackUtils';
@@ -83,5 +84,57 @@
id && ctx.workspace.getTrackById(id)?.pin();
},
});
+
+ ctx.commands.registerCommand({
+ id: 'perfetto.SelectNextTrackEvent',
+ name: 'Select next track event',
+ defaultHotkey: '.',
+ callback: async () => {
+ await selectAdjacentTrackEvent(ctx, 'next');
+ },
+ });
+
+ ctx.commands.registerCommand({
+ id: 'perfetto.SelectPreviousTrackEvent',
+ name: 'Select previous track event',
+ defaultHotkey: ',',
+ callback: async () => {
+ await selectAdjacentTrackEvent(ctx, 'prev');
+ },
+ });
}
}
+
+/**
+ * If a track event is currently selected, select the next or previous event on
+ * that same track chronologically ordered by `ts`.
+ */
+async function selectAdjacentTrackEvent(
+ ctx: Trace,
+ direction: 'next' | 'prev',
+) {
+ const selection = ctx.selection.selection;
+ if (selection.kind !== 'track_event') return;
+
+ const td = ctx.tracks.getTrack(selection.trackUri);
+ const dataset = td?.track.getDataset?.();
+ if (!dataset || !dataset.implements({id: NUM, ts: LONG})) return;
+
+ const windowFunc = direction === 'next' ? 'LEAD' : 'LAG';
+ const result = await ctx.engine.query(`
+ WITH
+ CTE AS (
+ SELECT
+ id,
+ ${windowFunc}(id) OVER (ORDER BY ts) AS resultId
+ FROM (${dataset.query()})
+ )
+ SELECT * FROM CTE WHERE id = ${selection.eventId}
+ `);
+ const resultId = result.maybeFirstRow({resultId: NUM_NULL})?.resultId;
+ if (!exists(resultId)) return;
+
+ ctx.selection.selectTrackEvent(selection.trackUri, resultId, {
+ scrollToSelection: true,
+ });
+}