Skip to content

Keep line-mode point and markers put across a resize - #702

Merged
dakra merged 1 commit into
mainfrom
fix/699-line-mode-resize-point
Sep 18, 2026
Merged

dakra merged 1 commit into
mainfrom
fix/699-line-mode-resize-point

Conversation

@dakra

@dakra dakra commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Fixes #699.

In line mode, after seq 1000, the first window resize threw point into
the scrollback and the next one threw it to the top of the buffer. Two
independent defects, both reproduced and measured in live sessions.

Point relocated to the middle of the window

The line-count branch of ghostel--anchor-window walked back from
point-max by the full screen-line count. That is correct only when
point-max begins a trailing empty row, which is what the renderer
normally leaves. Line mode trims that tail, so point-max ends at the
end of the prompt row, the walk-back lands one line too high, and the
prompt row falls below the window bottom. set-window-start sets
force_start, and redisplay answers an invisible point by moving it to
the middle of the window rather than scrolling.

Measured in a 22-row window with the prompt on buffer line 1002:

window-start line point ends on
980 (before) 990
981 (after) 1002, the prompt

Graphical frames use the exact pixel anchor and were unaffected. The
fallback runs on terminal frames, on Emacs 28, and whenever the pixel
measurement is unavailable.

Point, window start and mark collapsing to position 1

The renderer pins saved markers from inside commitResize, but a FULL
redraw erases the buffer before that. bufferPosToPin derives a screen
row with line-number-at-pos, so against an empty buffer every saved
position maps to row 0 and is restored as buffer position 1. Line mode
passes FULL on every redraw, so any resize hit it. Graphical frames were
affected too.

With the mark parked in the scrollback and a width resize applied:

mode mark before mark after
line 3878 1
semi-char 3878 3878

Point usually survived because ghostel--line-mode-restore puts it back
from its input-region offset. Once point is outside that region, which
is exactly where the first defect left it, nothing restores it.

Known ceiling

Skipping the pin restores raw buffer offsets, so a marker on a row that
rewraps during a width resize drifts by the rewrap delta instead of
following its row. Pinning accurately would mean moving the full-redraw
clear below the pin, which starts running scrollback eviction on a path
where it currently never executes. Eviction ordering here has produced
two silent desyncs before, so that trade is not worth an occasional
few-character drift. The reported collapse to the buffer start is gone.

Tests

Two native regression tests, both confirmed to fail with the fixes
reverted and the module and byte-code rebuilt:

  • a full redraw carrying a pending width resize, the combination line
    mode produces and the one case the existing position-preservation
    family did not cover
  • anchoring a buffer whose last row has no trailing newline

make -j8 all passes from cleared test stamps. Both symptoms were also
re-checked live, on terminal and graphical frames.

Two independent defects moved point out of the input region in line
mode, both visible after resizing a window over a long scrollback.

The line-count branch of `ghostel--anchor-window' walked back from
`point-max' by the full screen-line count.  That fits only when
`point-max' begins a trailing empty row, which line mode removes when it
trims the renderer's blank tail, so the last row landed one line below
the window and redisplay answered a forced `window-start' by relocating
point to the middle of the window.  The branch runs on terminal frames
and wherever the pixel measurement is unavailable.

The renderer pinned saved markers from inside `commitResize', after a
FULL redraw had already erased the buffer.  `bufferPosToPin' derives a
screen row from the buffer, so every window point, window start and mark
mapped to row 0 and came back as buffer position 1.  Line mode sets FULL
on every redraw, so any resize hit it.  Skipping the pin on an erased
buffer restores the raw offsets, which drift only when a row rewraps.

Closes #699
@dakra
dakra force-pushed the fix/699-line-mode-resize-point branch from 0cf5efc to 67f43b3 Compare September 18, 2026 09:15
@dakra
dakra merged commit 67f43b3 into main Sep 18, 2026
27 checks passed
@dakra
dakra deleted the fix/699-line-mode-resize-point branch September 18, 2026 09:16

This branch was successfully deployed

1 active deployment
github-pages — 67f43b3e Deployed Sep 18, 2026 by dakra via deploy #200
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.

line-mode: cursor placement when window configuration change

1 participant