From 2576258ba30f61dbb6c82e8313d3b685b1ed5647 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 9 Nov 2025 19:33:50 +0100 Subject: [PATCH 1/2] Cleanup: remove unnecessary code The method is only called from keybinding handlers, so the view must be focused already, otherwise the binding wouldn't have been dispatched to it. --- pkg/gui/controllers/list_controller.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/gui/controllers/list_controller.go b/pkg/gui/controllers/list_controller.go index f5f7c9289..c935854b7 100644 --- a/pkg/gui/controllers/list_controller.go +++ b/pkg/gui/controllers/list_controller.go @@ -101,10 +101,6 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error { rangeAfter := list.IsSelectingRange() after := list.GetSelectedLineIdx() - if err := self.pushContextIfNotFocused(); err != nil { - return err - } - // doing this check so that if we're holding the up key at the start of the list // we're not constantly re-rendering the main view. cursorMoved := before != after From 8114943cb16f56d85ea0f0467139e8537ac50e34 Mon Sep 17 00:00:00 2001 From: Raphaele Salvatore Licciardo Date: Fri, 7 Nov 2025 06:36:25 +0100 Subject: [PATCH 2/2] Fix page navigation scroll behavior to keep cursor at top/bottom When pressing '.' (next page) or ',' (previous page), the selection now stays at the bottom or top of the viewport respectively, instead of being centered which caused items to scroll off. If the selection is not already on the last/first line of the view, '.'/',' moves it there without scrolling. This implements a special case for page navigation as suggested by the maintainer in issue #5017, keeping the cursor position consistent with user expectations for page-based navigation. Fixes #5017 Co-authored-by: Stefan Haller --- pkg/gui/controllers/list_controller.go | 52 +++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/pkg/gui/controllers/list_controller.go b/pkg/gui/controllers/list_controller.go index c935854b7..f772fb3d8 100644 --- a/pkg/gui/controllers/list_controller.go +++ b/pkg/gui/controllers/list_controller.go @@ -123,11 +123,59 @@ func (self *ListController) handleLineChangeAux(f func(int), change int) error { } func (self *ListController) HandlePrevPage() error { - return self.handleLineChange(-self.context.GetViewTrait().PageDelta()) + return self.handlePageChange(-self.context.GetViewTrait().PageDelta()) } func (self *ListController) HandleNextPage() error { - return self.handleLineChange(self.context.GetViewTrait().PageDelta()) + return self.handlePageChange(self.context.GetViewTrait().PageDelta()) +} + +func (self *ListController) handlePageChange(delta int) error { + list := self.context.GetList() + view := self.context.GetViewTrait() + + before := list.GetSelectedLineIdx() + + viewPortStart, viewPortHeight := view.ViewPortYBounds() + beforeViewIdx := self.context.ModelIndexToViewIndex(before) + afterViewIdx := beforeViewIdx + delta + newModelIndex := self.context.ViewIndexToModelIndex(afterViewIdx) + + if delta < 0 { + // Previous page: keep selection at top of viewport + indexAtTopOfPage := self.context.ViewIndexToModelIndex(viewPortStart) + if before != indexAtTopOfPage { + // If the selection isn't already at the top of the page, move it there without scrolling + list.MoveSelectedLine(indexAtTopOfPage - before) + } else { + // Otherwise, move the selection by one page and scroll + list.MoveSelectedLine(newModelIndex - before) + + linesToScroll := afterViewIdx - viewPortStart + if linesToScroll < 0 { + view.ScrollUp(-linesToScroll) + } + } + } else { + // Next page: keep selection at bottom of viewport + indexAtBottomOfPage := self.context.ViewIndexToModelIndex(viewPortStart + viewPortHeight - 1) + if before != indexAtBottomOfPage { + // If the selection isn't already at the bottom of the page, move it there without scrolling + list.MoveSelectedLine(indexAtBottomOfPage - before) + } else { + // Otherwise, move the selection by one page and scroll + list.MoveSelectedLine(newModelIndex - before) + + linesToScroll := afterViewIdx - (viewPortStart + viewPortHeight - 1) + if linesToScroll > 0 { + view.ScrollDown(linesToScroll) + } + } + } + + self.context.HandleFocus(types.OnFocusOpts{}) + + return nil } func (self *ListController) HandleGotoTop() error {