Subject: Re: bug#72331: 29.4; Modifying horizontal-scroll-bar does not fully work (MacOS only)

From: Gerd Möllmann <[email-masked]>
Date: Mon, 05 Aug 2024 15:43:21 +0200

Eli Zaretskii <[email-masked]> writes:

>> Date: Sat, 27 Jul 2024 22:10:06 -0700
>> From:  Jared Finder via "Bug reports for GNU Emacs,
>>  the Swiss army knife of text editors" <[email-masked]>
>> 
>> Directly modifying the variable horizontal-scroll-bar on MacOS doesn't
>> show a scroll bar unless the frame also has the horizontal-scroll-bars
>> frame  parameter set.  This only happens on MacOS, on Linux and Windows
>> everything behaves as I would expect.
>> 
>> To reproduce, define the following function:
>> 
>> (defun bug-report-toggle-buffer-horizontal-scroll-bar ()
>>    "Like `toggle-scroll-bar', but for just the current buffer.
>> And for horizontal scroll bars.  I guess it's acutally very
>> different."
>>    (interactive)
>>    (setq horizontal-scroll-bar (if horizontal-scroll-bar nil 'bottom))
>>    (set-window-buffer (selected-window) (current-buffer)))
>> 
>> Then run M-x bug-report-toggle-buffer-horizontal-scroll-bar repeatedly
>> and observe that on MacOS space gets reserved for the horizontal scroll
>> bar but no scroll bar is rendered.  Finally, run M-x
>> horizontal-scroll-bar-mode and observe that now the horizontal scroll
>> bar is properly shown and hidden.
>> 
>> I also tested this on master and observed the same behavior.
>
> Thanks.
>
> Could some macOS user please look into this?

Same for vertical-scroll-bar, BTW. From reading the code and setting a
breakpoint in ns_set_horizontal_scroll_bar, I'd say it's the definition
of these macros in nsterm.h:

  /* Compute pixel size for vertical scroll bars.  */
  #define NS_SCROLL_BAR_WIDTH(f)						\
    (FRAME_HAS_VERTICAL_SCROLL_BARS (f)					\
     ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0			\
             ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)				\
             : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)))	\
     : 0)

  /* Compute pixel size for horizontal scroll bars.  */
  #define NS_SCROLL_BAR_HEIGHT(f)						\
    (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)					\
     ? rint (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0			\
             ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f)				\
             : (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)))	\
     : 0)

Both check FRAME_HAS_H/V_SCROLL_BARS which in this case results in width
or height being 0, which is a bit small.

A change like the one below makes the horizontal scroll bar visible with
Jared's test function.

1 file changed, 4 insertions(+), 1 deletion(-)
src/nsterm.m | 5 ++++-

modified   src/nsterm.m
@@ -5167,7 +5167,10 @@ Function modeled after x_draw_glyph_string_box ().
   window_box (window, ANY_AREA, &window_x, 0, &window_width, 0);
   left = window_x;
   width = window_width;
-  height = NS_SCROLL_BAR_HEIGHT (f);
+  //  height = NS_SCROLL_BAR_HEIGHT (f);
+  height = rint (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
+		 ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f)
+		 : (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)));
   top = WINDOW_SCROLL_BAR_AREA_Y (window);
 
   r = NSMakeRect (left, top, width, height);

If that's the right thing (plus a corresponding change for vertical
scroll bars) I don't know without studying the code and docs, and what
other platforms do.

Maybe Po Lu can help (CC'd).