From: Alan Third <alan@idiocy.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: netjune@outlook.com, 38731@debbugs.gnu.org
Subject: bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
Date: Sat, 28 Dec 2019 11:20:13 +0000 [thread overview]
Message-ID: <20191228112013.GA93177@breton.holly.idiocy.org> (raw)
In-Reply-To: <83v9q0omn9.fsf@gnu.org>
On Sat, Dec 28, 2019 at 10:54:50AM +0200, Eli Zaretskii wrote:
> > Date: Fri, 27 Dec 2019 19:06:52 +0000
> > From: Alan Third <alan@idiocy.org>
> > Cc: netjune@outlook.com, 38731@debbugs.gnu.org
> >
> > The actual problem is that if there is a face that’s to extend to the
> > end of the line (for example with global-hl-line-mode) then
> > expose_area asks draw_glyphs to draw glyph 0 at x coordinate 0, even
> > though in this case there is horizontal scrolling in effect that means
> > glyph 0 should be at a negative x coordinate.
> >
> > In my case I could see that row->x in expose_area was set to -42 but
> > expose_area called draw_glyphs with an x parameter of 0. This offset
> > the glyphs on the screen by 42 pixels. I could see this both in
> > debugging printfs and by actually measuring the difference between the
> > cursor and the equivalent text as drawn on the screen.
>
> You are saying that, when the window is hscrolled, the glyphs in the
> glyph row start with the glyph for the very first character of the
> physical line in this case? IOW, if the line's text is "abcdef", then
> row->glyphs[TEXT_AREA] is the glyph for the character 'a', even though
> the line is hscrolled?
>
> This shouldn't happen, because display_line, the function which
> produces glyphs in glyph rows, starts producing the glyphs at the
> first one that is actually visible, thus taking the hscroll into
> account. See the code in display_line that follows this comment:
>
> /* Move over display elements that are not visible because we are
> hscrolled. This may stop at an x-position < first_visible_x
> if the first glyph is partially visible or if we hit a line end. */
> if (it->current_x < it->first_visible_x + x_incr)
Ah! I have misunderstood what exactly expose_area is doing.
The first visible glyph is a tab character, width ~64 pixels, which is
only partially visible. It should start 42 pixels to the left of the
window. expose_area calls draw_glyphs with an x coordinate of 0, which
draws the entire tab instead of only the visible portion.
It’s pretty simple to manually step through the two sides of the big
if in expose_area and show that with the same input (except for
row->fill_line_p) they will start drawing the line at different x
coordinates.
A minimal, and possibly correct, fix is:
modified src/xdisp.c
@@ -33491,7 +33491,7 @@ expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
if (area == TEXT_AREA && row->fill_line_p)
/* If row extends face to end of line write the whole line. */
- draw_glyphs (w, 0, row, area,
+ draw_glyphs (w, row->x, row, area,
0, row->used[area],
DRAW_NORMAL_TEXT, 0);
else
> So if in your case you get a glyph row with all the characters,
> including those which are scrolled out of the viewport, then something
> is wrong where the glyph row is prepared, not where it is displayed.
> Specifically, when the window is hscrolled, display_line is called
> again to produce the glyphs starting from the first visible glyph.
> Perhaps in this case the NS display machinery uses a stale glyph row,
> from before the hscrolling?
I’m 100% sure the NS code is being passed bad coordinates.
This isn’t just a problem when scrolling to the end of the line. If
the window is horizontally scrolled and you move the cursor onto
another line, the line that was previously wrong corrects itself and
the line with the pointer on it now draws wrong. So it’s possible to
move the pointer between two lines and have them jump left and right.
Also the incorrectly drawn line doesn’t necessarily match any
previously displayed line. If we had some cached glyph row I wouldn’t
expect that to happen.
--
Alan Third
next prev parent reply other threads:[~2019-12-28 11:20 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <a0dc5800-db7e-4091-b385-e2c888f9472b@Spark>
2019-12-24 10:43 ` bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line HaiJun Zhang
2019-12-24 15:50 ` Eli Zaretskii
2019-12-24 16:42 ` HaiJun Zhang
2019-12-26 12:59 ` Alan Third
2019-12-26 13:24 ` HaiJun Zhang
2019-12-26 17:29 ` Eli Zaretskii
2019-12-27 14:35 ` Alan Third
2019-12-27 16:26 ` bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731) Alan Third
2019-12-27 17:17 ` Eli Zaretskii
2019-12-27 19:06 ` Alan Third
2019-12-28 8:54 ` Eli Zaretskii
2019-12-28 11:20 ` Alan Third [this message]
2019-12-28 18:27 ` Eli Zaretskii
2019-12-29 10:46 ` Alan Third
2019-12-30 4:55 ` HaiJun Zhang
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191228112013.GA93177@breton.holly.idiocy.org \
--to=alan@idiocy.org \
--cc=38731@debbugs.gnu.org \
--cc=eliz@gnu.org \
--cc=netjune@outlook.com \
/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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).