From e90a3dc666b93710bd50582e579f651e718986e7 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 6 Apr 2025 11:35:45 +0200 Subject: [PATCH] Fix view selection running out of sync with list selection when view isn't focused When rerendering a view at the end of a refresh, we call HandleFocus only if the view has the focus. This is so that we rerender the main view for the new selection. What was missing here is to update the view selection from the list selection if the view doesn't have the focus, so that the selection is painted properly. Normally this is not relevant because you don't see the selection if another side panel has the focus; however, you do see it as an inactive selection when e.g. a popup is shown, in which case it does matter. This will become more important when we introduce section headers for commits, because in that case the view selection needs to change when the working copy state changes from normal to rebasing or vice versa, even if the list selection stays the same. The changed test submodule/reset.go shows how this was wrong before: when entering the submodule again after resetting, there is a refresh which keeps the same branch selected as before (master); however, since the branches panel is not focused, the view didn't notice and kept thinking that the detached head is selected (which it isn't, you can tell by running the test in sandbox mode and focusing the branches panel at the end: you'll see that master is selected). So the change in this commit fixes that. --- pkg/gui/context/list_context_trait.go | 2 ++ pkg/gui/context/simple_context.go | 3 +++ pkg/gui/types/context.go | 2 +- pkg/gui/view_helpers.go | 7 +++++++ pkg/integration/tests/submodule/reset.go | 4 ++-- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pkg/gui/context/list_context_trait.go b/pkg/gui/context/list_context_trait.go index 1c059fb4f..25616af0a 100644 --- a/pkg/gui/context/list_context_trait.go +++ b/pkg/gui/context/list_context_trait.go @@ -26,6 +26,8 @@ type ListContextTrait struct { func (self *ListContextTrait) IsListContext() {} func (self *ListContextTrait) FocusLine() { + self.Context.FocusLine() + // Doing this at the end of the layout function because we need the view to be // resized before we focus the line, otherwise if we're in accordion mode // the view could be squashed and won't how to adjust the cursor/origin. diff --git a/pkg/gui/context/simple_context.go b/pkg/gui/context/simple_context.go index 579f975e6..db8160ea0 100644 --- a/pkg/gui/context/simple_context.go +++ b/pkg/gui/context/simple_context.go @@ -54,6 +54,9 @@ func (self *SimpleContext) HandleFocusLost(opts types.OnFocusLostOpts) { } } +func (self *SimpleContext) FocusLine() { +} + func (self *SimpleContext) HandleRender() { if self.handleRenderFunc != nil { self.handleRenderFunc() diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index eea207360..8a9bbf25b 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -105,6 +105,7 @@ type Context interface { HandleFocus(opts OnFocusOpts) HandleFocusLost(opts OnFocusLostOpts) + FocusLine() HandleRender() HandleRenderToMain() } @@ -173,7 +174,6 @@ type IListContext interface { ViewIndexToModelIndex(int) int ModelIndexToViewIndex(int) int - FocusLine() IsListContext() // used for type switch RangeSelectEnabled() bool RenderOnlyVisibleLines() bool diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 624d6e25f..bf83fd7f3 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -136,5 +136,12 @@ func (gui *Gui) postRefreshUpdate(c types.Context) { if gui.currentViewName() == c.GetViewName() { c.HandleFocus(types.OnFocusOpts{}) + } else { + // The FocusLine call is included in the HandleFocus method which we + // call for focused views above; but we need to call it here for + // non-focused views to ensure that an inactive selection is painted + // correctly, and that integration tests see the up to date selection + // state. + c.FocusLine() } } diff --git a/pkg/integration/tests/submodule/reset.go b/pkg/integration/tests/submodule/reset.go index 6f78d974f..5cd6d58aa 100644 --- a/pkg/integration/tests/submodule/reset.go +++ b/pkg/integration/tests/submodule/reset.go @@ -107,8 +107,8 @@ var Reset = NewIntegrationTest(NewIntegrationTestArgs{ // submodule has been hard reset to the commit the parent repo specifies t.Views().Branches().Lines( - Contains("HEAD detached").IsSelected(), - Contains("master"), + Contains("HEAD detached"), + Contains("master").IsSelected(), ) // empty commit is gone