bug#81585: 31.0.91 and 32.0.50; Crash on macos hiding header-line with pixel-scroll-precision-mode

Alan Third <[email protected]>
Newsgroups gmane.emacs.bugs
Message-ID <[email protected]>
On Wed, Aug 12, 2026 at 11:24:46AM +0100, Alan Third wrote:
> On Wed, Aug 12, 2026 at 12:58:46AM -0400, Corwin Kerr wrote:
> > > Honestly, I don't know if redisplay should be sending negative values
> > > to *_scroll_run, but just in case I've tried changing copyRect:to: so
> > > it can handle negative values.
> > The patch stops the crash for me as well. Thanks!
> > 
> > The crash might be a symptom of another bug because some other
> > scrolling weirdness occurs.
> > 
> > In both Emacs 30.2 and the patched build with the same minimal.el:
> > > file minimal.el
> > > ;; -*- lexical-binding: t; -*-
> > > (pixel-scroll-precision-mode)
> > > (defun toggle-header ()
> > >   (interactive)
> > >   (setq header-line-format
> > > 	(unless header-line-format "Pixel scroll, then press C-t to crash")))
> > > (toggle-header)
> > > (bind-key "C-t" #'toggle-header)
> > 
> > 1. emacs -Q --load minimal.el
> > 2. C-x 2 and click in lower buffer.
> > 3. Scroll in lower buffer.
> >    Let x = fractional part of number of lines scrolled.
> > 4. C-t to toggle off header-line.
> > 5. The lower x fraction of header-line covers the lower x fraction of the 
> >    mode-line of the upper buffer.
> > (And in Emacs 32.0.50 if mode-line-invisible-mode is on, the bottom
> > line of the buffer text is covered.)

Does the attached fix it?
-- 
Alan Third
v2-0001-Fix-crash-in-NS-scroll-code-bug-81585.patch (text/plain, 2 KB)
From 0fb078de845a0ef9a3e7d6cd1616a6399d90d474 Mon Sep 17 00:00:00 2001
From: Alan Third <[email protected]>
Date: Sun, 9 Aug 2026 19:22:57 +0100
Subject: [PATCH v2] Fix crash in NS scroll code (bug#81585)

There may be a problem in the core redisplay code that it can send
negative values to the *_scroll_run functions, but this fixes the
problem at the actual scrolling code.

* src/nsterm.m (ns_scroll_run) ([EmacsView copyRect:to:]): If the
destination is negative, fix the source and destination to keep
everything positive.
---
 src/nsterm.m | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 20967b7581f..f53eafd5841 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2857,7 +2857,6 @@ Hide the window (X11 semantics)
 
   NSTRACE ("ns_scroll_run");
 
-  /* begin copy from other terms */
   /* Get frame-relative bounding box of the text display area of W,
      without mode lines.  Include in this box the left and right
      fringe of W.  */
@@ -2875,6 +2874,15 @@ Hide the window (X11 semantics)
 	height = bottom_y - from_y;
       else
 	height = run->height;
+
+      /* If the destination is off the top of the current window, don't
+	 draw over the window above.  */
+      if (to_y < y) {
+	int d = y - to_y;
+	height -= d;
+	to_y += d;
+	from_y += d;
+      }
     }
   else
     {
@@ -2885,7 +2893,6 @@ Hide the window (X11 semantics)
       else
 	height = run->height;
     }
-  /* end copy from other terms */
 
   if (height == 0)
       return;
@@ -9316,6 +9323,16 @@ - (void)copyRect:(NSRect)srcRect to:(NSPoint)dest
   NSTRACE_RECT ("Source", srcRect);
   NSTRACE_POINT ("Destination", dest);
 
+  /* If the destination is off the top of the pixel buffer, fix the
+     source and destination to copy only to y = 0.  */
+  if (dest.y < 0)
+    {
+      int d = dest.y;
+      dest.y = 0;
+      srcRect.origin.y -= d;
+      srcRect.size.height += d;
+    }
+
   NSRect dstRect = NSMakeRect (dest.x, dest.y, NSWidth (srcRect),
                                NSHeight (srcRect));
 
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.