Skip to content

Commit 646d07a

Browse files
Copilotbrianrobleculver
authored
Fix StackViewer: "Set Time Range" resets "Goto Items by callees" (#2208)
* Initial plan for issue * Fix StackViewer: preserve focus when setting time range Co-authored-by: brianrob <[email protected]> * Clean-up compiler errors and remove the breaking call to SetFocus. * Fix unit test implementation. * Update test to use stacksource min/max times and revert currentFocusName scope change Co-authored-by: brianrob <[email protected]> * Revert all changes related to currentFocusName Co-authored-by: brianrob <[email protected]> * Keep track of the focus node and set focus again after the update. * Fix-up test compile errors * Use null-coalescing operator for FocusName Co-authored-by: leculver <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: brianrob <[email protected]> Co-authored-by: Brian Robbins <[email protected]> Co-authored-by: leculver <[email protected]>
1 parent 210455a commit 646d07a

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

src/PerfView.Tests/StackViewer/StackWindowTests.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,78 @@ public Task TestSetTimeRangeWithSpaceAsync()
277277
return TestSetTimeRangeWithSpaceImplAsync(CultureInfo.CurrentCulture);
278278
}
279279

280+
[WpfFact]
281+
[WorkItem(2179, "https://github.com/Microsoft/perfview/issues/2179")]
282+
[UseCulture("en-US")]
283+
public Task TestSetTimeRangeAfterGotoCalleesAsync()
284+
{
285+
Func<Task<StackWindow>> setupAsync = async () =>
286+
{
287+
await JoinableTaskFactory.SwitchToMainThreadAsync();
288+
289+
var file = new TimeRangeFile();
290+
await OpenAsync(JoinableTaskFactory, file, GuiApp.MainWindow, GuiApp.MainWindow.StatusBar).ConfigureAwait(true);
291+
var stackSource = file.GetStackSource();
292+
return stackSource.Viewer;
293+
};
294+
295+
Func<StackWindow, Task> cleanupAsync = async stackWindow =>
296+
{
297+
await JoinableTaskFactory.SwitchToMainThreadAsync();
298+
299+
stackWindow.Close();
300+
};
301+
302+
Func<StackWindow, Task> testDriverAsync = async stackWindow =>
303+
{
304+
await JoinableTaskFactory.SwitchToMainThreadAsync();
305+
306+
// First, navigate to the call tree tab
307+
stackWindow.CallTreeTab.IsSelected = true;
308+
await WaitForUIAsync(stackWindow.Dispatcher, CancellationToken.None);
309+
310+
// Find a node in the call tree that is not the root node.
311+
var callTreeNode = stackWindow.m_callTreeView.Root.Callees[0];
312+
Assert.NotNull(callTreeNode);
313+
314+
// Set focus to this node
315+
stackWindow.SetFocus(callTreeNode.Name);
316+
317+
// Use "Goto Items in Callees" command (Shift+F10)
318+
stackWindow.CalleesTab.IsSelected = true;
319+
await WaitForUIAsync(stackWindow.Dispatcher, CancellationToken.None);
320+
321+
// Remember current focus after going to callees
322+
string calleeFocusName = stackWindow.FocusName;
323+
Assert.NotNull(calleeFocusName);
324+
Assert.NotEqual("ROOT", calleeFocusName);
325+
326+
// Now execute Set Time Range command
327+
var byNameView = stackWindow.m_byNameView;
328+
329+
// Use min and max values from the stacksource
330+
double minTime = stackWindow.StackSource.GetSampleByIndex(0).TimeRelativeMSec;
331+
double maxTime = 0;
332+
for (int i = 0; i < stackWindow.StackSource.SampleIndexLimit; i++)
333+
{
334+
maxTime = Math.Max(maxTime, stackWindow.StackSource.GetSampleByIndex((StackSourceSampleIndex)i).TimeRelativeMSec);
335+
}
336+
337+
stackWindow.StartTextBox.Text = minTime.ToString("n3");
338+
stackWindow.EndTextBox.Text = maxTime.ToString("n3");
339+
stackWindow.Update();
340+
341+
// Wait for any background processing to complete
342+
await stackWindow.StatusBar.WaitForWorkCompleteAsync().ConfigureAwait(true);
343+
344+
// Verify focus was maintained
345+
Assert.Equal(calleeFocusName, stackWindow.FocusName);
346+
//}
347+
};
348+
349+
return RunUITestAsync(setupAsync, testDriverAsync, cleanupAsync);
350+
}
351+
280352
private Task TestSetTimeRangeWithSpaceImplAsync(CultureInfo culture)
281353
{
282354
Func<Task<StackWindow>> setupAsync = async () =>
@@ -304,6 +376,14 @@ private Task TestSetTimeRangeWithSpaceImplAsync(CultureInfo culture)
304376
var row = byNameView.FindIndex(node => node.FirstTimeRelativeMSec > 0 && node.FirstTimeRelativeMSec < node.LastTimeRelativeMSec);
305377
CallTreeNodeBase selected = byNameView[row];
306378

379+
// Set focus to a specific node
380+
string testFocusName = selected.Name;
381+
stackWindow.SetFocus(testFocusName);
382+
383+
// Verify the focus is set correctly
384+
Assert.Equal(testFocusName, stackWindow.FocusName);
385+
386+
// Now execute Set Time Range command
307387
var selectedCells = stackWindow.ByNameDataGrid.Grid.SelectedCells;
308388
selectedCells.Clear();
309389
selectedCells.Add(new DataGridCellInfo(byNameView[row], stackWindow.ByNameDataGrid.FirstTimeColumn));
@@ -314,8 +394,12 @@ private Task TestSetTimeRangeWithSpaceImplAsync(CultureInfo culture)
314394
// Wait for any background processing to complete
315395
await stackWindow.StatusBar.WaitForWorkCompleteAsync().ConfigureAwait(true);
316396

397+
// Verify time range was set correctly
317398
Assert.Equal(selected.FirstTimeRelativeMSec.ToString("n3", culture), stackWindow.StartTextBox.Text);
318399
Assert.Equal(selected.LastTimeRelativeMSec.ToString("n3", culture), stackWindow.EndTextBox.Text);
400+
401+
// Verify focus was maintained
402+
Assert.Equal(testFocusName, stackWindow.FocusName);
319403
};
320404

321405
return RunUITestAsync(setupAsync, testDriverAsync, cleanupAsync);

src/PerfView/StackViewer/StackWindow.xaml.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ public void SetStackSource(StackSource newSource, Action onComplete = null)
371371

372372
StatusBar.EndWork(delegate ()
373373
{
374+
var selectedNodeName = FocusName ?? "ROOT";
374375
var oldCallTree = m_callTree;
375376
m_callTree = newCallTree;
376377

@@ -395,8 +396,7 @@ public void SetStackSource(StackSource newSource, Action onComplete = null)
395396
ByNameDataGrid.Grid.Columns[i].SortDirection = direction;
396397
}
397398

398-
// SignalPropertyChange the Caller-Callee Tab
399-
SetFocus(m_callTree.Root);
399+
SetFocus(selectedNodeName);
400400

401401
ByNameDataGrid.Focus();
402402

0 commit comments

Comments
 (0)