Skip to content

Fix five Avalonia UI regressions: mouse navigation, derived types, Enter, Delete, Analyze in the Analyzer pane - #4039

Open
christophwille wants to merge 5 commits into
masterfrom
fix/ui-regressions-4027-4028-4030
Open

Fix five Avalonia UI regressions: mouse navigation, derived types, Enter, Delete, Analyze in the Analyzer pane#4039
christophwille wants to merge 5 commits into
masterfrom
fix/ui-regressions-4027-4028-4030

Conversation

@christophwille

@christophwille christophwille commented Aug 20, 2026

Copy link
Copy Markdown
Member

Five UI regressions from the Avalonia migration (the fourth and fifth, Delete and Analyze in the Analyzer pane, were reported in the #4030 thread), one commit each, each with a headless regression test that was shown red before the fix.

Fixes #4027
Fixes #4028
Fixes #4030

Mouse4 / Mouse5 no longer navigate back / forward (#4027)

WPF translated the extra mouse buttons into BrowseBack/BrowseForward commands by itself, so they never reached the control under the pointer as a click; Avalonia has no such translation and KeyBinding cannot express pointer buttons, so only Alt+Left / Alt+Right survived the migration. MainWindow now swallows the XButton1/XButton2 press while it tunnels (otherwise Dock activates the pane under the pointer and AvaloniaEdit focuses the editor or toggles a folding marker) and routes the release to the existing DockWorkspace.NavigateBackCommand/NavigateForwardCommand. Navigating also no longer moves the active pane to the editor: the history target is usually the already-active tab, and Dock's ActiveDockable setter re-runs SetFocusedDockable even for an unchanged value, so ApplyNavigationTarget only activates a tab that is not active yet (WPF's ActiveTabPage setter was a no-op for the same value).

Derived types not shown in tree (#4028)

DerivedTypesEntryNode.Filter reported FilterResult.Recurse, but the filter cascade's Recurse handling force-loads the node's lazy children and hides the node when all of them are hidden. A leaf derived type has no children, so every entry under "Derived Types" ended up hidden, and the hiding propagated up the whole chain. Reporting Match (what the WPF tree effectively did, since the tree ignores the search term) restores the entries and also keeps derived chains lazy instead of eagerly scanning the assembly list for every level.

Enter does nothing on a selected tree row (#4030)

Avalonia 12's default key selection triggers treat plain Enter/Space on a ListBoxItem as selection input and mark the KeyDown handled before it bubbles, so the activation handling in SharpTreeView.OnKeyDown (navigate to the member from an analyzer row, toggle a checkable row) never saw those keys. SharpTreeView now overrides ShouldTriggerSelection — the Avalonia 12 extension point for exactly this — to suppress the selection trigger precisely for the case OnKeyDown activates instead: a single selected row that is the row the key landed on. Multi-row selections keep the default collapse-to-focused-row behaviour.

Delete does nothing on a selected analyzer row (#4030, follow-up report)

The WPF SharpTreeView bound ApplicationCommands.Delete at class level, so Delete removed the top-level selection of any tree whose nodes opt in through CanDelete/Delete -- which is how a top-level analyzer entry was removed from the Analyzer pane. The Avalonia tree never received that binding; only the assembly list pane carried a hand-rolled Delete handler for assemblies. The gesture now lives in SharpTreeView.OnKeyDown again (delete the top-level selection when every node in it is deletable, then reselect the nearest survivor), which restores it for the analyzer pane and lets the pane-specific handler go.

Analyze missing from the Analyzer pane's context menu (#4030 thread, second follow-up report)

The WPF AnalyzerEntityTreeNode implemented IMemberTreeNode, which is what the "Analyze" entry (and "Copy name") keys off, so right-clicking a result row in the Analyzer pane offered Analyze and promoted that row's entity to a new top-level entry. The Avalonia port dropped the interface from the node, so no analyzer row ever showed the entry. The interface is back on the node; as in WPF, top-level analyzer rows keep Analyze hidden (re-analysing them is a no-op, Remove is the entry for those rows).

Verification

Full ILSpy.Tests suite green locally, including the new regression tests (Mouse_Back_And_Forward_Buttons_Navigate_The_History, Mouse_Back_Button_Press_Does_Not_Reach_The_Control_Under_The_Pointer, Browse_Back_Keeps_The_Active_Pane, Derived_Type_Entries_Stay_Visible_When_The_DerivedTypes_Node_Is_Expanded, Enter_Activates_The_Selected_Analyzer_Node, Delete_Removes_The_Selected_Top_Level_Analyzer_Node, Analyze_Promotes_An_Analyzer_Result_Row_To_A_Top_Level_Entry, Analyze_Is_Hidden_For_A_Top_Level_Analyzer_Row).

Written by an AI agent (Claude) on Christoph's behalf.

DerivedTypesEntryNode.Filter reported Recurse, but the cascade's
Recurse handling force-loads the entry's lazy children and hides the
entry when all of them are hidden. A leaf derived type has no children,
so every entry under "Derived Types" ended up hidden, and the hiding
propagated up the whole derived chain. The WPF tree showed these
entries as matches; Match restores that and also keeps the entries'
children lazy instead of eagerly scanning the assembly list for each
level of the chain.

Assisted-by: Claude:claude-fable-5:Claude Code
Avalonia 12 treats plain Enter/Space on a ListBoxItem as selection
input: the container marks the KeyDown handled before it bubbles, so
SharpTreeView.OnKeyDown never saw the keys and its activation handling
(navigate to the member from an analyzer row, toggle a checkable row)
was dead. Override ShouldTriggerSelection -- the extension point added
for this in Avalonia 12 -- to suppress the selection trigger exactly
for the case OnKeyDown activates instead: a single selected row that
is the row the key landed on. Multi-row selections keep the default
collapse-to-focused-row behaviour.

Assisted-by: Claude:claude-fable-5:Claude Code
@christophwille christophwille changed the title Fix three Avalonia UI regressions: mouse navigation, derived types, Enter activation Fix four Avalonia UI regressions: mouse navigation, derived types, Enter activation, Delete Aug 21, 2026
WPF translated XButton1/XButton2 into BrowseBack/BrowseForward
commands by itself, so the WPF frontend got the behaviour for free
and the buttons never reached the control under the pointer as a
click. Avalonia has no such translation and KeyBinding cannot express
pointer buttons, so only Alt+Left / Alt+Right survived the migration.
MainWindow now swallows the X-button press while it tunnels (Dock
would otherwise activate the pane under the pointer, AvaloniaEdit
would focus the editor or toggle a folding marker) and routes the
release to the existing DockWorkspace navigation commands.

Navigating also no longer moves the active pane to the editor: the
history target is usually the already-active tab, and Dock's
ActiveDockable setter re-runs InitActiveDockable -> SetFocusedDockable
even for an unchanged value, so re-activating it only moved the
focus. WPF's ActiveTabPage setter was a no-op for the same value.

Assisted-by: Claude:claude-fable-5:Claude Code
The WPF SharpTreeView bound ApplicationCommands.Delete at class level, so
Delete deleted the top-level selection of any tree whose nodes opt in via
CanDelete/Delete -- which is how a top-level analyzer entry was removed
from the Analyzer pane. The Avalonia tree never received that binding;
only the assembly list pane carried a hand-rolled Delete handler for
assemblies, so the analyzer pane lost the key entirely even though its
nodes still implement the deletion overrides.

Moving the gesture back into SharpTreeView restores it for every tree
and lets the pane-specific handler (with its own reselect logic) go.

Assisted-by: Claude:claude-fable-5:Claude Code
@christophwille
christophwille force-pushed the fix/ui-regressions-4027-4028-4030 branch from 71b732f to 9132a09 Compare August 22, 2026 08:20
The port dropped IMemberTreeNode from AnalyzerEntityTreeNode, so the
member-based context-menu entries (Analyze, Copy name, ...) no longer
recognised analyzer rows and a result row could not be promoted to a
top-level entry. Top-level rows keep the entry hidden: re-analysing
them is a no-op, and Remove is the entry for those rows.

Assisted-by: Claude:claude-fable-5:Claude Code
@christophwille christophwille changed the title Fix four Avalonia UI regressions: mouse navigation, derived types, Enter activation, Delete Fix five Avalonia UI regressions: mouse navigation, derived types, Enter, Delete, Analyze in the Analyzer pane Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Enter" key now does nothing in Analyzer pane Derived types do not shown in tree. Mouse4 and Mouse5 no longer work as back and forward.

2 participants