Skip to content

Track scroll-conservatively per-buffer to avoid clobbering local values#45

Open
brettatoms wants to merge 1 commit into
jdtsmith:mainfrom
brettatoms:fix-scroll-conservatively-clobber
Open

Track scroll-conservatively per-buffer to avoid clobbering local values#45
brettatoms wants to merge 1 commit into
jdtsmith:mainfrom
brettatoms:fix-scroll-conservatively-clobber

Conversation

@brettatoms

Copy link
Copy Markdown

ultra-scroll raises scroll-conservatively to 101 during a scroll and restores the prior value on idle, tracking the saved value in a global variable (ultra-scroll--scroll-conservatively-orig).

scroll-conservatively can be set buffer-locally, and some modes set it to >=100 on purpose. Tracking the saved value globally leaks it across buffers:

  1. Scroll in a buffer where scroll-conservatively is <100 (e.g. the global default). --prepare-to-scroll saves that low value and raises to 101.
  2. Scroll in a buffer whose buffer-local scroll-conservatively is >=100. --prepare-to-scroll skips the save (nothing to raise), but --end-scroll still runs the restore and writes the stale low value into this buffer, overwriting its buffer-local >=100 setting.

Once lowered, a forced redisplay while point is off-screen makes Emacs recenter, yanking the window by a large amount.

I hit this with the ghostel terminal emulator, which sets scroll-conservatively to 101 buffer-locally so its decoupled point does not trigger a recenter. After scrolling a normal buffer and then the terminal, the terminal's value was reset to the global default, and the next redraw (a spinner timer) jumped the window several pages toward the top.

Fix

Make ultra-scroll--scroll-conservatively-orig buffer-local and use nil to mean "not raised in this buffer", so --end-scroll only restores when this buffer's value was actually raised. The save in --prepare-to-scroll already only runs when the value is <100, so it doubles as the sentinel. The seed in the mode-enable body is no longer needed and is removed.

Testing

  • Byte-compiles with no new warnings.
  • In emacs -Q: a <100 buffer is raised to 101 during scroll and restored after; a >=100 buffer is left untouched with no nil-comparison error; a >=100 buffer is not affected by a prior scroll in a <100 buffer.

ultra-scroll raises `scroll-conservatively' to 101 during a scroll and
restores the prior value on idle, but tracked the saved value globally.
Since `scroll-conservatively' can be buffer-local (some modes pin it
>=100), this leaks across buffers: a scroll in a <100 buffer saves that
low value, then a scroll in a >=100 buffer skips the save but still runs
the restore, clobbering its local setting.  Once lowered, a redisplay
with point off-screen recenters, causing a large jump.

Make the saved value buffer-local and use nil for "not raised here", so
the restore only fires when this buffer's value was actually raised.
@jdtsmith

Copy link
Copy Markdown
Owner

Thanks. Can you test this in scenarios where the same buffer is shown in multiple windows and the non-active window gets scrolled?

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.

2 participants