From: martin rudalics <rudalics@gmx.at>
To: 34569@debbugs.gnu.org
Subject: bug#34569: 26.1.90; Zero wide scroll bars
Date: Tue, 19 Feb 2019 10:08:15 +0100 [thread overview]
Message-ID: <5C6BC77F.6020104@gmx.at> (raw)
Setting 'scroll-bar-width' to zero can have unforeseen consequences
depending on the toolkit used. To reproduce with Emacs 26 run a Lucid
or Motif build as
emacs - Q --eval "(setq default-frame-alist '((minibuffer . nil) (vertical-scroll-bars . nil) (scroll-bar-width . 0)))"
Then evaluate
(set-frame-parameter nil 'vertical-scroll-bars 'left)
Emacs aborts with a
X protocol error: BadValue (integer parameter out of range for operation) on protocol request 12
GTK builds do not abort but have for example a scroll bar on the left
overwrite buffer text. A similar bug can be produced with horizontal
scroll bars.
It's not entirely trivial to explain why Emacs aborts here. The cause
is a combination of contrived logic and the absence of a more cautious
initial setting for X builds. For starters, frame.h says that
/* Width that a scroll bar in frame F should have, if there is one.
Measured in pixels.
If scroll bars are turned off, this is still nonzero. */
#define FRAME_CONFIG_SCROLL_BAR_WIDTH(f) ((f)->config_scroll_bar_width)
This comment is, unfortunately, wrong because in our example
'frame-notice-user-settings'
(setq parms (frame-parameters frame-initial-frame))
'frame-parameters' creates a zero entry for the 'scroll-bar-width'
frame parameter since our initial frame has no scroll bars and
'frame-notice-user-settings' passes that parameter on to 'make-frame'.
In frame.c this subsequently bypasses both checks in
x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
int unit = FRAME_COLUMN_WIDTH (f);
if (NILP (arg))
{
x_set_scroll_bar_default_width (f);
...
}
else if (RANGED_INTEGERP (1, arg, INT_MAX)
&& XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
{
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
...
since ARG is zero which is neither nil nor a ranged integer > 0. So
we continue with the initially zero FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
and try to make a window with a zero wide scroll bar produced from the
initial w->scroll_bar_width (which equals -1) and these definitions in
window.h:
/* Width that a scroll bar in window W should have, if there is one.
Measured in pixels. If scroll bars are turned off, this is still
nonzero. */
#define WINDOW_CONFIG_SCROLL_BAR_WIDTH(W) \
(W->scroll_bar_width >= 0 \
? W->scroll_bar_width \
: FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (W)))
/* Width of scroll bar area in window W, measured in pixels. */
#define WINDOW_SCROLL_BAR_AREA_WIDTH(W) \
(WINDOW_HAS_VERTICAL_SCROLL_BAR (W) \
? WINDOW_CONFIG_SCROLL_BAR_WIDTH (W) \
: 0)
Here the first comment is wrong again, WINDOW_CONFIG_SCROLL_BAR_WIDTH
is zero and X is rightfully annoyed.
The easisest fix I could come up with is switching the two branches of
the if clause in x_set_scroll_bar_width thusly:
void
x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
int unit = FRAME_COLUMN_WIDTH (f);
if (RANGED_INTEGERP (1, arg, INT_MAX)
&& XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
{
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
if (FRAME_X_WINDOW (f))
adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
SET_FRAME_GARBAGED (f);
}
else
{
x_set_scroll_bar_default_width (f);
if (FRAME_X_WINDOW (f))
adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
SET_FRAME_GARBAGED (f);
}
XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
}
But maybe someone has a better idea.
Note that Windows builds sidestep the problem by unconditionally doing
/* By default, make scrollbars the system standard width and height. */
FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
in 'x-create-frame'.
Note also that with emacs 27.1 the bug can be produced more directly by
including
(setq default-frame-alist '((vertical-scroll-bars . nil) (scroll-bar-width . 0)))
in the early-init.el and then enabling vertical scroll bars. The
indirection via 'frame-notice-user-settings' is not needed there.
Thanks, martin
next reply other threads:[~2019-02-19 9:08 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-19 9:08 martin rudalics [this message]
2019-02-23 9:51 ` bug#34569: 26.1.90; Zero wide scroll bars Eli Zaretskii
2019-02-23 14:01 ` martin rudalics
2019-02-23 16:49 ` Eli Zaretskii
2019-02-24 8:43 ` martin rudalics
2019-02-24 16:09 ` Eli Zaretskii
2019-02-24 18:31 ` martin rudalics
2019-02-24 19:04 ` Eli Zaretskii
2019-02-25 10:13 ` martin rudalics
2019-02-26 16:07 ` Eli Zaretskii
2019-03-04 10:14 ` martin rudalics
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5C6BC77F.6020104@gmx.at \
--to=rudalics@gmx.at \
--cc=34569@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.