unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
       [not found] <a0dc5800-db7e-4091-b385-e2c888f9472b@Spark>
@ 2019-12-24 10:43 ` HaiJun Zhang
  2019-12-24 15:50   ` Eli Zaretskii
  0 siblings, 1 reply; 15+ messages in thread
From: HaiJun Zhang @ 2019-12-24 10:43 UTC (permalink / raw)
  To: Emanuel, Berg, via, Bug, reports, for, GNU, Emacs, 38731


[-- Attachment #1.1: Type: text/plain, Size: 3757 bytes --]

In GNU Emacs 27.0.50 (build 1, x86_64-apple-darwin17.7.0, NS appkit-1561.61 Version 10.13.6 (Build 17G10021))
 of 2019-12-23 built on jundeMac
Repository revision: 3ee8ee8476fef2a5e8159f7597e36e0953295ce2
Repository branch: mod
Windowing system distributor ‘Apple', version 10.3.1561
System Description: Mac OS X 10.13.6

Reproduction steps:
1. emacs -Q
2. open the test file in attachment(a.cpp)
3. M-x toggle-truncate-lines
4. M-x global-hl-line
5. shrink the width of the emacs window so that the longest line(#12) can’t be fully visible
6. go to line 12 and press C-e to goto end of line
7. the cursor is not at the end of line and you can’t move the cursor to end of line



Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Truncate long lines enabled
Global Hl-Line mode enabled
next-line: End of buffer
delete-backward-char: Text is read-only
funcall-interactively: End of buffer [3 times]

Configured using:
 ‘configure —with-ns '--enable-locallisppath=/Library/Application
 Support/Emacs/${version}/site-lisp:/Library/Application
 Support/Emacs/site-lisp’ --with-modules --disable-acl
 —without-makeinfo CFLAGS=-O2’

Configured features:
RSVG GLIB NOTIFY KQUEUE GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS
MODULES THREADS PDUMPER LCMS2 GMP

Important settings:
  value of $LANG: zh_CN.UTF-8
  locale-coding-system: utf-8-unix

Major mode: C++//l

Minor modes in effect:
  global-hl-line-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t
  abbrev-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message rmc puny dired dired-loaddefs
format-spec rfc822 mml mml-sec password-cache epa derived epg epg-config
gnus-util rmail rmail-loaddefs text-property-search time-date subr-x seq
byte-opt gv bytecomp byte-compile cconv mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047
rfc2045 ietf-drums mm-util mail-prsvr mail-utils cus-start cus-load
hl-line vc-git diff-mode easy-mmode cc-mode cc-fonts easymenu cc-guess
cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs
cl-loaddefs cl-lib china-util tooltip eldoc electric uniquify ediff-hook
vc-hooks lisp-float-type mwheel term/ns-win ns-win ucs-normalize
mule-util term/common-win tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch timer
select scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite charscript charprop case-table epa-hook
jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice loaddefs
button faces cus-face macroexp files text-properties overlay sha1 md5
base64 format env code-pages mule custom widget hashtable-print-readable
backquote threads kqueue cocoa ns lcms2 multi-tty make-network-process
emacs)

Memory information:
((conses 16 80300 14394)
 (symbols 48 9922 0)
 (strings 32 24946 2210)
 (string-bytes 1 886243)
 (vectors 16 14651)
 (vector-slots 8 229697 4904)
 (floats 8 23 40)
 (intervals 56 259 0)
 (buffers 1000 12))


[-- Attachment #1.2: Type: text/html, Size: 5390 bytes --]

[-- Attachment #2: a.cpp --]
[-- Type: application/octet-stream, Size: 255 bytes --]

#include <stdio.h>

int main(int argc, char **argv)
{
	printf("hello world\n");

	if(1)
	{
		if(1)
		{
			if(a long long variable -name fffffffffffff ) {
				// printf("------------ very long line .......", foobar())

				foo();
			}
		}
	}

	return 0;
}

^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
  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
  0 siblings, 2 replies; 15+ messages in thread
From: Eli Zaretskii @ 2019-12-24 15:50 UTC (permalink / raw)
  To: HaiJun Zhang; +Cc: 38731

> Date: Tue, 24 Dec 2019 18:43:34 +0800
> From: HaiJun Zhang <netjune@outlook.com>
> 
> 1. emacs -Q
> 2. open the test file in attachment(a.cpp)
> 3. M-x toggle-truncate-lines
> 4. M-x global-hl-line
> 5. shrink the width of the emacs window so that the longest line(#12) can’t be fully visible
> 6. go to line 12 and press C-e to goto end of line
> 7. the cursor is not at the end of line and you can’t move the cursor to end of line

I cannot reproduce this.

Note how in the video you produced, moving cursor across the
right-most part of the line after C-e shows characters from the end of
the line.  IOW, Emacs does know it is at EOL, it's just that the
window display somehow was not updated.

I think this is Darwin-specific display problem.





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
  2019-12-24 15:50   ` Eli Zaretskii
@ 2019-12-24 16:42     ` HaiJun Zhang
  2019-12-26 12:59     ` Alan Third
  1 sibling, 0 replies; 15+ messages in thread
From: HaiJun Zhang @ 2019-12-24 16:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 38731

[-- Attachment #1: Type: text/plain, Size: 435 bytes --]

在 2019年12月24日 +0800 PM11:50,Eli Zaretskii <eliz@gnu.org>,写道:
> Note how in the video you produced, moving cursor across the
> right-most part of the line after C-e shows characters from the end of
> the line. IOW, Emacs does know it is at EOL, it's just that the
> window display somehow was not updated.
>
> I think this is Darwin-specific display problem.

Yes. I just tried on linux. It is ok on linux.


[-- Attachment #2: Type: text/html, Size: 989 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
  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
  1 sibling, 2 replies; 15+ messages in thread
From: Alan Third @ 2019-12-26 12:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: HaiJun Zhang, 38731

On Tue, Dec 24, 2019 at 05:50:36PM +0200, Eli Zaretskii wrote:
> > Date: Tue, 24 Dec 2019 18:43:34 +0800
> > From: HaiJun Zhang <netjune@outlook.com>
> > 
> > 1. emacs -Q
> > 2. open the test file in attachment(a.cpp)
> > 3. M-x toggle-truncate-lines
> > 4. M-x global-hl-line
> > 5. shrink the width of the emacs window so that the longest line(#12) can’t be fully visible
> > 6. go to line 12 and press C-e to goto end of line
> > 7. the cursor is not at the end of line and you can’t move the cursor to end of line
> 
> I cannot reproduce this.
> 
> Note how in the video you produced, moving cursor across the
> right-most part of the line after C-e shows characters from the end of
> the line.  IOW, Emacs does know it is at EOL, it's just that the
> window display somehow was not updated.
> 
> I think this is Darwin-specific display problem.

I may be entirely wrong but after looking into this I think the NS
code is being passed bad information.

It may be because we only ever draw from expose_frame: I have a test
branch that draws directly into an offscreen bitmap, not relying on
expose_frame, and it draws correctly despite using almost the same
logic.

In ns_draw_glyph_string I can see that s->x is correctly set to 136
when the backtrace doesn’t contain expose_frame, but 178 when it does.

The issue seems to rely on the combination of truncate lines mode,
global hl mode and tabs on the left. The number of tabs seems to make
no difference, the offset remains the same, and replacing tabs with
spaces displays correctly.

Any thoughts on how to debug this further?
-- 
Alan Third





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
  2019-12-26 12:59     ` Alan Third
@ 2019-12-26 13:24       ` HaiJun Zhang
  2019-12-26 17:29       ` Eli Zaretskii
  1 sibling, 0 replies; 15+ messages in thread
From: HaiJun Zhang @ 2019-12-26 13:24 UTC (permalink / raw)
  To: Eli Zaretskii, Alan Third; +Cc: 38731

[-- Attachment #1: Type: text/plain, Size: 412 bytes --]

在 2019年12月26日 +0800 PM8:59,Alan Third <alan@idiocy.org>,写道:
>
> The issue seems to rely on the combination of truncate lines mode,
> global hl mode and tabs on the left. The number of tabs seems to make
> no difference, the offset remains the same, and replacing tabs with
> spaces displays correctly.
>
It seems that it happens when the leftmost tab char stays across the left border.

[-- Attachment #2: Type: text/html, Size: 789 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
  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
  1 sibling, 1 reply; 15+ messages in thread
From: Eli Zaretskii @ 2019-12-26 17:29 UTC (permalink / raw)
  To: Alan Third; +Cc: netjune, 38731

> Date: Thu, 26 Dec 2019 12:59:17 +0000
> From: Alan Third <alan@idiocy.org>
> Cc: HaiJun Zhang <netjune@outlook.com>, 38731@debbugs.gnu.org
> 
> In ns_draw_glyph_string I can see that s->x is correctly set to 136
> when the backtrace doesn’t contain expose_frame, but 178 when it does.

Isn't it the other way around?  The correct display should start at a
larger X coordinate.  Or maybe I don't understand what is s->x in this
context, i.e. what glyph string is S.

> The issue seems to rely on the combination of truncate lines mode,
> global hl mode and tabs on the left. The number of tabs seems to make
> no difference, the offset remains the same, and replacing tabs with
> spaces displays correctly.
> 
> Any thoughts on how to debug this further?

A TAB is displayed by a stretch glyph, so maybe start looking there.





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: 27.0.50; Unexpected redisplay behaviour. Cursor can’t be moved to end of line.
  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
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Third @ 2019-12-27 14:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: netjune, 38731

[-- Attachment #1: Type: text/plain, Size: 1236 bytes --]

On Thu, Dec 26, 2019 at 07:29:21PM +0200, Eli Zaretskii wrote:
> > Date: Thu, 26 Dec 2019 12:59:17 +0000
> > From: Alan Third <alan@idiocy.org>
> > Cc: HaiJun Zhang <netjune@outlook.com>, 38731@debbugs.gnu.org
> > 
> > In ns_draw_glyph_string I can see that s->x is correctly set to 136
> > when the backtrace doesn’t contain expose_frame, but 178 when it does.
> 
> Isn't it the other way around?  The correct display should start at a
> larger X coordinate.  Or maybe I don't understand what is s->x in this
> context, i.e. what glyph string is S.

Unless I’m somehow seeing a different problem (I haven’t watched the
video) the problem occurs when the buffer is scrolled horizontally,
and we should be able to see the end of the line point is on. However,
the line is drawn off the right side of the frame.

I’ve attached an image that I hope illustrates it better than I can
describe. You can see the glyph seen in the cursor is a /, and is the
first character of the text. The end of the line is at the b in
foobar.

So the text is drawn at too large an X coordinate, although the glyph
seen in the cursor is always correct.

Anyway, I’ll have a dig around and see if I can find where it’s going
wrong.

-- 
Alan Third

[-- Attachment #2: bug38731 screenshot --]
[-- Type: image/png, Size: 14448 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-27 14:35         ` Alan Third
@ 2019-12-27 16:26           ` Alan Third
  2019-12-27 17:17             ` Eli Zaretskii
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Third @ 2019-12-27 16:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: netjune, 38731

* src/xdisp.c (expose_area): When the face extends to the end of the
line calculate the first glyph to be redrawn rather than assuming it
starts at the first glyph in the row.
---
src/xdisp.c | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/xdisp.c b/src/xdisp.c
index 3080f8920a..42a86a1d12 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -33489,30 +33489,30 @@ expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
   struct glyph *last;
   int first_x, start_x, x;
 
+  /* Set START_X to the window-relative start position for drawing glyphs of
+     AREA.  The first glyph of the text area can be partially visible.
+     The first glyphs of other areas cannot.  */
+  start_x = window_box_left_offset (w, area);
+  x = start_x;
+  if (area == TEXT_AREA)
+    x += row->x;
+
+  /* Find the first glyph that must be redrawn.  */
+  while (first < end
+         && x + first->pixel_width < r->x)
+    {
+      x += first->pixel_width;
+      ++first;
+    }
+
   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,
-		 0, row->used[area],
+    draw_glyphs (w, x - start_x, row, area,
+		 first - row->glyphs[area], row->used[area],
 		 DRAW_NORMAL_TEXT, 0);
   else
     {
-      /* Set START_X to the window-relative start position for drawing glyphs of
-	 AREA.  The first glyph of the text area can be partially visible.
-	 The first glyphs of other areas cannot.  */
-      start_x = window_box_left_offset (w, area);
-      x = start_x;
-      if (area == TEXT_AREA)
-	x += row->x;
-
-      /* Find the first glyph that must be redrawn.  */
-      while (first < end
-	     && x + first->pixel_width < r->x)
-	{
-	  x += first->pixel_width;
-	  ++first;
-	}
-
-      /* Find the last one.  */
+      /* Find the last glyph to be redrawn.  */
       last = first;
       first_x = x;
       /* Use a signed int intermediate value to avoid catastrophic
-- 
2.24.0


-- 
Alan Third





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  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
  0 siblings, 1 reply; 15+ messages in thread
From: Eli Zaretskii @ 2019-12-27 17:17 UTC (permalink / raw)
  To: Alan Third; +Cc: netjune, 38731

> Date: Fri, 27 Dec 2019 16:26:20 +0000
> From: Alan Third <alan@idiocy.org>
> Cc: netjune@outlook.com, 38731@debbugs.gnu.org
> 
> * src/xdisp.c (expose_area): When the face extends to the end of the
> line calculate the first glyph to be redrawn rather than assuming it
> starts at the first glyph in the row.

Thanks, but can you please explain the rationale behind these changes?
I'm mildly worried why this is done in generic code, whereas the
problem was Darwin-specific.





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-27 17:17             ` Eli Zaretskii
@ 2019-12-27 19:06               ` Alan Third
  2019-12-28  8:54                 ` Eli Zaretskii
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Third @ 2019-12-27 19:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: netjune, 38731

On Fri, Dec 27, 2019 at 07:17:03PM +0200, Eli Zaretskii wrote:
> > Date: Fri, 27 Dec 2019 16:26:20 +0000
> > From: Alan Third <alan@idiocy.org>
> > Cc: netjune@outlook.com, 38731@debbugs.gnu.org
> > 
> > * src/xdisp.c (expose_area): When the face extends to the end of the
> > line calculate the first glyph to be redrawn rather than assuming it
> > starts at the first glyph in the row.
> 
> Thanks, but can you please explain the rationale behind these changes?
> I'm mildly worried why this is done in generic code, whereas the
> problem was Darwin-specific.

The problem only appears to be Darwin specific as the NS port uses the
expose functionality for all its drawing.

I have a scratch NS branch that draws to an offscreen bitmap using the
normal redisplay routines and it looks fine despite using the same
logic in the NS specific code.

This issue doesn’t show up anywhere else because it’s a rare situation
and will only appear when expose is used to redraw the frame, which
makes it even rarer. If we could force Emacs to redraw using expose on
X or Windows I’m certain the same problem would be observed.

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.

-- 
Alan Third





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-27 19:06               ` Alan Third
@ 2019-12-28  8:54                 ` Eli Zaretskii
  2019-12-28 11:20                   ` Alan Third
  0 siblings, 1 reply; 15+ messages in thread
From: Eli Zaretskii @ 2019-12-28  8:54 UTC (permalink / raw)
  To: Alan Third; +Cc: netjune, 38731

> 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)

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?





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-28  8:54                 ` Eli Zaretskii
@ 2019-12-28 11:20                   ` Alan Third
  2019-12-28 18:27                     ` Eli Zaretskii
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Third @ 2019-12-28 11:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: netjune, 38731

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





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-28 11:20                   ` Alan Third
@ 2019-12-28 18:27                     ` Eli Zaretskii
  2019-12-29 10:46                       ` Alan Third
  0 siblings, 1 reply; 15+ messages in thread
From: Eli Zaretskii @ 2019-12-28 18:27 UTC (permalink / raw)
  To: Alan Third; +Cc: netjune, 38731

> Date: Sat, 28 Dec 2019 11:20:13 +0000
> From: Alan Third <alan@idiocy.org>
> Cc: netjune@outlook.com, 38731@debbugs.gnu.org
> 
> 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

This change LGTM, thanks.  If it solves your problem, then we can
close this issue.





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-28 18:27                     ` Eli Zaretskii
@ 2019-12-29 10:46                       ` Alan Third
  2019-12-30  4:55                         ` HaiJun Zhang
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Third @ 2019-12-29 10:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: netjune, 38731-done

On Sat, Dec 28, 2019 at 08:27:35PM +0200, Eli Zaretskii wrote:
> > Date: Sat, 28 Dec 2019 11:20:13 +0000
> > From: Alan Third <alan@idiocy.org>
> > Cc: netjune@outlook.com, 38731@debbugs.gnu.org
> > 
> > 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
> 
> This change LGTM, thanks.  If it solves your problem, then we can
> close this issue.

Thanks. Pushed to emacs-27.
-- 
Alan Third





^ permalink raw reply	[flat|nested] 15+ messages in thread

* bug#38731: [PATCH] Calculate first glyph to be redrawn when exposing (bug#38731)
  2019-12-29 10:46                       ` Alan Third
@ 2019-12-30  4:55                         ` HaiJun Zhang
  0 siblings, 0 replies; 15+ messages in thread
From: HaiJun Zhang @ 2019-12-30  4:55 UTC (permalink / raw)
  To: Eli Zaretskii, Alan Third; +Cc: 38731-done

[-- Attachment #1: Type: text/plain, Size: 1025 bytes --]

It is fixed. Thanks.

Can you see another bug #38727. It is also Darwin-specific. It causes flicker.

在 2019年12月29日 +0800 PM6:46,Alan Third <alan@idiocy.org>,写道:
> On Sat, Dec 28, 2019 at 08:27:35PM +0200, Eli Zaretskii wrote:
> > > Date: Sat, 28 Dec 2019 11:20:13 +0000
> > > From: Alan Third <alan@idiocy.org>
> > > Cc: netjune@outlook.com, 38731@debbugs.gnu.org
> > >
> > > 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
> >
> > This change LGTM, thanks. If it solves your problem, then we can
> > close this issue.
>
> Thanks. Pushed to emacs-27.
> --
> Alan Third

[-- Attachment #2: Type: text/html, Size: 2146 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-12-30  4:55 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [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
2019-12-28 18:27                     ` Eli Zaretskii
2019-12-29 10:46                       ` Alan Third
2019-12-30  4:55                         ` HaiJun Zhang

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).