From 53334eebcfbbd985a933bc96fded995c631004cc Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Tue, 5 May 2026 22:10:23 +0200 Subject: [PATCH] ResourceLinkGenerator opts out of Ctrl+Click explicitly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AvaloniaEdit's TextEditorOptions.RequireControlModifierForHyperlinkClick only flows into its *built-in* LinkElementGenerator (via the IBuiltinElementGenerator.FetchOptions hook the editor calls from UpdateBuiltinElementGeneratorsFromOptions). Subclasses added to ElementGenerators by hand inherit whatever the parameterless base constructor sets — which is "true" — so the editor-level flag flipped in DecompilerTextView didn't actually reach our generator. Assisted-by: Claude:claude-opus-4-7:Claude Code --- ILSpy.Tests/Commands/HelpCommandTests.cs | 14 ++++++++++++++ ILSpy/Commands/ResourceLinkGenerator.cs | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/ILSpy.Tests/Commands/HelpCommandTests.cs b/ILSpy.Tests/Commands/HelpCommandTests.cs index c1e9e3963..a0bf07eab 100644 --- a/ILSpy.Tests/Commands/HelpCommandTests.cs +++ b/ILSpy.Tests/Commands/HelpCommandTests.cs @@ -132,6 +132,20 @@ public class HelpCommandTests licenseTab.Text.Should().Contain("Permission is hereby granted"); } + [Test] + public void ResourceLinkGenerator_Does_Not_Require_Ctrl_Modifier_For_Click() + { + // AvaloniaEdit's TextEditorOptions.RequireControlModifierForHyperlinkClick only + // propagates to the *built-in* LinkElementGenerator via IBuiltinElementGenerator. + // FetchOptions; user-added subclasses keep whatever the base parameterless ctor sets + // (default true). The About-page generator must opt out explicitly so its links + // activate on a plain click. + var gen = new ResourceLinkGenerator( + "MIT License", + new System.Uri("resource:license.txt")); + gen.RequireControlModifierForClick.Should().BeFalse(); + } + [AvaloniaTest] public async Task Decompiler_Editor_Activates_Hyperlinks_Without_Ctrl_Modifier() { diff --git a/ILSpy/Commands/ResourceLinkGenerator.cs b/ILSpy/Commands/ResourceLinkGenerator.cs index 4ab920147..7c62f8539 100644 --- a/ILSpy/Commands/ResourceLinkGenerator.cs +++ b/ILSpy/Commands/ResourceLinkGenerator.cs @@ -36,6 +36,13 @@ namespace ILSpy.Commands : base(new Regex(Regex.Escape(phrase))) { this.target = target ?? throw new ArgumentNullException(nameof(target)); + // AvaloniaEdit's TextEditorOptions.RequireControlModifierForHyperlinkClick only + // propagates to its *built-in* LinkElementGenerator (via the + // IBuiltinElementGenerator.FetchOptions hook the editor invokes from + // UpdateBuiltinElementGeneratorsFromOptions). User-added subclasses inherit + // whatever the parameterless base constructor set (default true), so we have to + // opt out explicitly here. + RequireControlModifierForClick = false; } protected override Uri GetUriFromMatch(Match match) => target;