Subject: Re: bug#42452: 27.0.91; hollow box cursor sometimes leaves artifacts

From: Radon Rosborough <[email-masked]>
Date: Sun, 28 Mar 2021 15:21:47 -0700

I've been affected by this issue for some years, only on Linux to my
recollection, across multiple Emacs versions (26, 27, 28), and with
the same behavior described by Aaron.

After some time using Emacs---the trigger is unclear---Emacs enters a
state where the hollow box cursor is drawn incorrectly. Specifically,
the lines of the hollow box cursor are drawn with a thickness of 2
pixels rather than 1 pixel. To make things a bit more confusing, only
the bottom, left, and right lines of the hollow box experience this. I
believe this is because the rectangle drawing is clipped to the
current glyph row (though not the current glyph column), so the extra
pixels on the top fall outside the clip region and get dropped.

Here are screenshots showing the behavior at a pixel level, for
comparison: https://imgur.com/a/L84ekeS

The relevant code is in the function x_draw_hollow_cursor, here:
https://github.com/emacs-mirror/emacs/blob/96dd0196c28bc36779584e47fffcca433c9309cd/src/xterm.c#L9234

By compiling Emacs with debugging symbols and stepping through
x_draw_hollow_cursor with GDB, I verified that all the arguments
passed to XDrawRectangle (via x_draw_rectangle) are identical between
an instance of Emacs exhibiting the bug and one that is fine.

I've attached a patch that appears to resolve the problem for me.

What we are doing in this patch is overriding the graphics context
configuration so that line_width is set to 1, rather than the default
of 0. There is somewhat detailed documentation from xlib on the
meaning of the line_width argument, and how to set it via XChangeGC,
here: https://tronche.com/gui/x/xlib/GC/manipulating.html

In short, a line_width of 0 means "draw a line of width 1 pixel, but
use a device-dependent algorithm to do so, which may have higher
performance". Unlike setting line_width to 1, setting it to 0 does not
make any guarantees about the exact pixels that are rendered as part
of the line. Apparently, there is a bug in the X server's
device-dependent graphics code, or perhaps the graphics driver, which
causes the "device-dependent algorithm" to be buggy under some
circumstances, and draw a line of width 2 when a line of width 1 is
requested.

Other interesting behavior: If I set line_width explicitly to 2 rather
than to 1, then the graphical artifacts mentioned in the initial bug
report occur unconditionally, every time a hollow box cursor is
rendered.

Would this change be appropriate to include in Emacs?