diff --git a/Terminal.Gui/Views/Selectors/FlagSelector.cs b/Terminal.Gui/Views/Selectors/FlagSelector.cs
index 932e396f8b..5ebbf00b4d 100644
--- a/Terminal.Gui/Views/Selectors/FlagSelector.cs
+++ b/Terminal.Gui/Views/Selectors/FlagSelector.cs
@@ -7,7 +7,7 @@ namespace Terminal.Gui.Views;
// Item HotKey - Focus item. Activate (Toggle) item. Do NOT Accept.
// Focused:
// Space key - Activate (Toggle) focused item. Do NOT Accept.
-// Enter key - Activate (Toggle) and Accept the focused item.
+// Enter key - Accept. Do NOT Toggle.
// HotKey - No-op.
// Item HotKey - Focus item, Activate (Toggle), and do NOT Accept.
@@ -60,6 +60,11 @@ public FlagSelector ()
///
protected override bool ConsumeDispatch => true;
+ ///
+ /// FlagSelector does not toggle on Enter — Enter only accepts.
+ ///
+ protected override bool ActivateOnAccept => false;
+
// Set by OnHandlingHotKey to suppress the Activate that DefaultHotKeyHandler
// fires after RaiseHandlingHotKey. Checked and cleared in GetDispatchTarget.
private bool _suppressHotKeyActivate;
diff --git a/Terminal.Gui/Views/Selectors/SelectorBase.cs b/Terminal.Gui/Views/Selectors/SelectorBase.cs
index 1fc8423991..3bdefd2dca 100644
--- a/Terminal.Gui/Views/Selectors/SelectorBase.cs
+++ b/Terminal.Gui/Views/Selectors/SelectorBase.cs
@@ -159,6 +159,13 @@ public SelectorStyles Styles
}
}
+ ///
+ /// Gets whether the Accept command (Enter key) should also invoke Activate (toggle/select) before accepting.
+ /// The default is (OptionSelector behavior). Override to return
+ /// to accept without activating (FlagSelector behavior).
+ ///
+ protected virtual bool ActivateOnAccept => true;
+
///
protected override bool OnAccepting (CommandEventArgs args)
{
@@ -167,7 +174,7 @@ protected override bool OnAccepting (CommandEventArgs args)
return true;
}
- // Per spec: Enter key should Activate AND Accept for both OptionSelector and FlagSelector.
+ // Per spec: Enter key should Activate AND Accept for OptionSelector.
// Enter only triggers Command.Accept (View's default key binding), so invoke Activate here
// before continuing with Accept processing. Also handle direct programmatic Accept invocations
// (Binding is null) by activating the currently focused checkbox.
@@ -178,7 +185,7 @@ protected override bool OnAccepting (CommandEventArgs args)
bool directAccept = args.Context?.Binding is null && Focused is CheckBox;
- if (!enterFromCheckBox && !directAccept)
+ if ((!enterFromCheckBox && !directAccept) || !ActivateOnAccept)
{
return args.Context?.Binding switch
{
diff --git a/Tests/UnitTestsParallelizable/Views/FlagSelectorTests.cs b/Tests/UnitTestsParallelizable/Views/FlagSelectorTests.cs
index 4b05d78796..25c2627d4a 100644
--- a/Tests/UnitTestsParallelizable/Views/FlagSelectorTests.cs
+++ b/Tests/UnitTestsParallelizable/Views/FlagSelectorTests.cs
@@ -151,6 +151,36 @@ public void FlagSelector_Command_HotKey_WhenFocused_Does_Not_Change_Value ()
Assert.Equal (valueBefore, flagSelector.Value);
}
+ // Copilot - Sonnet 4
+ // Per issue: Enter should just accept, not toggle, in FlagSelector
+ [Fact]
+ public void FlagSelector_Enter_Does_Not_Toggle_Value ()
+ {
+ using FlagSelector flagSelector = new ();
+
+ CheckBox firstCheckBox = flagSelector.SubViews.OfType ().ElementAt (0);
+ flagSelector.SetFocus ();
+ Assert.True (flagSelector.HasFocus);
+
+ SelectorStyles? valueBefore = flagSelector.Value;
+
+ int selectorValueChanged = 0;
+ flagSelector.ValueChanged += (_, _) => selectorValueChanged++;
+
+ int acceptingFired = 0;
+ flagSelector.Accepting += (_, _) => acceptingFired++;
+
+ // Press Enter on the focused checkbox
+ firstCheckBox.NewKeyDownEvent (Key.Enter);
+
+ // Value should NOT change (Enter does not toggle in FlagSelector)
+ Assert.Equal (0, selectorValueChanged);
+ Assert.Equal (valueBefore, flagSelector.Value);
+
+ // But Accepting should fire
+ Assert.Equal (1, acceptingFired);
+ }
+
// Tests for FlagSelector
[Fact]
public void GenericInitialization_ShouldSetDefaults ()